索引地址:系列索引
角点和角点检测:角点检测
moravec算法
基本原理
这是一种基于灰度方差的角点检测算子,该算子计算图像中每个像素点沿着水平、垂直、对角线及反对角线的四个方向的灰度方差,其中的最小值选作该像素点的兴趣值IV(interest value),再通过局部非极大值抑制来检测其是否为特征点(角点)。
算法步骤
(1)计算各像元的兴趣值IV。以像素(c,r)为中心的 w x w
的影像窗口(如 5x5 的窗口),计算四个方向相邻像素灰度差的平方和:
1 2 3 4 5
| a-a-a -aaa- --a-- -aaa- a-a-a
|
其计算公式为:
V1=i=−k∑k−1(gc+i,r−gc+i+1,r)2V2=i=−k∑k−1(gc+i,r+i−gc+i+1,r+i+1)2V3=i=−k∑k−1(gc,r+i−gc,r+i+1)2V4=i=−k∑k−1(gc+i,r−1−gc+i+1,r−i−1)2
其中k =INT (w/ 2),即窗口的一半取整。取其中最小者作为该像素(c,r)的兴趣值。
(2)给定一经验阈值,将兴趣值大于该阈值的点作为候选点。阈值的原则应以候选点中包括的所需要的特征点而又不含过多的非特征点为原则。
(3)选取候选点中的极值点作为特征点。在一定大小的窗口内,将候选点中兴趣值不是最大者均去掉,仅留下一个兴趣值最大者,该像素即为一个特征点(抑制局部非最大)。
测试代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69
|
#include <opencv2/highgui/highgui.hpp> #include <opencv2/imgproc/imgproc.hpp> #include <opencv2/opencv.hpp> using namespace std; using namespace cv;
cv::Mat MoravecCorners(cv::Mat srcImage, int kSize, int threshold) { cv::Mat resMorMat = srcImage.clone(); int r = kSize / 2; const int nRows = srcImage.rows; const int nCols = srcImage.cols; int nConut = 0; Point * pPoint = new Point[ nRows * nCols ]; for (int i = r; i < srcImage.rows - r; i++) { for (int j = r; j < srcImage.cols - r; j++) { int wV1, wV2, wV3, wV4; wV1 = wV2 = wV3 = wV4 = 0; for (int k = -r; k < r; k++) wV1 += (srcImage.at<uchar>(i, j + k) - srcImage.at<uchar>(i, j + k + 1)) * (srcImage.at<uchar>(i, j + k) - srcImage.at<uchar>(i, j + k + 1)); for (int k = -r; k < r; k++) wV2 += (srcImage.at<uchar>(i + k, j) - srcImage.at<uchar>(i + k + 1, j)) * (srcImage.at<uchar>(i + k, j) - srcImage.at<uchar>(i + k + 1, j)); for (int k = -r; k < r; k++) wV3 += (srcImage.at<uchar>(i + k, j + k) - srcImage.at<uchar>(i + k + 1, j + k + 1)) * (srcImage.at<uchar>(i + k, j + k) - srcImage.at<uchar>(i + k + 1, j + k + 1)); for (int k = -r; k < r; k++) wV4 += (srcImage.at<uchar>(i + k, j - k) - srcImage.at<uchar>(i + k + 1, j - k - 1)) * (srcImage.at<uchar>(i + k, j - k) - srcImage.at<uchar>(i + k + 1, j - k - 1)); int value = min(min(wV1, wV2), min(wV3, wV4)); if (value > threshold) { pPoint[ nConut ] = Point(j, i); nConut++; } } } for (int i = 0; i < nConut; i++) cv::circle(resMorMat, pPoint[ i ], 5, cv::Scalar(255, 0, 0)); return resMorMat; }
int main() { cv::Mat srcImage = imread("circles.jpg", 0); if (!srcImage.data) return -1; cv::Mat resMorMat = MoravecCorners(srcImage, 5, 10000); cv::imshow("srcImage", srcImage); cv::imshow("resMorMat", resMorMat); cv::waitKey(0); return 0; }
|
效果为