opencv 的norm_【OpenCV入门之十九】Harris与ShiTomasi角点检测

9721fae25bc5d452100faa407835696d.png

小白导读

学习计算机视觉最重要的能力应该就是编程了,为了帮助小伙伴尽快入门计算机视觉,小白准备了【OpenCV入门】系列。新的一年文章的内容进行了很大的完善,主要是借鉴了更多大神的文章,希望让小伙伴更加容易理解。如果小伙伴觉得有帮助,请点击一下文末的“在看”鼓励一下小白。

角点检测是计算机视觉系统中用来获取图像特征的一种方法。我们都常说,这幅图像很有特点,但是一问他到底有哪些特点,或者这幅图有哪些特征可以让你一下子就识别出该物体,你可能就说不出来了。其实说图像的特征,你可以尝试说一下这幅图有几个矩形啊几个圆形啊,有几条直线啊,当然啦,你也可以说一下有几个角点。

什么是角点?

角点通常被定义为两条边的交点。比如,三角形有三个角,矩形有四个角,这些就是角点,也是他们叫做矩形、三角形的特征,我们看到一些几何图形具有三个角,那么我们便可以脱口而出说这是一个三角形。

上面所说的是严格意义上的角点,但是从广义来说,角点指的是拥有特定特征的图像点,这些特征点在图像中有具体的坐标,并具有某些数学特征(比如局部最大或最小的灰度)。

图像特征类型可以被分为三种:

  • 边缘

  • 角点(感兴趣关键点)

  • 斑点(感兴趣区域)

角点是个很特殊的存在。如果某一点在任意方向的一个微小的变动都会引起灰度很大的变化,那么我们就可以把该点看做是角点。

Harris 角点检测

Harris角点检测是一种直接基于灰度图的角点提取算法,稳定性高,尤其对L型角点(也就是直角)检测精度高。缺点也是明显的,就是运算速度慢。

OpenCV使用的相应函数是

void cornerHarris( InputArray src, OutputArray dst, int blockSize,int ksize,double k, int borderType = BORDER_DEFAULT );

下面给出相应的检测代码。

#include   
#include "opencv2/highgui/highgui.hpp"  
#include "opencv2/imgproc/imgproc.hpp"  

using namespace cv;
using namespace std;


Mat g_srcImage, g_srcImage1, g_grayImage;
int thresh = 30; //当前阈值  
int max_thresh = 175; //最大阈值  

void on_CornerHarris(int, void*);//回调函数  

int main(int argc, char** argv){
   g_srcImage = imread("lol19.jpg", 1);
   if (!g_srcImage.data)
   {
       printf("读取图片错误! \n");
       return -1;
   }
   imshow("原始图", g_srcImage);
   g_srcImage1 = g_srcImage.clone();

   //存留一张灰度图  
   cvtColor(g_srcImage1, g_grayImage, CV_BGR2GRAY);

   //创建窗口和滚动条  
   namedWindow("角点检测", CV_WINDOW_AUTOSIZE);
   createTrackbar("阈值: ", "角点检测", &thresh, max_thresh, on_CornerHarris);

   //调用一次回调函数,进行初始化  
   on_CornerHarris(0, 0);

   waitKey(0);
   return(0);
}


void on_CornerHarris(int, void*){
   Mat dstImage;//目标图  
   Mat normImage;//归一化后的图  
   Mat scaledImage;//线性变换后的八位无符号整型的图  

   //置零当前需要显示的两幅图,即清除上一次调用此函数时他们的值  
   dstImage = Mat::zeros(g_srcImage.size(), CV_32FC1);
   g_srcImage1 = g_srcImage.clone();

   //进行角点检测  
   //第三个参数表示邻域大小,第四个参数表示Sobel算子孔径大小,第五个参数表示Harris参数
   cornerHarris(g_grayImage, dstImage, 2, 3, 0.04, BORDER_DEFAULT);

   // 归一化与转换  
   normalize(dstImage, normImage, 0, 255, NORM_MINMAX, CV_32FC1, Mat());
   convertScaleAbs(normImage, scaledImage);//将归一化后的图线性变换成8位无符号整型  

   // 将检测到的,且符合阈值条件的角点绘制出来  
   for (int j = 0; j < normImage.rows; j++)
   {
       for (int i = 0; i < normImage.cols; i++)
       {
           //Mat::at(j,i)获取像素值,并与阈值比较
           if ((int)normImage.at<float>(j, i) > thresh + 80)
           {
               circle(g_srcImage1, Point(i, j), 5, Scalar(10, 10, 255), 2, 8, 0);
               circle(scaledImage, Point(i, j), 5, Scalar(0, 10, 255), 2, 8, 0);
           }
       }
   }
   
   imshow("角点检测", g_srcImage1);
   imshow("角点检测2", scaledImage);

}

先看看原始图

c451a67e4f55747229f51a88a1dab9bc.png

开始检测,我把阈值设为30,检测到角点还挺多的。d69b5dcf571f3a6af94105649dfd64c1.png

我把阈值进一步提高,角点变少了。认真观察一下,是不是检测到的点都是一些亮度明显变化的临界点?比如由黑变白的边界点。59aea30fa486b51af7d3fa169cd6c1ff.png

Shi-Tomasi角点检测

除了上述的Harris角点检测方法,我们还可以采用Shi-Tomasi方法进行角点检测。Shi-Tomsi算法是Harris算法的加强版,性能当然也有相应的提高。

#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include
#include
#include

using namespace cv;
using namespace std;

Mat src, src_gray;

int maxCorners = 23;
int maxTrackbar = 100;

RNG rng(12345);  //RNG:random number generator,随机数产生器
char* source_window = "Image";

void goodFeaturesToTrack_Demo(int, void*);

int main(){
   //转化为灰度图
   src = imread("lol19.jpg", 1);
   cvtColor(src, src_gray, CV_BGR2GRAY);

   namedWindow(source_window, CV_WINDOW_AUTOSIZE);

   //创建trackbar
   createTrackbar("MaxCorners:", source_window, &maxCorners, maxTrackbar, goodFeaturesToTrack_Demo);

   imshow(source_window, src);

   goodFeaturesToTrack_Demo(0, 0);

   waitKey(0);
   return(0);
}

void goodFeaturesToTrack_Demo(int, void*){
   if (maxCorners < 1) { maxCorners = 1; }

   //初始化 Shi-Tomasi algorithm的一些参数
   vector corners;double qualityLevel = 0.01;double minDistance = 10;int blockSize = 3;bool useHarrisDetector = false;double k = 0.04;//给原图做一次备份
   Mat copy;
   copy = src.clone();// 角点检测
   goodFeaturesToTrack(src_gray,corners,maxCorners,qualityLevel,minDistance,Mat(),blockSize,useHarrisDetector,k);//画出检测到的角点cout << "** Number of corners detected: " << corners.size() << endl;int r = 4;for (int i = 0; i < corners.size(); i++)
   {
       circle(copy, corners[i], r, Scalar(rng.uniform(0, 255), rng.uniform(0, 255),
           rng.uniform(0, 255)), -1, 8, 0);
   }
   namedWindow(source_window, CV_WINDOW_AUTOSIZE);
   imshow(source_window, copy);
}

e768ff1910c4812d64a34a98485e97bb.png

结束语

由于时间和文章篇幅有限,本次总结先到这里,下次小白会为小伙伴们带来OpenCV的图像矫正,各位小伙伴敬请期待。,如果小伙伴觉得本文对自己有帮助,请帮忙点击一下右下角的“在看”,鼓励一下小白。

往期文章一览

1、通过形态学操作提取水平与垂直线

2、影响机器视觉的场景因素有哪些

3、SLAM实习生面试基础知识总结

4、OpenCV实现边缘模板匹配算法

5、我竟然用OpenCV实现了卡尔曼滤波

6、机器视觉检测相较于人工检测有哪些优势

7、每周精选公众号推荐——期待你的围观

8、小心!你看到的图像可能隐藏了重大机密

bd332e48a4562b80fd0532ac0747376d.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值