一、相关原理

Moravec是最早的角点检测算法之一,它将角点定义为具有低“自相关性”的点。针对图像的每个像素,算法将像素周边的一个邻域作为一个patch,并检测这个patch和周围其他patch的相关性。这种相关性通过两个patch间的SSD(平方差之和)来衡量,SSD值越小则相似性越高。

一幅图像可分为区域、边缘和角点三个部分。如图1所示,如果像素位于平滑图像区域内,周围的patch都会非常相似。如果像素在边缘上,则周围的patch在与边缘正交的方向上会有很大差异,在与边缘平行的方向上则较为相似。而如果像素是各个方向上都有变化的特征点,则周围所有的patch都不会很相似。Moravec计算每个像素patch和周围patch的SSD最小值作为强度值,取局部强度最大的点作为角点。

图1

首先,计算每个像素点的兴趣值,即以该像素点为中心,取一个w*w(如:5x5)的方形窗口,计算0度、45度、90度、135度四个方向灰度差的平方和,取其中的最小值作为该像素点的兴趣值。

      (1.1)

如图2所示,以3x3窗口为例,黑色窗口为I(x,y),红色窗口为I(x+u,y+v),其中四种移位(u,v)= (1,0), (1,1), (0,1), (-1, 1)。w(x,y)为方形二值窗口,若像素点在窗口内,则取值为1,否则为0。

图2

然后,使用非极大值抑制找到局部最大值(此时局部窗口大小可另行设定),将局部最大值与设定的阈值比较,最终确定角点。

此外,度量图像块A与图像块B之间的差异性(或相似性)有以下几种方法:

1)SAD(Sum of Absolute Difference),即两个小块的差的绝对值之和:

        (1.2)

2)SSD(Sum of Squared Distance),即两个小块之间差的平方和:

       (1.3)

3)NCC(Normalized Cross Correlation,归一化互相关),这种方式比前两种方法要复杂,它计算两个小块的相关性,所以相关性接近0表示不相似,而接近1表示相似。前两种距离形式恰好相反,距离越小越相似。

        (1.4)

二、基本步骤

输入:源单通道图像、窗口大小、阈值

输出:角点

算法具体步骤:

1)对于每个像素点,计算E(u,v)的值。如果是3*3,(u,v)的值为4种情况,(1,0),(1,1),(0,1),(-1,1);如果是5*5的窗口,(u,v)的取值为8种情况,(1,0),(1,1),(0,1),(-1,1),(-1,0),(-1,-1),(0,-1),(1,-1)。

2)计算E(u,v)的最小值minValue;

3)对于每个位置minValue进行判断,是不是大于设定的阈值,如果大于设定的阈值,就进行非局部极大值抑制,判断是不是局部极大值。如果是局部极大值则为角点,否者不是角点。

算法结束。

图3 算法流程图

注:为什么要进行非局部极大值抑制?因为在一个窗口内,中心点附近的值也可能大于阈值,导致角点聚集现象。所以要在这个窗口内排除这些值,确定局部的最大值,而进行非局部极大值抑制。

三、缺点分析

1、对边缘点的反应比较强烈

强度值的计算并不是各向同性的(各向异性),只有离散的8个角度方向被考虑。moravec算法对角点的定义是:窗口在各个方向的移动,窗口内的灰度值都会产生较大的变化。而其实这里的“各个方向”,最多也就只有8个方向。所以,如果边缘的方向是这8个方向以外的方向,那么,就会被认为是角点。

图4

2、不具备旋转不变性

因为moravec算法只计算最多八个方向的灰度值差的平方和,所以可能会出现原来的一条边缘在这8个方向之上而旋转之后却不在了,也有可能是相反的情况。这种旋转不变性进一步抑制了moravec算法的实用性。

3、窗口是方形且是二元的

在moravec中,使用的滑动窗口是正方形的、以及窗内的各个像素权重同质性(应该是中心像素权重大,距离中心越远,权重越小),并且窗口值是二元的,在窗口内,窗口值是1,在窗口外,窗口值是0。为了达到精确估计局部灰度值的变化程度,圆形的窗口才是理想的。圆形的窗口,使得中心点到窗口的每一个边缘点的欧式距离基本是相等的,以及赋予离中心更近的点更大的权重。

4、离散点(噪声点)与角点有相同的角点性(cornerness),因此Moravec算子对噪声敏感,但是通过增大滑动窗口的大小可以对噪声起到一定的抑制作用,同时增加了计算量。另一方面,通过设定一个阈值T来对cornerness map进行二值化,小于阈值T的cornerness map设置为0,从而对离散点的局部极大值进行抑制。

5、对于图像的一些边界区域像素,没有计算E(u,v)值。

四、代码分析

注意在实际使用时还要进行非局部极大值抑制,本代码未实现。

/**********************************************************************************
*函数 Mat MoravecCorners(cv::Mat SrcImage, int kSize, int threshold)
*输入:*SrcImage : 单通道图像*kSize : 窗口尺寸*threshold : 阈值
*输出*MorImage : 提取到角点的图像
***************************************************************************************/
#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
using namespace std;
using namespace cv;Mat MoravecCorners(cv::Mat SrcImage, int kSize, int threshold)
{Mat MorImage = SrcImage.clone();// 获取初始化参数信息int r = kSize / 2;const int nRows = SrcImage.rows;const int nCols = SrcImage.cols;int nConut = 0;CvPoint *pPoint = new CvPoint[nRows*nCols];// 图像遍历for (int y = r; y < SrcImage.rows - r; y++)//行(y轴--v轴){for (int x = r; x<SrcImage.cols - r; x++)//列(x轴--u轴){int wV1, wV2, wV3, wV4;wV1 = wV2 = wV3 = wV4 = 0;// 计算水平(0度)方向窗内兴趣值for (int k = -r; k < r; k++)//k=-2,-1,0,1wV1 += (SrcImage.at<uchar>(y, x + k) - SrcImage.at<uchar>(y, x + k + 1))*(SrcImage.at<uchar>(y, x + k) - SrcImage.at<uchar>(y, x + k + 1));// 计算垂直(90度)方向窗内兴趣值for (int k = -r; k < r; k++)wV2 += (SrcImage.at<uchar>(y + k, x) - SrcImage.at<uchar>(y + k + 1, x))*(SrcImage.at<uchar>(y + k, x) - SrcImage.at<uchar>(y + k + 1, x));// 计算45度方向窗内兴趣值for (int k = -r; k < r; k++)wV3 += (SrcImage.at<uchar>(y + k, x + k) - SrcImage.at<uchar>(y + k + 1, x + k + 1))*(SrcImage.at<uchar>(y + k, x + k) - SrcImage.at<uchar>(y + k + 1, x + k + 1));// 计算135度方向窗内兴趣值for (int k = -r; k < r; k++)wV4 += (SrcImage.at<uchar>(y + k, x - k) - SrcImage.at<uchar>(y + k + 1, x - k - 1))*(SrcImage.at<uchar>(y + k, x - k) - SrcImage.at<uchar>(y + k + 1, x - k - 1));// 取其中的最小值作为该像素点的最终兴趣值int value = min(min(wV1, wV2), min(wV3, wV4));//若兴趣值大于阈值,则将点的坐标存入数组中if (value > threshold){pPoint[nConut] = cvPoint(x, y);nConut++;}}}//绘制兴趣点cout << "kSize :5*5" << endl;cout << "threshold : 5000" << endl;cout << "corners :" << nConut << endl;for (int i = 0; i < nConut; i++)cv::circle(MorImage, pPoint[i], 3, cv::Scalar(255, 0, 0));return MorImage;
}int main()
{cv::Mat SrcImage = imread("3.jpg");if (!SrcImage.data)return -1;cv::Mat srcImage;cvtColor(SrcImage, srcImage,CV_RGB2GRAY);//窗口设置为5*5,阈值设置为5000double time0 = static_cast<double>(getTickCount());cv::Mat MorImage = MoravecCorners(srcImage, 5, 5000);time0 = ((double)getTickCount() - time0) / getTickFrequency();cout <<"runtime :"<< time0 << "s" << endl;cv::imshow("MorMat", MorImage);cv::waitKey(0);return 0;
}

输入:lena.jpg,窗口大小5*5,阈值5000

输出:角点检测图(由于没有实现非局部极大值抑制,所以出现角点粘连现象)

图5 实验结果图

1、Moravec角点检测算法相关推荐

  1. Moravec角点检测算子

    Moravec角点检测算子 Moravec 在1981年提出Moravec角点检测算子[1],并将它应用于立体匹配. 首先, 计算每个像素点的兴趣值, 即以该像素点为中心, 取一个w*w(如:5x5) ...

  2. 【机器视觉学习笔记】Harris 角点检测算法(C++)

    目录 原理 算法步骤 优缺点 源码 效果 原图 输出 平台:Windows 10 20H2 Visual Studio 2015 OpenCV 4.5.3 本文摘自2.Harris角点检测算法 -- ...

  3. Harris角点检测算法

    Harris角点检测算法 一.算法原理 二.代码 三.运行结果与分析 (一)纹理.角点丰富场景 (二)纹理平坦场景 (三)垂直或水平边缘多场景 四.总结 PS:为了消除参数k的影响,也可采用商来计算响 ...

  4. 角点检测--基于梯度的方法(Moravec角点检测、Harris角点检测、Shi-Tomasi角点检测)

    Moravec Detector Moravec角点检测是第一个提出兴趣点(interest points)的Paper.它的主要思想是:以每个像素为中心,有一个固定的滑动窗口.该方法计算并在八个方向 ...

  5. Harris角点检测算法优化

    Harris角点检测算法优化 一.综述 用 Harris 算法进行检测,有三点不足:(1 )该算法不具有尺度不变性:(2 )该算法提取的角点是像素级的:(3 )该算法检测时间不是很令人满意. 基于以上 ...

  6. Python+OpenCV:图像快速角点检测算法(FAST Algorithm for Corner Detection)

    Python+OpenCV:图像快速角点检测算法(FAST Algorithm for Corner Detection) 理论 Feature Detection using FAST Select ...

  7. Harris角点检测算法手动实现

    算法流程: 将图像转换为灰度图像 利用Sobel滤波器求出 海森矩阵 (Hessian matrix) : 将高斯滤波器分别作用于Ix².Iy².IxIy: 计算每个像素的 R= det(H) - k ...

  8. FAST角点检测算法(二)- 非极大值抑制筛选fast特征点

    FAST角点检测算法(二)- 非极大值抑制筛选fast特征点 author@jason_ql(lql0716) http://blog.csdn.net/lql0716 fast角点检测算法参考文章& ...

  9. 【理解】经典角点检测算法--Harris角点

    目录 什么是角点 角点检测算法的原始思想: Harris角点检测原理 Harris角点算法的基本步骤 实践: Harris角点检测可能会用到的OpenCV API: 手写API: 1.展示图片: 2. ...

最新文章

  1. BST(binary search tree)类型题目需要用到的头文件binary_tree.h
  2. 介绍如何用 Python 来绘制高清的交互式地图,建议收藏
  3. spring boot 的常用注解使用 总结
  4. 大家谈谈公司里的项目经理角色及职责都是干什么的?
  5. java list循环中删除元素的坑
  6. 3、play中的模板引擎
  7. 前端开发知识点解答-CSS-面试
  8. PHP中文分词的实现
  9. 上一家单位离职的原因_员工离职再入职,专项附加扣除该如何变更?
  10. day1---流程控制语句的四种基本格式
  11. 计算机网络(北京理工大学出版社)课后习题答案
  12. 2017济南北大青鸟accp和学士后课程的真实情况
  13. 智能蓝牙技术原理及设计方案集锦
  14. powershell_windows命令行杀进程(pskill)/进程任务管理/服务管理/(查看/关闭/停止/移除windows移除mysql服务)
  15. APP被应用商店下架了怎么办?
  16. php根据淘宝短链接获取商品ID
  17. 图片缩略图,CMYK图片变红问题解决
  18. Illegal mix of collations (utf8mb4_0900_ai_ci,IMPLICIT) and (utf8mb4_general_ci,IMPLICIT) for operat
  19. CG-多边形扫描线填充算法详解
  20. SysInfoTools MS SQL Transaction Log Recovery 22.0

热门文章

  1. c++中函数参数的求值顺序
  2. 英语总结—— 翩若惊鸿, 婉若游龙
  3. FPGA之动态数码管显示实验
  4. 计算机教育的改革论文,学校计算机改革下的计算机教育论文
  5. 渡一教育公开课web前端开发JavaScript精英课学习笔记(二十六)JavaScript 打砖块
  6. 晨读美文推荐【英文悦读】-《a day so happy》
  7. [转]Linux相关图书选购指南
  8. 七彩虹计算机主板怎么样,七彩虹的主板怎么样?
  9. Linux 命令行字符画工具
  10. php 固定资产源码,Assets 固定资产管理源代码!asp .net WEB(ASP,PHP,...) 274万源代码下载- www.pudn.com...