An Implementation of Image Enhancement Algorithm Based on Opencv Document


Because the project needs to enhance the document image, that is, to process the fuzzy, dark or uneven document to facilitate subsequent identification. Image enhancement methods are mainly divided into two aspects: spatial domain and frequency domain. Spatial threshold enhancement method, color enhancement, such as: histogram equalization, contrast and gama enhancement, etc.; blur, such as: mean filtering, etc.; sharpening, such as: local standard deviation to achieve contrast enhancement. Frequency domain methods, such as wavelet transform, operate on the transform coefficients of the image in a certain transform domain of the image, and then obtain the image enhancement effect through the inverse transform. Generally speaking, in actual projects, one or more of these methods may be used for image enhancement. The effect of image enhancement is generally very poor. We are more to fuse these algorithms to achieve the effect we want.

1. Image enhancement based on division mode

Suppose we have images A and B, respectively taking pictures of the same scene under different lighting, where A represents the primary color and B represents the mixed color. Then we model the light distribution in this scene to get the calculation formula of the division mode: result color = (primary color/mixed color) *255 .

  • What do you mean specifically?

We analyze the value of each channel and enhance it based on the base color. If the base color value is greater than or equal to the mixed color, the result color is white; if the base color is less than the mixed color, the result will be darker than the base color.

  • Why is this algorithm more suitable for document image enhancement?

We know that document images generally consist of text and background. The text is black and the background is white. If you simply enhance the contrast and the like, it is indeed effective for brighter or darker images, but for documents, this method will make part of the text missing, instead of achieving the effect of enhancement. Image enhancement based on the division mode takes this into consideration. For dark ones, such as fonts, it will become darker, and for bright ones, such as background, it will become brighter.

  • How to achieve it?

The problem specification is images A and B, taking pictures of the same scene in different lighting, then:

Illumination distribution L = A / B

If A and L are known, then B = A / L (B is the result of A de-illuminating)

Here, A represents the picture we need to enhance, and B represents the picture after Gaussian filtering. Then, when we perform A/B, we get an enhanced image. Is not it simple.

2. Implementation based on c++ OpenCV

#include <opencv2/opencv.hpp>

using namespace std;
using namespace cv;

int main(int argc, char** argv)
{
	Mat image = imread("./pic/raw.png");
	//划分算法
	//如果混合色与基色相同则结果色为白色
	//如混合色为白色则结果色为基色不变
	//如混合色为黑色则结果色为白色
	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);
	imshow("dst", dst);
	waitKey();
    
    return 0;
}

Result display:

3. Auxiliary enhancement algorithm

We see that some images are not processed well, such as the first and third lines. There is a lot of black noise in the processed result, so other enhanced algorithms can be used to assist in the follow-up. Here we choose the gamma contrast enhancement algorithm. The specific implementation is as follows:

//Gamma校正 fGamaa=0.45是常用值
void GammaCorrection(Mat& src, Mat& dst, float fGamma)
{
	CV_Assert(src.data);
	// accept only char type matrices
	CV_Assert(src.depth() != sizeof(uchar));
	// build look up table
	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;
	}
	}
}

The complete code is as follows:

#include <opencv2/opencv.hpp>

using namespace std;
using namespace cv;

//Gamma校正 fGamaa=0.45是常用值
void GammaCorrection(Mat& src, Mat& dst, float fGamma)
{
	CV_Assert(src.data);
	// accept only char type matrices
	CV_Assert(src.depth() != sizeof(uchar));
	// build look up table
	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)
{
	Mat image = imread("./pic/raw.jpg");
	划分算法
	//如果混合色与基色相同则结果色为白色
	//如混合色为白色则结果色为基色不变
	//如混合色为黑色则结果色为白色
	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);
	gamma变换
	Mat matGamma;
	GammaCorrection(dst.clone(), matGamma,1.5);
	//显示最终结果
	//namedWindow("Soure", 0);
	namedWindow("dst", 0);

	imshow("Soure", image);
	imshow("dst", matGamma);
	waitKey();
    
    return 0;
}

Reference connection:

Camscanner (scanning almighty king) function analysis and reproduction

Scanning effect image enhancement

Guess you like

Origin blog.csdn.net/wxplol/article/details/112645349