• OpenCV图像特征提取学习二,Shi-Tomasi 角点检测算法


    一.Shi-Tomasi 角点检测算法

    Harris角点检测基本数学公式如下: 

                                E(u,v)=x,yw(x,y)[I(x+u,y+v)I(x,y)]2" role="presentation" style="position: relative;">E(u,v)=x,yw(x,y)[I(x+u,y+v)I(x,y)]2

    泰勒公式进行展开后,近似为:

                                E[u,v]w(u,v)[(Ix2,IxIyIxIy,Iy2)](uv)" role="presentation" style="position: relative;">E[u,v]w(u,v)[(Ix2,IxIyIxIy,Iy2)](uv)

    对于局部微小的移动量[u,v]" role="presentation" style="position: relative;">[u,v],可以近似得到下面的表达:

                                 E[u,v]M[uv]" role="presentation" style="position: relative;">E[u,v]M[uv]

    其中M为2*2的矩阵,可由图像的导数求得:

                                 M=x,yw(u,v)[Ix2IxIyIxIyIy2]" role="presentation" style="position: relative;">M=x,yw(u,v)[Ix2IxIyIxIyIy2]

    矩阵M,将其对角化之后 ,特征值λ1, λ2 分别代表了X 和Y 方向的灰度变化率.

                                 M=x,yw(u,v)[Ix2IxIyIxIyIy2]=[λ100λ2]" role="presentation" style="position: relative;">M=x,yw(u,v)[Ix2IxIyIxIyIy2]=[λ100λ2]

    E(u,v)" role="presentation" style="position: relative;">E(u,v)的椭圆形式如下:

                                  

    Harris角点检测算法的角点响应函数为:

                                     R=λ1λ2K(λ1+λ2)2" role="presentation" style="position: relative;">R=λ1λ2K(λ1+λ2)2

    Harris角点检测算法就是对角点响应函数R进行阈值处理:R > threshold,即提取R的局部极大值。shi-Tomasi 算法是基于Harris 算法进行的改进,Harris算法最基础的数学定义是将矩阵 M 的行列式值与矩阵 M 的迹相减,再将差值与预先给定的阈值进行比较。若两个特征值中较小的一个大于最小阈值,则会得到强角点,这就是Shi-Tomasi角点检测算法。

    Shi-Tomasi角点检测算法的角点响应函数为:

                                     R=min(λ1,λ2)" role="presentation" style="position: relative;">R=min(λ1,λ2)

    Shi-tomasi角点检测 和Harris 算法一样,如果该分数大于设定的阈值,我们就认为它是一个角点。可以看出来只有当 λ1 和 λ 2 都大于最小值时,才被认为是角点,即下图中的紫色区域。

    --------------------------------------------------------------------------------------------------------------------------------

    二.Shi-Tomasi角点检测API函数接口

    1. void goodFeaturesToTrack
    2. ( InputArray image,
    3. OutputArray corners,
    4. int maxCorners,
    5. double qualityLevel,
    6. double minDistance,
    7. InputArray mask=noArray(),
    8. int blockSize=3,
    9. bool useHarrisDetector=false,
    10. double k=0.04 );

    参数说明:

    第一个参数image:输入图像,8位或浮点32比特,单通道图像;
    第二个参数corners:输出参数,检测到的角点;表示返回角点的数目,如果检测出来角点数目大于最大数目则返回响应值最强前规定数目;
    第三个参数corner_count:输出参数,检测到的角点数目;
    第四个参数quality_level:最大最小特征值的乘法因子。定义可接受图像角点的最小质量因子;
    第五个参数min_distance:限制因子。得到的角点的最小距离;使用 Euclidian 距离;
    第六个参数mask:ROI感兴趣区域。函数在ROI中计算角点;如果 mask 为 NULL,则选择整个图像;
    第七个参数block_size: 是计算导数的自相关矩阵时指定点的领域,采用小窗口计算的结果比单点 (也就是block_size为1)计算的结果要好;
    第八个参数useHarrisDetector:当use_harris的值为非0,则函数使用Harris的角点定义;若为 0,则使用Shi-Tomasi的定义;
    第九个参数K:用于设置Hessian自相关矩阵即对Hessian行列式的相对权重的权重系数;

    ---------------------------------------------------------------------------------------------------------------------------------

    代码实现

    1. #include"stdafx.h"
    2. #include <opencv2/opencv.hpp>
    3. #include <iostream>
    4. #include <opencv2/highgui/highgui.hpp>
    5. #include <opencv2/imgproc/imgproc.hpp>
    6. #include <iostream>
    7. using namespace cv;
    8. using namespace std;
    9. #define WIN_NAME "Shi-Tomasi角点检测"
    10. Mat srcImage, grayImage;
    11. int maxCornerNumber = 33;
    12. int maxTrackbarNumber = 500;
    13. RNG rng(12345);
    14. void on_GoodFeatureToTrack(int, void *)
    15. {
    16. if (maxCornerNumber <= 1)
    17. {
    18. maxCornerNumber = 1;
    19. }
    20. //Shi-Tomasi参数准备
    21. vector<Point2f> corners;
    22. double qualityLevel = 0.01; //角点检测可以接受的最小特征值
    23. double minDistance = 10; //角点间的最小像素距离设置
    24. int blockSize = 3; //计算导数自相关矩阵时指定的领域范围
    25. double k = 0.04; //权重系数
    26. Mat copy = srcImage.clone(); //复制原图到一个临时变量中,作为感兴趣区域
    27. //Shi-Tomasi Test
    28. goodFeaturesToTrack(grayImage, corners, maxCornerNumber, qualityLevel, minDistance, Mat(), blockSize, false, k);
    29. //输出文字信息
    30. cout << ">此次检测到的角点数量为: " << corners.size() << endl;
    31. //绘制检测到的角点
    32. for (unsigned int i = 0; i < corners.size(); i++)
    33. {
    34. circle(copy, corners[i], 5, Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255)), -1, 8, 0);
    35. }
    36. imshow(WIN_NAME, copy);
    37. }
    38. int main(int argc, char** argv)
    39. {
    40. srcImage = imread("F:/photo/lj.jpg");
    41. cvtColor(srcImage, grayImage, COLOR_BGR2GRAY);
    42. namedWindow(WIN_NAME, WINDOW_AUTOSIZE);
    43. createTrackbar("最大角点数:", WIN_NAME, &maxCornerNumber, maxTrackbarNumber, on_GoodFeatureToTrack);
    44. //imshow(WIN_NAME, srcImage);
    45. on_GoodFeatureToTrack(0, 0);
    46. waitKey(0);
    47. return 0;
    48. }

    -------------------------------------------------------------------------------------------------------------------------------- 

    图像处理效果

  • 相关阅读:
    小程序中如何给会员卡设置到期时间
    力扣记录:剑指offer(7)——JZ59-68
    DDD领域驱动设计总结和C#代码示例
    一些思想概念(分布式 )
    notepad 文本筛选并替换
    spring aop 初探
    C++继承
    重庆自考2022报名注意事项
    *CTF babyarm内核题目分析
    为什么SQL预编译可以防止SQL注入攻击
  • 原文地址:https://blog.csdn.net/weixin_44651073/article/details/126475441