一、图像增强代码的 C++ 实现
在博客 一种基于Opencv文档图像增强算法的实现
提到了一种基于 C++ OpenCV 的图像增强算法,
并添加了辅助增强算法使效果更加明显.
1. PC 端实现代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69
| #include <opencv2/opencv.hpp>
using namespace std; using namespace cv;
void GammaCorrection(Mat& src, Mat& dst, float fGamma) { CV_Assert(src.data); CV_Assert(src.depth() != sizeof(uchar)); unsigned char lut[256]; for (int i = 0; i < 256; i++) { lut[i] = saturate_cast<uchar>(pow((float)(i / 255.0), fGamma) * 255.0f); }
dst = src.clone(); const int channels = dst.channels(); switch (channels) { case 1: {
MatIterator_<uchar> it, end; for (it = dst.begin<uchar>(), end = dst.end<uchar>(); it != end; it++) *it = lut[(*it)];
break; } case 3: {
MatIterator_<Vec3b> it, end; for (it = dst.begin<Vec3b>(), end = dst.end<Vec3b>(); it != end; it++) { (*it)[0] = lut[((*it)[0])]; (*it)[1] = lut[((*it)[1])]; (*it)[2] = lut[((*it)[2])]; } break; } } }
int main(int argc, char** argv) { string addr = "C:\\Users\\64975\\Desktop\\test1.jpg"; Mat image = imread(addr); Mat src = image.clone(); src.convertTo(src, CV_32FC3, 1.0 / 255); Mat gauss; Mat dst = src.clone(); GaussianBlur(src, gauss, Size(101, 101), 0); dst = src / gauss; dst.convertTo(dst, CV_8UC3, 255); Mat ss; Mat matGamma; ss = dst.clone(); GammaCorrection(ss, matGamma, 1.5); imwrite("C:\\Users\\64975\\Desktop\\test1_out.jpg", matGamma); return 0; }
|
2. 图片处理前后对比

上述图片中, 左侧为未处理图片, 右侧为处理后的图片.
可以明显发现,
由于光线所造成的阴影部分以及背景颜色在处理后都可以忽略不计,
并且图片中的文字质量仍保证在可辨识的状态.
3.
对处理前后图片的模型识别结果
(注: 图片中文字过多使得检测模型只能检测到部分,
故测试采用文字数较少图片进行测试)

效果不是很明显, 还需要更多的测试来对其图像增强效果进行判断.
为了简便步骤, 这步工作在移植该算法到安卓端后进行.
二、图像增强算法移植安卓
1. 移植过程
Step 1 : 在 xxx/src/main/cpp 文件夹下新建两个文件
image_enhancement.cpp 和 image_enhancement.h
Step 2 : 编写 image_enhancement.cpp 和 image_enhancement.h 文件,
这里为移植的代码.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
|
#ifndef ANDROID_DEMO_IMAGE_ENHANCEMENT_H #define ANDROID_DEMO_IMAGE_ENHANCEMENT_H
#include <opencv2/opencv.hpp>
#include <string> using namespace std;
using namespace cv; void GammaCorrection(Mat &src,Mat &dst, float fGamma); std::string ImageEnhance(std::string addr);
#endif
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
|
#include <opencv2/opencv.hpp> #include <string>
using namespace std; using namespace cv; void GammaCorrection(Mat& src, Mat& dst, float fGamma) { CV_Assert(src.data); CV_Assert(src.depth() != sizeof(uchar)); unsigned char lut[256]; for (int i = 0; i < 256; i++) { lut[i] = saturate_cast<uchar>(pow((float)(i / 255.0), fGamma) * 255.0f); }
dst = src.clone(); const int channels = dst.channels(); switch (channels) { case 1: {
MatIterator_<uchar> it, end; for (it = dst.begin<uchar>(), end = dst.end<uchar>(); it != end; it++) *it = lut[(*it)];
break; } case 3: {
MatIterator_<Vec3b> it, end; for (it = dst.begin<Vec3b>(), end = dst.end<Vec3b>(); it != end; it++) { (*it)[0] = lut[((*it)[0])]; (*it)[1] = lut[((*it)[1])]; (*it)[2] = lut[((*it)[2])]; } break; } } }
std::string ImageEnhance(std::string addr) { Mat image = imread(addr); Mat src = image.clone(); src.convertTo(src, CV_32FC3, 1.0 / 255); Mat gauss; Mat dst = src.clone(); GaussianBlur(src, gauss, Size(101, 101), 0); dst = src / gauss; dst.convertTo(dst, CV_8UC3, 255); Mat ss; Mat matGamma; ss = dst.clone(); GammaCorrection(ss, matGamma, 1.5); return addr; }
|
Step 3 : 在 xxx/src/main/cpp/native.cpp 文件末尾添加函数
为了满足 JNI 的要求, 这里的函数命名都需要严格要求
1 2 3 4 5 6 7
| extern "C" JNIEXPORT jstring JNICALL Java_com_baidu_paddle_lite_demo_ocr_OCRPredictorNative_enhancement(JNIEnv *env, jobject thiz,jstring image_path) { std::string image_path1 = jstring_to_cpp_string(env, image_path); std::string image_out_path1 = ImageEnhance(image_path1); jstring j_string = cpp_string_to_jstring(env, image_out_path1); return j_string; }
|
Step 4 : 在 xxx/src/main/java/xxxxx/OCRPredictorNative.java
文件中添加函数, 作为 Java 调用 C++ 的接口.
1
| protected native String enhancement(String imagePath);
|
Step 5 : 根据需要调用函数处理图像.
2. 编译提示
观察编译结果可能会发现并没有生成有关 image_enhancement 的 .o 文件.
这时就会出现链接文件时找不到 ImageEnhance() 函数.
需要删除 根目录/app/.cxx 和 根目录/app/build 两个文件夹之后再 Make
Build 该项目.
三、存在问题
目前图像增强代码移植安卓失败, 会出现 Assertion failed locateROI
之类的错误. 暂时还没有解决办法.
在初期测试时, 对于文字占比较大的图片虽然识别率不高,
但是能够全部检测到. 但是在最近测试时发现,
模型对于此类图片的检测率只能达到 50 % 甚至更少.
无论使用其他开源模型还是使用官方网页模型以及官方在 PC
上的模型测试都是如此.