对象分割和检测
先对图像进行预处理:
- 噪声消除
- 光消除
- 二值化
再对图像进行分割:
- 连接组件
- 寻找轮廓
噪声消除以及光消除
这里需要两张图片,一张是包括物体和背景的,另外一张只有背景。
#include<opencv2/opencv.hpp>
#include<opencv2/highgui.hpp>
using namespace cv;
Mat removeLight(Mat img, Mat pattern, int method) {
Mat aux;
// if method is normalization
if (method == 1) {
// require change image to 32float for division
Mat img32, pattern32;
img.convertTo(img32, CV_32F);
pattern.convertTo(pattern32, CV_32F);
// divide the image by the pattern
aux = 1 - (img32 / pattern32);
// convert 8 bit format and scale
aux.convertTo(aux, CV_8U, 255);
}
else {
aux = pattern - img;
}
return aux;
}
Mat calculateLightPattern(Mat img) {
Mat pattern;
// Basic and effective way to calculate the light pattern from one image
blur(img, pattern, Size(img.cols / 3, img.cols / 3));
return pattern;
}
int main() {
// decrease noise
Mat things = imread("C:/Users/86177/Desktop/opencv c++/目标追踪/image/things(1).jpg");
Mat back = imread("C:/Users/86177/Desktop/opencv c++/目标追踪/image/back(1).jpg");
Mat img_noise;
Mat aux1, pattern, aux2;
aux1 = removeLight(things, back, 1);
aux2 = removeLight(things, back, 2);
pattern = calculateLightPattern(things);
Mat results = removeLight(things, pattern, 1);
medianBlur(things, img_noise, 3);
namedWindow("remove noise", WINDOW_AUTOSIZE);
imshow("remove noise", things);
imshow("remove light1", aux1);
imshow("remove light2", aux2);
imshow("remove calculateLight", results);
waitKey(0);
return 0;
}
效果图:
如果没有背景图,也可以用更好的算法取学习各个部分出现在不同区域的图像背景。这里先采用一种简单的应用于输入图像的大内核尺寸的模糊技术,这种技术在光学字符识别(OCR)中经常使用,可以对图像中的光模式进行近似,已在上述代码中实现。