博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
OpenCV探索之路(十五):角点检测
阅读量:4616 次
发布时间:2019-06-09

本文共 4350 字,大约阅读时间需要 14 分钟。

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

什么是角点?

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

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

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

  • 边缘
  • 角点(感兴趣关键点)
  • 斑点(感兴趣区域)

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

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
(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);}

先看看原始图

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

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

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);}

转载于:https://www.cnblogs.com/xieyulin/p/7060891.html

你可能感兴趣的文章
创建添加表格
查看>>
Javascript触屏手势库-JTouch
查看>>
Ext.Net学习笔记14:Ext.Net GridPanel Grouping用法
查看>>
Struts2日期类型转换
查看>>
树的遍历
查看>>
iOS开发~UI布局(二)storyboard中autolayout和size class的使用详解
查看>>
排序算法之 Non-recursive Merge Sort
查看>>
初识Spring框架IOC属性注入
查看>>
.net core 在视图中快速获取路由(Areas、Controller、Action)
查看>>
SpringMVC详解(二)
查看>>
MVC中子页面如何引用模板页中的jquery脚本
查看>>
$.extend、$.fn.extend
查看>>
DEDE去掉会员登录及注册验证码的方法
查看>>
反射全的方法
查看>>
注入(2)--APC(Asynchronous Procedure Call)注入(异步过程调用)
查看>>
2014 HDU多校弟五场J题 【矩阵乘积】
查看>>
iOS-隐藏Navigation导航栏线
查看>>
js_<a>
查看>>
BZOJ3562: [SHOI2014]神奇化合物
查看>>
BZOJ1877: [SDOI2009]晨跑
查看>>