基于模板匹配布匹瑕疵检测算法实现
1. 算法目的
查阅了不少论文,主流算法是利用Gabor或者其他对纹理极其敏感的算法来实现纹理瑕疵检测的,但是Gabor对于纹理要求较高,对于纹理模糊布匹的检测效果并不好(甚至连明显的破洞也检测不出来),解决薄纱布等纹理模糊布匹的瑕疵检测
2. 算法思想
读取待测图和模板图,对图像进行灰度化处理,处理后的待测图与模板图进行等比例分块,得到的模板图经过扩展与相对应的待测图分块区域进行模板匹配,从而得到各个分块区域的最优匹配结果,将匹配结果进行组合,得到与待测图匹配效果最好的模板图,新的模板图与待测图进行差值运算以及二值化操作,得到瑕疵位置,最终实现瑕疵检测。
附上算法流程图:
附上核心代码:
void Template_match::_template_match(Mat src_mat, Mat mod_mat, int thresh, cv::Mat& spotmat, int xstep, int xextend, int ystep, int yextend)//第四个参数 Mat& spotmat,
{
Rect srcRt, modRt, dstRt;
int xsize = src_mat.cols / xstep + 1;//水平方向步数
int ysize = src_mat.rows / ystep + 1;//垂直方向步数
spotmat = Mat::zeros(src_mat.size(), CV_8UC1);
//#pragma omp parallel for
for (int i = 0; i < xsize; i++)
for (int j = 0; j < ysize; j++)
{
srcRt = Rect(i * xstep, j * ystep, xstep, ystep);//所有可选框(长宽为单步步长)
check_rect(srcRt, src_mat);//判断srcRt是否越界
//modRt = Rect(i*xstep - xextend, j*ystep - yextend, xstep + xextend * 2, ystep + yextend * 2);
modRt = Rect(i * xstep - xextend, 1 * ystep - yextend, xstep + xextend * 2, ystep + yextend * 2);//可选框的带扩展模板图(左右上下各扩展xextend和yextend的大小)
check_rect(modRt, mod_mat);//判断模板图是否越界
dstRt.width = srcRt.width;
dstRt.height = srcRt.height;
dstRt.x = modRt.x;
dstRt.y = modRt.y;
Mat tmat = mod_mat(modRt);//大图像,带扩展
//imshow("result", tmat);
Mat tmpl = src_mat(srcRt);//小图像
//imshow("tmp1", tmpl);
int result_cols = tmat.cols - tmpl.cols + 1;
int result_rows = tmat.rows - tmpl.rows + 1;
int method = TM_SQDIFF;//模板匹配方法
Mat result;
result.create(result_cols, result_rows, CV_32FC1);
matchTemplate(tmat, tmpl, result, method);//模板匹配
double minVal, maxVal;
Point minLoc, maxLoc, matchLoc;
minMaxLoc(result, &minVal, &maxVal, &minLoc, &maxLoc, Mat());
//匹配方法不同,对应匹配点不同
if (method == CV_TM_SQDIFF || method == CV_TM_SQDIFF_NORMED)
{
matchLoc = minLoc;//取最小值的匹配点
}
else
matchLoc = maxLoc;
dstRt.x = dstRt.x + maxLoc.x;
dstRt.y = dstRt.y + maxLoc.y;
Mat diffmat, dstmat;
dstmat = mod_mat(dstRt);
absdiff(tmpl, dstmat, diffmat);
if (diffmat.channels() == 1)
diffmat.copyTo(spotmat(srcRt));
else
cvtColor(diffmat, spotmat(srcRt), CV_BGR2GRAY);
}
threshold(spotmat, spotmat, thresh, 255, CV_THRESH_BINARY);
// spotmat = spotmat * 10;
// //获取自定义核 第一个参数MORPH_RECT表示矩形的卷积核,当然还可以选择椭圆形的、交叉型的
// Mat element = getStructuringElement(MORPH_RECT, Size(1.5, 1.5));
//
//
// //具体要选择哪种操作,就修改第三个参数就可以了。这里演示的是形态学开运算处理
// morphologyEx(spotmat, spotmat, MORPH_OPEN, element);
imshow("模板匹配结果图", spotmat);
}
3. 算法缺点
需要匹配模板,对纹理较强布匹匹配效果不好,有兴趣的话可以尝试加入傅里叶变换,用傅里叶变换去分辨纹理/非纹理布匹,从而调用合适的算法。
4. 结语
后期会使用深度学习方法对布匹进行分类,这些都是预处理,为了制作工具做瑕疵的自动标定。(留下贫穷的泪水hhhhh)