1、背景:
再对输入图像进行直接阈值处理后,会在部分区域出现伪影,而伪影常常会伴随着白噪声,这使得后续对图像的边缘提取会造成一定的困难,因此需要对该部分进行去除。
如下为含有伪影的二值化处理图像、原图:
2、解决方法:
将没有待识别物体的背景图像(光图像shine_back)与含有待识别物体的图像(待处理图像image)进行减法或除法处理。
原理:
减法:
image-shine_back 时,shine_back与image的同时亮光部分像素值会置0,而只有image亮的部分会被保留下来。
除法:
在进行除法操作前,需要将image和shine_back均进行浮点类型转换(此时两个图像的所有像素值均在0~1之间),在除法操作时,为1 - (shine_back/image ),同样shine_back与image的同时亮光部分的像素值会在操作后被置0,而只有image亮的部分会被置1。
3、如何获取背景图
受各种因素影响,有时获取完全相同的纯背景图是比较困难的,此时可以通过设定ROI区域,将输入图像的ROI区域(含有被识别物体的区域)置0即可。
参考代码:
void Quick_func::pre_deal(Mat& image)
{
namedWindow("原图", WINDOW_FREERATIO);
imshow("原图", image);
//去噪点
Mat no_noise;
medianBlur(image, no_noise, 3);
/*namedWindow("去除噪声", WINDOW_FREERATIO);
imshow("去除噪声", no_noise);*/
//灰度化
Mat gray;
cvtColor(image, gray, COLOR_BGR2GRAY);
//二值化
Mat dst;
threshold(gray, dst, 150,255, THRESH_BINARY);
namedWindow("二值化", WINDOW_FREERATIO);
imshow("二值化", dst);
//获取光化背景,即没有物料的背景图
Mat shine_back;
dst.copyTo(shine_back);
int a = 120, b = 800;
int h = gray.rows;
int w = gray.cols;
for (int i = int(h / 2) - b; i < int(h / 2) + b; i++) {
for (int j = int(w/2) - a; j < int(w / 2) + 0.5 * a ; j++){
//灰色图像ROI区域处理
shine_back.at<uchar>(i, j) = 0;
}
}
/*Rect rect(image.cols / 2 - a, image.rows / 2 - b, 1.5 * a, 2 * b);
Mat ROI = dst(rect);
namedWindow("ROI", WINDOW_FREERATIO);
imshow("ROI", ROI);*/
//光背景显示
namedWindow("光背景", WINDOW_FREERATIO);
imshow("光背景", shine_back);
//减法去除伪影
Mat dst3 = dst - shine_back;
namedWindow("减法去除伪影", WINDOW_FREERATIO);
imshow("减法去除伪影", dst3);
//除法去除伪影部分,由于是除法,需要将光背景和二值图像均转化为浮点型数据
Mat dst32, shine_back32;
dst.convertTo(dst32, CV_32F);
shine_back.convertTo(shine_back32, CV_32F);
//定义输出图像
Mat output;
output = 1 - (shine_back32 / dst32);
//再将原浮点型输出转换为整形
output.convertTo(output, CV_8U, 255);
namedWindow("除法去除伪影", WINDOW_FREERATIO);
imshow("除法去除伪影", output);
}
结果: