OpenCV+MFC study notes (2): OpenCV binarizes images and displays them adaptively in Picture Control

In the previous we have completed reading pictures in Picture Control through OpenCV and displaying them adaptively . Next, we naturally need to process the read pictures. After processing, we naturally think of looking at the effect. So today's note is to process the image through OpenCV grayscale and display the result.

Description of Requirement

as the picture shows,

S1, the button above opens the resource manager, loads a picture to the Picture Control adaptive display on the left;

S2, the button below processes the loaded image through OpenCV grayscale, and then adaptively displays it on the Picture Control on the right;

S3, adjust the threshold through the scroll bar below, observe and perceptually recognize the different effects of grayscale under different thresholds.

 

grayscale processing

According to my understanding in Novice Village, if the last step of digital image preprocessing is the binarization of the image, then the first step is the grayscale of the image.

The purpose of image grayscale processing is simply to digitize the image to facilitate technology development and analysis.

Each pixel of a grayscale image only needs one byte to store the grayscale value (also known as intensity value, brightness value), and the grayscale range is 0-255. Grayscale images usually measure each pixel in a single electromagnetic wave spectrum (such as visible light) obtained by the brightness. Grayscale images for display are usually stored with a non-linear scale of 8 bits per sample pixel, which allows for 256 grayscale levels. This kind of precision is just enough to avoid visible banding distortion, and it is very easy to program.

Binarization

The binarization of the image is to set the gray value of the pixels on the image to 0 or 255, which will make the whole image appear obvious black and white effect. In digital image processing, binary image occupies a very important position. Binarization of image greatly reduces the amount of data in the image, thus highlighting the outline of the target.

From a programming point of view, it can be understood as converting the complex pixel information in the image into binary data that is either 0 or 1, or 1 or 0, which is convenient for our calculations.

//第二个按钮的响应事件代码
void CmyMFCDlg::OnBnClickedBinary()
{
	// TODO: 在此添加控件通知处理程序代码
	Mat dst_mat;//左边载入的图片对象

	//S1,灰度处理
	cv::cvtColor(src_mat, dst_mat, cv::COLOR_BGR2GRAY);

	//S2,开始二值化
	//第二个和第三个参数是阀值,决定了二值化显示的效果.如果设定不正确可能图像显不出来	
	cv::threshold(dst_mat, dst_mat, 127, 255, cv::THRESH_BINARY);

	//S3,展示图片处理后的效果
	DrawMat(dst_mat, IDC_STATIC_RESULT);
}

Briefly speaking about the binarization method cv::threshold, there are a total of 5 parameters, pay attention to the 3rd and 5th parameters.

The third is the threshold, and the fifth is the threshold algorithm type.

How to understand the threshold here? For example, if our camera takes a photo with a fixed angle and parameters, the resulting image may be different due to changes in the light source (such as changes in sunlight, such as light and dark). We can't binarize the picture simply and roughly, which may lead to the loss of pixel information that should be 1, but collect and enlarge the pixel information that should be 0.

Most of the time, in the industrial assembly line environment, since the light source and angle are relatively fixed, the threshold value can be set through the experience value after repeated debugging to set an optimal threshold value and threshold algorithm type. But when the light source environment changes a lot, this threshold requires more energy to calculate.

Let's take a look at the same picture, the picture effect at different thresholds:

 

 

Seeing that the change of the slider leads to the change of the threshold, it also leads to the change of the effect after binarization, which values ​​are useful, which values ​​will calculate what results, which will have different thresholds to bring different results.

Do you know how powerful this threshold is? 

As for the threshold algorithm type of the fifth parameter of cv::threshold, it also complements the threshold value. These are relatively comprehensive and easy to consult on the Internet, so I won’t say more.

Finally, post the third requirement mentioned at the beginning of the article. The image processed by OpenCV should be displayed in Picture Control.

//参数1:要显示的图对象  
//参数2:Picture Control控件的ID
void CmyMFCDlg::DrawMat(cv::Mat& img, UINT nID)
{
	CRect rect;
	cv::Mat imgTmp;

	GetDlgItem(nID)->GetClientRect(&rect);  // 获取控件大小
	cv::resize(img, imgTmp, cv::Size(rect.Width(), rect.Height()));// 缩放Mat并备份
	// 再重新灰度处理下,备用 
	switch (imgTmp.channels())
	{
	case 1:
		cv::cvtColor(imgTmp, imgTmp, CV_GRAY2BGRA); // GRAY单通道
		break;
	case 3:
		cv::cvtColor(imgTmp, imgTmp, CV_BGR2BGRA);  // BGR三通道
		break;
	default:
		break;
	}
	int pixelBytes = imgTmp.channels() * (imgTmp.depth() + 1); // 计算一个像素多少个字节
	// 制作bitmapinfo(数据头)
	BITMAPINFO bitInfo;
	bitInfo.bmiHeader.biBitCount = 8 * pixelBytes;
	bitInfo.bmiHeader.biWidth = imgTmp.cols;
	bitInfo.bmiHeader.biHeight = -imgTmp.rows;
	bitInfo.bmiHeader.biPlanes = 1;
	bitInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
	bitInfo.bmiHeader.biCompression = BI_RGB;
	bitInfo.bmiHeader.biClrImportant = 0;
	bitInfo.bmiHeader.biClrUsed = 0;
	bitInfo.bmiHeader.biSizeImage = 0;
	bitInfo.bmiHeader.biXPelsPerMeter = 0;
	bitInfo.bmiHeader.biYPelsPerMeter = 0;
	// Mat.data + bitmap数据头 -> MFC
	CDC* pDC = GetDlgItem(nID)->GetDC();
	::StretchDIBits(
		pDC->GetSafeHdc(),
		0, 0, rect.Width(), rect.Height(),
		0, 0, rect.Width(), rect.Height(),
		imgTmp.data,
		&bitInfo,
		DIB_RGB_COLORS,
		SRCCOPY
	);
	ReleaseDC(pDC);
}

As a double novice in MFC and image processing, it is difficult to learn, but there will always be gains over time, so come on!

Guess you like

Origin blog.csdn.net/laolitou_1024/article/details/124509445