角点 (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$ 方向上平移 $u$,且 $y$ 方向上平移 $v$ 时,图像灰度值的变化为

 $ \qquad E(u,v) = \sum\limits_{x,y}  \, \underbrace{w(x,y)}_\text{window function} \; [\underbrace{I(x+u, y+v)}_\text{shifted intensity} - \underbrace{I(x, y)}_\text{intensity}]^2 $

一阶泰勒级数近似展开得

$ \qquad \sum\limits_{x,y}  \; [I(x+u, y+v) - I(x, y)]^2 \approx \sum\limits_{x,y}  \; [I(x, y) +uI_x + vI_y - I(x, y)]^2 = \sum\limits_{x,y}  \; [u^2I_x^2 + 2uvI_x I_y + v^2I_y^2 ] $

写成矩阵形式

$ \qquad E(u,v) \approx \begin{bmatrix} u & v \end{bmatrix} \left ( \displaystyle \sum_{x,y} w(x,y) \begin{bmatrix} I_x^{2} & I_{x}I_{y} \\ I_xI_{y} & I_{y}^{2} \end{bmatrix} \right ) \begin{bmatrix} u \\ v \end{bmatrix}$

则有

$ \qquad E(u,v) \approx \begin{bmatrix} u & v \end{bmatrix} M \begin{bmatrix} u \\ v \end{bmatrix}$,    假定  $ M = \displaystyle \sum_{x,y} w(x,y) \begin{bmatrix} I_x^{2} & I_{x}I_{y} \\ I_xI_{y} & I_{y}^{2} \end{bmatrix}$

2.2  判别方法

定义一个角点响应值$\qquad 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 cv::cornerHarris (
InputArray src, // 输入图像 (单通道,8位或浮点型)
OutputArray dst, // 输出图像 (类型 CV_32FC1,大小同 src)
int blockSize, // 邻域大小
int ksize, // Sobel 算子的孔径大小
double k, // 经验参数,取值范围 0.04 ~ 0.06
int 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 image
Mat 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 detect
cornerHarris(src_gray, dst, kBlockSize, kApertureSize, k); normalize(dst, dst_norm, 0, 255, NORM_MINMAX, CV_32FC1);
convertScaleAbs(dst_norm, dst_norm_scaled); // draw detected corners
for(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$

$\qquad R = min(\lambda_1, \lambda_2)  $

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

3.1  goodFeaturesToTrack()

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

void cv::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 image
Mat src, src_gray;
src = imread("building.jpg");
if (src.empty())
return -1; cvtColor(src, src_gray, COLOR_BGR2GRAY);
// Shi-Tomasi corner detect
vector<Point2f> corners;
goodFeaturesToTrack(src_gray, corners, kMaxCorners, kQualityLevel, kMinDistance); // draw and show detected corners
for (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  角点检测的实现

在 OpenCV 中分析 cornerHarris() 函数的源码,得到实现步骤如下:sobel 算子求解 dx 和 dy  ->  矩阵 M  -> boxFilter  -> 每个像素的角点响应值 R

代码实现:

#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 image
Mat src, src_gray;
src = imread("chessboard.png");
if (src.empty())
return -1; cvtColor(src, src_gray, COLOR_BGR2GRAY);

  // scale
int depth = src_gray.depth();
double scale = (double)(1 << (2* kBlockSize)); if (depth == CV_8U)
scale *= 255.0;
scale = 1.0 / scale; // 1) dx, dy
Mat Dx, Dy;
Sobel(src_gray, Dx, CV_32F, 1, 0, kApertureSize, scale);
Sobel(src_gray, Dy, CV_32F, 0, 1, kApertureSize, scale); // 2) cov
Size 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) boxfilter
boxFilter(cov, cov, cov.depth(), Size(kBlockSize, kBlockSize)); // 4) R
Mat 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));
}
} // 5) normalize
Mat dst_norm, dst_norm_scaled;
normalize(dst, dst_norm, 0, 255, NORM_MINMAX, CV_32FC1);
convertScaleAbs(dst_norm, dst_norm_scaled); // 6) draw detected corners
for (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);
}

5  亚像素角点检测

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

5.1  cornerSubpix()

void cv::cornerSubPix(
InputArray image, // 输入图象(单通道,8位或浮点型)
InputOutputArray corners, // 亚像素精度的角点坐标
Size winSize, // 搜索窗口尺寸的 1/2
Size 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()
{
// 1) read image
Mat src, src_gray;
src = imread("chessboard.png");
if (src.empty())
return -1; cvtColor(src, src_gray, COLOR_BGR2GRAY);
// 2) Shi-Tomasi corner detect
vector<Point2f> corners;
goodFeaturesToTrack(src_gray, corners, kMaxCorners, kQualityLevel, kMinDistance); // 3) draw and show detected corners
for (size_t i = 0; i < corners.size(); i++)
{
circle(src, corners[i], 3, Scalar(0, 255, 0));
}
imshow("Shi-Tomasi corner", src); TermCriteria criteria = TermCriteria(TermCriteria::EPS + TermCriteria::COUNT, 40, 0.001);
// 4) find corner positions in subpixel
cornerSubPix(src_gray, corners, Size(5, 5), Size(-1, -1), criteria);
// 5) output subpixel corners
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 章

https://www.cnblogs.com/ronny/p/4009425.html

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 / Creating your own corner detector

OpenCV Tutorials / feature2d module / Detecting corners location in subpixels

OpenCV 之 角点检测的更多相关文章

  1. 【OpenCV】角点检测:Harris角点及Shi-Tomasi角点检测

    角点 特征检测与匹配是Computer Vision 应用总重要的一部分,这需要寻找图像之间的特征建立对应关系.点,也就是图像中的特殊位置,是很常用的一类特征,点的局部特征也可以叫做“关键特征点”(k ...

  2. OpenCV Shi-Tomasi角点检测子

    Shi-Tomasi角点检测子 目标 在这个教程中我们将涉及: 使用函数 goodFeaturesToTrack 来调用Shi-Tomasi方法检测角点. 理论 代码 这个教程的代码如下所示.源代码还 ...

  3. OpenCV Harris 角点检测子

    Harris 角点检测子 目标 本教程中我们将涉及: 有哪些特征?它们有什么用? 使用函数 cornerHarris 通过 Harris-Stephens方法检测角点. 理论 有哪些特征? 在计算机视 ...

  4. Opencv Shi-Tomasi角点检测

    #include <iostream>#include <opencv2/opencv.hpp> using namespace std;using namespace cv; ...

  5. Opencv Harris角点检测

    #include <iostream>#include <opencv2/opencv.hpp> using namespace std;using namespace cv; ...

  6. OPENCV(6) —— 角点检测

    图像特征的类型通常指边界.角点(兴趣点).斑点(兴趣区域).角点就是图像的一个局部特征,应用广泛.harris角点检测是一种直接基于灰度图像的角点提取算法,稳定性高,尤其对L型角点检测精度高,但由于采 ...

  7. opencv::自定义角点检测

    #include <opencv2/opencv.hpp> #include <iostream> #include <math.h> using namespac ...

  8. opencv笔记6:角点检测

    time:2015年10月09日 星期五 23时11分58秒 # opencv笔记6:角点检测 update:从角点检测,学习图像的特征,这是后续图像跟踪.图像匹配的基础. 角点检测是什么鬼?前面一篇 ...

  9. opencv: 角点检测源码分析;

    以下6个函数是opencv有关角点检测的函数 ConerHarris, cornoerMinEigenVal,CornorEigenValsAndVecs, preConerDetect, coner ...

随机推荐

  1. python之字符串方法upper/lower

    1.描述: upper():用于将字符串全部转换为大写字母 lower():用于将字符串全部转换为小写字母 2.语法 str.upper() str.lower() 3.返回值 upper()或low ...

  2. 基于Vue的单页面应用的Markdown渲染

    之前渲染 Markdown 的时候, 笔者使用的是 mavonEditor 的预览模式, 使用起来比较爽, 只需要引入组件即可, 但是在最近的开发中, 遇到了困难. 主要问题在于作为单页面应用, 站内 ...

  3. python3 anaconda 安装pyhook3 pythoncom(pywin32)

    为什么不安装pyhook 1.pyhook不支持python3 2.网络上有一些方法下载pyhook的whl然后pip安装到python3,可以运行,但是会因为编码问题导致移动到窗口标题含有非ASCI ...

  4. Git使用指南(下)

    9 初识分支 把每一次的提交,都用线连起来,你会发现,很连贯. C/C++    指针的概念 git reset --hard commitid HEAD    如果说内容已经add到暂存区,此时要想 ...

  5. Linux 驱动框架---net驱动框架

    这一篇主要是学习网络设备驱动框架性的东西具体的实例分析可以参考Linux 驱动框架---dm9000分析 .Linux 对于网络设备的驱动的定义分了四层分别是网络接口层对上是IP,ARP等网络协议,因 ...

  6. BB link

    1 1 1 BB link: 1 1 demo: code: result: 1 1 1 1 1 1 1

  7. HTML5 download 执行条件

    HTML5 download 执行条件 同一个域名下的资源 http only 绝对路径/相对路径 都可以 demo https://cdn.xgqfrms.xyz/ https://cdn.xgqf ...

  8. 移动端 750px UI 设计稿

    750px UI 设计稿 App 小程序 H5 rem & vh/vw 在移动端页面开发中,UI 一般会用750px(iphone 6)来出设计稿; 然后要求能够做到页面是自适应屏幕的,这种情 ...

  9. npm init & npx create & yarn create

    npm init & npx create & yarn create https://create-react-app.dev/docs/getting-started/#creat ...

  10. yapi & mock JSON

    yapi & mock JSON json, body https://hellosean1025.github.io/yapi/documents/mock.html response bo ...