角点 (corners) 的定义有两个版本:两条边缘的交点,或者,邻域内具有两个主方向的特征点

从人眼来看,角点是图像亮度发生剧烈变化的点 或 边缘曲线上曲率为极大值的点。例如,下图 E 和 F 便是典型的角点

1  检测思路

在图像中定义一个局部小窗口,然后沿各个方向移动这个窗口,则会出现 a) b) c) 三种情况,分别对应平坦区、边缘和角点

a)  窗口内的图像强度,在窗口向各个方向移动时,都没有发生变化,则窗口内都是 “平坦区”,不存在角点

b)  窗口内的图像强度,在窗口向某一个 (些) 方向移动时,发生较大变化;而在另一些方向不发生变化,那么,窗口内可能存在 “边缘”

c)  窗口内的图像强度,在窗口向各个方向移动时,都发生了较大的变化,则认为窗口内存在 “角点”

a)  flat region              b)  edge                     c)  corner

2  Harris 角点

2.1  泰勒展开

图像在点 $(x,y) $ 处的灰度值为 $I(x, y)$,当在 $x$ 方向上平移 $\Delta u$,且 $y$ 方向上平移 $\Delta v$ 时,图像灰度值的变化为

 

$I(x,y)$ 的偏导数分别记为 $I_x$ 和 $I_y$,则上式用一阶泰勒级数近似展开

写成矩阵形式

则有

, 假定

2.2  判别方法

定义角点响应值 $R = det(M) - k(trace(M))^{2} = \lambda_{1} \lambda_{2} - k (\lambda_{1}+\lambda_{2})^2 $,根据响应值的大小,判断小窗口内是否包含角点:

1) “平坦区”:|R| 小的区域,即 $\lambda_1$ 和 $\lambda_2$ 都小;

2)  “边缘”: R <0 的区域,即 $\lambda_1 >> \lambda_2$ 或反之;

3)  “角点”: R 大的区域,即 $\lambda_1$ 和 $\lambda_2$ 都大且近似相等

为了便于直观理解,绘制成 $\lambda_1-\lambda_2$ 平面如下图:

2.3  cornerHarris()

OpenCV 中 Harris 角点检测的函数为:

void  cornerHarris (InputArray      src,   // 输入图像 (单通道,8位或浮点型)OutputArray     dst,   // 输出图像 (类型 CV_32FC1,大小同 src)int      blockSize,    // 邻域大小int      ksize,        // Sobel 算子的孔径大小double   k,            // 经验参数,取值范围 0.04 ~ 0.06int      borderType = BORDER_DEFAULT    // 边界模式
)     

2.4  代码示例

#include "opencv2/highgui.hpp"
#include "opencv2/imgproc.hpp"using namespace cv;
// Harris corner parameters
int  kThresh = 150;
int kBlockSize = 2;
int kApertureSize = 3;
double k = 0.04;int main()
{// read imageMat src, src_gray;src = imread("building.jpg");if(src.empty())return -1;cvtColor(src, src_gray, COLOR_BGR2GRAY);Mat dst, dst_norm, dst_norm_scaled;// Harris corner detectcornerHarris(src_gray, dst, kBlockSize, kApertureSize, k);normalize(dst, dst_norm, 0, 255, NORM_MINMAX, CV_32FC1);convertScaleAbs(dst_norm, dst_norm_scaled);// draw detected cornersfor(int j=0; j < dst_norm.rows; j++){for(int i=0; i<dst_norm.cols;i++){if((int)dst_norm.at<float>(j,i) > kThresh){circle(src, Point(i, j), 2, Scalar(0,255,0));}}}imshow("harris corner", src);waitKey(0);
}

检测结果:

3  Shi-Tomasi 角点

Shi-Tomasi 角点是 Harris 角点的改进,在多数情况下,其检测效果要优于 Harris。二者的区别在于,Shi-Tomasi 选取 $\lambda_1$ 和 $\lambda_2$ 中的最小值,作为新的角点响应值 $R$

则相应的 $\lambda_1-\lambda_2$ 平面为:

3.1  goodFeaturesToTrack()

OpenCV 中 Shi-Tomasi 角点检测函数为:

void  goodFeaturesToTrack (     InputArray      image,     // 输入图像 (单通道,8位或浮点型32位)OutputArray     corners,   // 检测到的角点int         maxCorners,    // 最多允许返回的角点数量double      qualityLevel,  //  double      minDistance,   // 角点间的最小欧拉距离InputArray  mask = noArray(), //int         blockSize = 3,    //bool        useHarrisDetector = false,  //double      k = 0.04  // )     

3.2  代码示例

#include "opencv2/highgui.hpp"
#include "opencv2/imgproc.hpp"using namespace cv;
using namespace std;int kMaxCorners = 1000;
double kQualityLevel = 0.1;
double kMinDistance = 1;int main()
{// read imageMat src, src_gray;src = imread("building.jpg");if (src.empty())return -1;cvtColor(src, src_gray, COLOR_BGR2GRAY);// Shi-Tomasi corner detectvector<Point2f> corners;goodFeaturesToTrack(src_gray, corners, kMaxCorners, kQualityLevel, kMinDistance);// draw and show detected cornersfor (size_t i = 0; i < corners.size(); i++){circle(src, corners[i], 2.5, Scalar(0, 255, 0));}imshow("Shi-Tomasi corner", src);waitKey(0);
}

检测结果:

4  角点检测的实现

分析 cornerHarris() 源码,复现计算步骤:Sobel 算子求解 dx 和 dy  ->  矩阵 M  -> boxFilter  -> 每个像素的角点响应值 R,对应 C++ 代码实现如下:

#include <iostream>
#include "opencv2/highgui.hpp"
#include "opencv2/imgproc.hpp"using namespace cv;
using namespace std;int kApertureSize = 3;
int kBlockSize = 2;
double k = 0.04;
int  kThresh = 150;int main()
{// read imageMat src, src_gray;src = imread("chessboard.png");if (src.empty())return -1;cvtColor(src, src_gray, COLOR_BGR2GRAY);//  determine scaledouble scale = (double)(1 << (kApertureSize - 1)) * kBlockSize;scale *= 255.0;scale = 1.0 / scale;// 1) dx, dyMat Dx, Dy;Sobel(src_gray, Dx, CV_32F, 1, 0, kApertureSize, scale);Sobel(src_gray, Dy, CV_32F, 0, 1, kApertureSize, scale);// 2) cov matrixSize size = src_gray.size();Mat cov(size, CV_32FC3);for (int i = 0; i < size.height; i++){float* cov_data = cov.ptr<float>(i);const float* dxdata = Dx.ptr<float>(i);const float* dydata = Dy.ptr<float>(i);for (int j=0; j < size.width; j++){float dx = dxdata[j];float dy = dydata[j];cov_data[j * 3] = dx * dx;cov_data[j * 3 + 1] = dx * dy;cov_data[j * 3 + 2] = dy * dy;}}// 3) box filterboxFilter(cov, cov, cov.depth(), Size(kBlockSize, kBlockSize), Point(-1,-1), false);// 4) RMat dst(size,CV_32FC1);Size size_cov = cov.size();for (int i = 0; i < size_cov.height; i++){const float* ptr_cov = cov.ptr<float>(i);float* ptr_dst = dst.ptr<float>(i);for (int j=0; j < size_cov.width; j++){float a = ptr_cov[j * 3];float b = ptr_cov[j * 3 + 1];float c = ptr_cov[j * 3 + 2];ptr_dst[j] = (float)(a * c - b * b - k * (a + c) * (a + c));}}#if HARRIS_OPENCV  // compare with cornerHarris()cornerHarris(src_gray, dst, kBlockSize, kApertureSize, k);
#endif// 5) normalizationMat dst_norm, dst_norm_scaled;normalize(dst, dst_norm, 0, 255, NORM_MINMAX, CV_32FC1);convertScaleAbs(dst_norm, dst_norm_scaled);// 6) drawing cornersfor (int j = 0; j < dst_norm.rows; j++){for (int i = 0; i < dst_norm.cols; i++){if ((int)dst_norm.at<float>(j, i) > 150){circle(src, Point(i, j), 2, Scalar(0, 255, 0));}}}imshow("Harris corner", src);waitKey(0);
}

检测结果:将求得的角点响应值$R$,输出 txt 文件,与 cornerHarris() 输出的 $R$ 进行比较,结果几乎完全相同 (只有几处小数点后7位的值不同)

5  亚像素角点检测

5.1  cornerSubpix()

亚像素角点提取的函数 cornerSubPix(),常用于相机标定中,定义如下:

void  cornerSubPix(InputArray          image,  // 输入图象(单通道,8位或浮点型)InputOutputArray  corners,  // 亚像素精度的角点坐标Size              winSize,  // 搜索窗口尺寸的 1/2Size             zeroZone,  //TermCriteria     criteria   // 迭代终止准则
)     

5.2  代码示例

#include <iostream>#include "opencv2/highgui.hpp"
#include "opencv2/imgproc.hpp"using namespace cv;
using namespace std;int kMaxCorners = 40;
double kQualityLevel = 0.01;
double kMinDistance = 50;int main()
{// read imageMat src, src_gray;src = imread("chessboard.png");if (src.empty())return -1;cvtColor(src, src_gray, COLOR_BGR2GRAY);// Shi-Tomasi corner detectvector<Point2f> corners;goodFeaturesToTrack(src_gray, corners, kMaxCorners, kQualityLevel, kMinDistance);// draw and show detected cornersfor (size_t i = 0; i < corners.size(); i++){circle(src, corners[i], 3, Scalar(0, 255, 0));}imshow("Shi-Tomasi corner", src);imwrite("subpix.png", src);TermCriteria criteria = TermCriteria(TermCriteria::EPS + TermCriteria::COUNT, 40, 0.001);// find corner positions in subpixelcornerSubPix(src_gray, corners, Size(5, 5), Size(-1, -1), criteria);for (size_t i = 0; i < corners.size(); i++){cout << "Corner[" << i << "]: (" << corners[i].x << "," << corners[i].y << ")" << endl;}waitKey(0);
}

输入棋盘格5行8列,对应7x4个角点,图像的分辨率为 600*387,则所有角点的理论坐标如下表:

         

角点的图象坐标值输出如下:

 

参考资料:

《图像局部不变性特征与描述》 第 3 章

Harris 角点

http://www.cse.psu.edu/~rtc12/CSE486/

OpenCV Tutorials / feature2d module / Harris corner detector

OpenCV-Python Tutorials / Feature Detection and Description / Shi-Tomasi Corner Detector & Good Features to Track

OpenCV Tutorials / feature2d module / Detecting corners location in subpixels

OpenCV 之 角点检测相关推荐

  1. MFC+OPENCV实现角点检测

    MFC+OPENCV实现角点检测: // 角点检测 // 根据<基于OpenCV的计算机视觉技术实现>#define max_corners 200; // 限定的最大角点数IplImag ...

  2. OpenCV ChArUco角的检测

    OpenCV ChArUco角的检测 ChArUco角的检测 目标 源代码 ChArUco Board创建 ChArUco板检测 拍摄输入图像 读取相机校准参数(仅用于相机校准检测) 检测标记 ChA ...

  3. 【opencv】角点检测——虚线表格

    [opencv]角点检测--虚线表格 处理对象--虚线表格 处理方法--角点检测 Harris角点检测 函数解读 处理结果 处理对象--虚线表格 把之前做研电赛的东西做一点小的分享,先给大家看一下所处 ...

  4. Opencv java 角点检测 preCornerDetect(15)

    之前我们讲过一节的角点检测,是用的cornerHarris 这个方法,今天我们介绍另外的一种方法preCornerDetect 进行角点检测 效果 首先我们看一下角点检测的效果: 代码 那么代码上应该 ...

  5. OpenCV Fast角点检测

    FAST是一种用于角点检测的算法,该算法的原理是取图像中检测点,以改点为圆心的周围邻域内像素点判断监测点是否为角点. OpenCV中的FAST检测算法是用传统方法实现的. 实例化fast fast = ...

  6. opencv 实现角点检测 Shi-Tomasi角点检测

    角点检测概述 角点检测概述 Harris角点检测算法手动实现 Harris角点检测算法手动实现 opencv中使用Harris角点检测 opencv中使用Harris角点检测 opencv中使用 Sh ...

  7. OpenCV实现角点检测(cornerHarris)

    1.概述 案例:使用cornerHarris实现角点检测,并调节其参数看看不同参数下的不同效果 技术:Qt+C+++OpenCV 角点检测函数介绍: cornerHarris(src,dst,bloc ...

  8. opencv harris 角点检测

    一.图像特征的分类 [OpenCV入门教程之十六]OpenCV角点检测之Harris角点检测_[浅墨的游戏编程Blog]毛星云(浅墨)的专栏-CSDN博客_基于轮廓曲线的角点检测 下面部分图像来自与B ...

  9. opencv棋盘格角点检测原理总结

    第一步,局部平均自适应阈值化方法对亮度不均匀情况适应性强,因此用该方法对图像二值化,均衡化后得到了理想的门限,效果如图2所示. 第二步,图像膨胀分离各个黑块四边形的衔接,由于膨胀的是白色像素点,因此能 ...

  10. OpenCV中角点检测:Harris、Shi-Tomasi、亚像素级角点检测

    1.角点的定义 角点通常被定义为两条边的交点,或者说,角点的局部邻域应该具有两个不同区域的不同方向的边界.比如,三角形有三个角,矩形有四个角,这些就是角点,也是他们叫做矩形.三角形的特征. 角点是个很 ...

最新文章

  1. 扎克伯格成美国科技巨头里最后一位在任创始人CEO
  2. Mybatis Plugin(拦截器)的开发
  3. java 单例 实现_java 实现单例的各种方式
  4. 程序员需要知道的8个Linux命令
  5. 数据结构 - 栈(链表实现栈的入栈出栈)
  6. ORA-23616:执行块5失败
  7. python中import os_Python常用模块os--与操作系统交互
  8. python微信自动打卡_「微信辅助」吃鸡再也不怕了,Python用wxpy实现微信自动回复...
  9. 消息中间件之JMS实践(ActiveMQ) 1
  10. PUN☀️三、服务器大厅、服务器房间
  11. javascript手册安卓版_JavaScript 手册
  12. 达梦数据库报网络通讯异常排查步骤
  13. Unity:动态加载游戏等级.
  14. uk码对照表_【鞋子尺码对照表】 全面轻松了解鞋子尺码对照表 让你购物无困扰...
  15. DveC++编译[Error] ld returned 1 exit status
  16. C# Monitor.TryEnter 源码跟踪
  17. 个人家用nas_方便易用的家用NAS私家云不超千元
  18. C# dataGridView上下移动选中行
  19. vue 导航切换页面
  20. 复现lio_sam激光slam算法创建点云地图

热门文章

  1. python 钉钉导出Excel考勤统计
  2. 三阶金字塔魔方还原 - 3步无公式
  3. cwRsync的安装与配置用法
  4. 学习记录-FDD大规模MIMO系统的稀疏信道估计技术研究
  5. JPA中id前面有空格导致的Column 'id' not found问题
  6. 显示风场的某一局部区域,实现多分辨率
  7. CSS度量单位rem、em、vw、vh详解
  8. CDR是什么?CorelDRAW矢量绘图
  9. 记录在Deepin Linux上使用Jupyter/Pycharm中关于findfont: Font family [‘sans-serif‘] not found的解决方案及相关问题
  10. 计算机病毒和恶意软件管理制度,白城师范学院计算机病毒防治管理制度