1500字范文,内容丰富有趣,写作好帮手!
1500字范文 > 使用OpenCV实现Halcon算法(4)OpenCV实现边缘模板匹配算法

使用OpenCV实现Halcon算法(4)OpenCV实现边缘模板匹配算法

时间:2019-12-30 05:25:53

相关推荐

使用OpenCV实现Halcon算法(4)OpenCV实现边缘模板匹配算法

声明:本篇仅仅是分享网上的开源项目,算法非本人原创。

本文转自:OpenCV研习社

干货 | OpenCV实现边缘模板匹配算法 - 云+社区 - 腾讯云

干货 | OpenCV实现边缘模板匹配算法 - 云+社区 - 腾讯云

背景概述

OpenCV中自带的模板匹配算法,完全是像素基本的模板匹配,特别容易受到光照影响,光照稍微有所不同,该方法就会歇菜了!搞得很多OpenCV初学者刚学习到该方法时候很开心,一用该方法马上很伤心,悲喜交加,充分感受到了理想与现实的距离,不过没关系,这里介绍一种新的模板匹配算法,主要是基于图像边缘梯度,它对图像光照与像素迁移都有很强的抗干扰能力,据说Halcon的模板匹配就是基于此的加速版本,在工业应用场景中已经得到广泛使用。

算法原理

该算法主要是基于图像梯度,实现基于梯度级别的NCC模板匹配,基于Sobel梯度算子得到dx, dy, magnitude

通过Canny算法得到边缘图像、基于轮廓发现得到所有的轮廓点集,基于每个点计算该点的dx、dy、magnitude(dxy)三个值。生成模板信息。然后对输入的图像进行Sobel梯度图像之后,根据模型信息进行匹配,这样的好处有两个:

梯度对光照有很强的抗干扰能力,对模板匹配的抗光照干扰基于梯度匹配,可以对目标图像上出现的微小像素迁移进行抵消。

算法实现代码详解

梯度图像计算

Mat gx, gy;Sobel(gray, gx, CV_32F, 1, 0);Sobel(gray, gy, CV_32F, 0, 1);Mat magnitude, direction;cartToPolar(gx, gy, magnitude, direction);long contoursLength = 0;double magnitudeTemp = 0;int originx = contours[0][0].x;int originy = contours[0][0].y;

模板生成

// 提取dx\dy\mag\log信息vector<vector<ptin>> contoursInfo;// 提取相对坐标位置vector<vector<Point>> contoursRelative;// 开始提取for (int i = 0; i < contours.size(); i++) {int n = contours[i].size();contoursLength += n;contoursInfo.push_back(vector<ptin>(n));vector<Point> points(n);for (int j = 0; j < n; j++) {int x = contours[i][j].x;int y = contours[i][j].y;points[j].x = x - originx;points[j].y = y - originy;ptin pointInfo;pointInfo.DerivativeX = gx.at<float>(y, x);pointInfo.DerivativeY = gy.at<float>(y, x);magnitudeTemp = magnitude.at<float>(y, x);pointInfo.Magnitude = magnitudeTemp;if (magnitudeTemp != 0)pointInfo.MagnitudeN = 1 / magnitudeTemp;contoursInfo[i][j] = pointInfo;}contoursRelative.push_back(points);}

计算目标图像梯度

// 计算目标图像梯度Mat grayImage;cvtColor(src, grayImage, COLOR_BGR2GRAY);Mat gradx, grady;Sobel(grayImage, gradx, CV_32F, 1, 0);Sobel(grayImage, grady, CV_32F, 0, 1);Mat mag, angle;cartToPolar(gradx, grady, mag, angle);

形状模板匹配

double partialScore = 0;double resultScore = 0;int resultX = 0;int resultY = 0;double start = (double)getTickCount();for (int row = 0; row < grayImage.rows; row++) {for (int col = 0; col < grayImage.cols; col++) {double sum = 0;long num = 0;for (int m = 0; m < contoursRelative.size(); m++) {for (int n = 0; n < contoursRelative[m].size(); n++) {num += 1;int curX = col + contoursRelative[m][n].x;int curY = row + contoursRelative[m][n].y;if (curX < 0 || curY < 0 || curX > grayImage.cols - 1 || curY > grayImage.rows - 1) {continue;}// 目标边缘梯度double sdx = gradx.at<float>(curY, curX);double sdy = grady.at<float>(curY, curX);// 模板边缘梯度double tdx = contoursInfo[m][n].DerivativeX;double tdy = contoursInfo[m][n].DerivativeY;// 计算匹配if ((sdy != 0 || sdx != 0) && (tdx != 0 || tdy != 0)){double nMagnitude = mag.at<float>(curY, curX);if (nMagnitude != 0)sum += (sdx * tdx + sdy * tdy) * contoursInfo[m][n].MagnitudeN / nMagnitude;}// 任意节点score之和必须大于最小阈值partialScore = sum / num;if (partialScore < min((minScore - 1) + (nGreediness * num), nMinScore * num))break;}}// 保存匹配起始点if (partialScore > resultScore){resultScore = partialScore;resultX = col;resultY = row;}}}

运行效果

正常光照

光照非常暗

改进:

不需要全局匹配,可以对目标图像先做一个小梯度阈值,然后再进行匹配,提升速度、构造目标图像金字塔,实现多分辨率模板匹配支持!

觉得不错点【好看】支持一下!

参考:

Edge Based Template Matching - CodeProject

/meiqua/shape_based_matching

/daxiaHuang/edge-template-match

基于边界的模板匹配的原理及算法实现

基于边界的模板匹配的原理及算法实现_小新识图的博客-CSDN博客_halcon模板匹配原理

基于边界的模板匹配的原理及算法实现C++_模板匹配算法原理,c++模板匹配算法-C++代码类资源-CSDN下载

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。