OpenCV学习笔记__角点检测
2015-09-29 12:55
423 查看
1、Harris角点检测
引言:
a.图像特征类型可以被分为如下三种:
- <1>边缘
- <2>角点 (感兴趣关键点)
- <3>斑点(Blobs)(感兴趣区域)
b.在当前的图像处理领域,角点检测算法可归纳为三类:
- <1>基于灰度图像的角点检测
- <2>基于二值图像的角点检测
- <3>基于轮廓曲线的角点检测
定义:角点位于两条边缘的交点处,代表了两个边缘变化的方向上的点,,所以他们是可以精确定位的二维特征,甚至可以达到亚像素的精度。且其图像梯度有很高的变化,这种变化是可以用来帮助检测角点的。需要注意的是,角点与位于相同强度区域上的点不同,与物体轮廓上的点也不同,因为轮廓点难以在相同的其他物体上精确定位。角点通常被定义为两条边的交点,更严格的说,角点的局部邻域应该具有两个不同区域的不同方向的边界。而实际应用中,大多数所谓的角点检测方法检测的是拥有特定特征的图像点,而不仅仅是“角点”。这些特征点在图像中有具体的坐标,并具有某些数学特征,如局部最大或最小灰度、某些梯度特征等。
另外,关于角点的具体描述可以有几种:
- 一阶导数(即灰度的梯度)的局部最大所对应的像素点;
- 两条及两条以上边缘的交点;
- 图像中梯度值和梯度方向的变化速率都很高的点;
- 角点处的一阶导数最大,二阶导数为零,指示物体边缘变化不连续的方向。
cornerHarris 函数用于在OpenCV中运行Harris角点检测算子处理图像
- 第一个参数,InputArray类型的src,输入图像,即源图像,填Mat类的对象即可,且需为单通道8位或者浮点型图像。
- 第二个参数,OutputArray类型的dst,函数调用后的运算结果存在这里,即这个参数用于存放Harris角点检测的输出结果,和源图片有一样的尺寸和类型。
- 第三个参数,int类型的blockSize,表示邻域的大小,更多的详细信息在cornerEigenValsAndVecs()中有讲到。
- 第四个参数,int类型的ksize,表示Sobel()算子的孔径大小。
- 第五个参数,double类型的k,Harris参数。
- 第六个参数,int类型的borderType,图像像素的边界模式,注意它有默认值BORDER_DEFAULT。更详细的解释,参考borderInterpolate( )函数。
2、Shi-Tomasi 角点检测(对Harris算法的改进)
函数:
goodFeaturesToTrack(image,corners,maxCorners,qualityLevel,minDistance,noArray( ),blockSize,false,k)
***3、定制化创建角点检测子
- 使用 OpenCV 函数 cornerEigenValsAndVecs 来计算像素对应的本征值和本征向量来确定其是否是角点。
- 使用OpenCV 函数 cornerMinEigenVal 通过最小化本征值来进行角点检测。
- 用上述两个函数实现一个定制化的Harris detector,类似Shi-Tomasi检测子。
4、亚像素级的角点检测
- 使用OpenCV函数 cornerSubPix 寻找更精确的角点位置 (不是整数类型的位置,而是更精确的浮点类型位置).
即进行几何测量。
引言:
a.图像特征类型可以被分为如下三种:
- <1>边缘
- <2>角点 (感兴趣关键点)
- <3>斑点(Blobs)(感兴趣区域)
b.在当前的图像处理领域,角点检测算法可归纳为三类:
- <1>基于灰度图像的角点检测
- <2>基于二值图像的角点检测
- <3>基于轮廓曲线的角点检测
定义:角点位于两条边缘的交点处,代表了两个边缘变化的方向上的点,,所以他们是可以精确定位的二维特征,甚至可以达到亚像素的精度。且其图像梯度有很高的变化,这种变化是可以用来帮助检测角点的。需要注意的是,角点与位于相同强度区域上的点不同,与物体轮廓上的点也不同,因为轮廓点难以在相同的其他物体上精确定位。角点通常被定义为两条边的交点,更严格的说,角点的局部邻域应该具有两个不同区域的不同方向的边界。而实际应用中,大多数所谓的角点检测方法检测的是拥有特定特征的图像点,而不仅仅是“角点”。这些特征点在图像中有具体的坐标,并具有某些数学特征,如局部最大或最小灰度、某些梯度特征等。
另外,关于角点的具体描述可以有几种:
- 一阶导数(即灰度的梯度)的局部最大所对应的像素点;
- 两条及两条以上边缘的交点;
- 图像中梯度值和梯度方向的变化速率都很高的点;
- 角点处的一阶导数最大,二阶导数为零,指示物体边缘变化不连续的方向。
cornerHarris 函数用于在OpenCV中运行Harris角点检测算子处理图像
- 第一个参数,InputArray类型的src,输入图像,即源图像,填Mat类的对象即可,且需为单通道8位或者浮点型图像。
- 第二个参数,OutputArray类型的dst,函数调用后的运算结果存在这里,即这个参数用于存放Harris角点检测的输出结果,和源图片有一样的尺寸和类型。
- 第三个参数,int类型的blockSize,表示邻域的大小,更多的详细信息在cornerEigenValsAndVecs()中有讲到。
- 第四个参数,int类型的ksize,表示Sobel()算子的孔径大小。
- 第五个参数,double类型的k,Harris参数。
- 第六个参数,int类型的borderType,图像像素的边界模式,注意它有默认值BORDER_DEFAULT。更详细的解释,参考borderInterpolate( )函数。
#include "opencv2/highgui/highgui.hpp" #include "opencv2/imgproc/imgproc.hpp" #include <iostream> #include <stdio.h> #include <stdlib.h> using namespace cv; using namespace std; /// 定义全局变量 Mat src, src_gray; int thresh = 200; int max_thresh = 255; char* source_window = "Source image"; char* corners_window = "Corners detected"; /// 函数声明 void cornerHarris_demo(int, void*); /// 主函数 int main(int argc, char** argv) { /// 加载原始图像以及将它转换为灰度图像 src = imread("e:\\1.jpg"); cvtColor(src, src_gray, CV_BGR2GRAY); /// 创建一个窗口和滑动条 namedWindow(source_window, CV_WINDOW_AUTOSIZE); createTrackbar("Threshold: ", source_window, &thresh, max_thresh, cornerHarris_demo); imshow(source_window, src); cornerHarris_demo(0, 0); waitKey(0); return(0); } /** 函数 cornerHarris_demo */ void cornerHarris_demo(int, void*) { Mat dst, dst_norm, dst_norm_scaled; dst = Mat::zeros(src.size(), CV_32FC1); /// 参数 int blockSize = 2; int apertureSize = 3; double k = 0.04; /// 进行角点检测 cornerHarris(src_gray, dst, blockSize, apertureSize, k, BORDER_DEFAULT); /// 归一化与转换 normalize(dst, dst_norm, 0, 255, NORM_MINMAX, CV_32FC1, Mat()); convertScaleAbs(dst_norm, dst_norm_scaled);//将归一化后的图线性变换成8位无符号整型 /// 符合阈值条件的,将角点绘制出来 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) > thresh) { circle(dst_norm_scaled, Point(i, j), 5, Scalar(0), 2, 8, 0); } } } /// 显示最终效果 namedWindow(corners_window, CV_WINDOW_AUTOSIZE); imshow(corners_window, dst_norm_scaled); }
2、Shi-Tomasi 角点检测(对Harris算法的改进)
函数:
goodFeaturesToTrack(image,corners,maxCorners,qualityLevel,minDistance,noArray( ),blockSize,false,k)
#include "opencv2/highgui/highgui.hpp" #include "opencv2/imgproc/imgproc.hpp" #include <iostream> using namespace cv; using namespace std; #define WINDOW_NAME "【Shi-Tomasi角点检测】" Mat g_srcImage, g_grayImage; int g_maxCornerNumber = 33; int g_maxTrackbarNumber = 500; RNG g_rng(12345);//初始化随机数生成器 int main() { //【1】载入源图像并将其转换为灰度图 g_srcImage = imread("e:\\1.jpg"); cvtColor(g_srcImage, g_grayImage, CV_BGR2GRAY); //【2】创建窗口和滑动条,并进行显示和回调函数初始化 namedWindow(WINDOW_NAME, CV_WINDOW_AUTOSIZE); createTrackbar("最大角点数", WINDOW_NAME, &g_maxCornerNumber, g_maxTrackbarNumber, on_GoodFeaturesToTrack); imshow(WINDOW_NAME, g_srcImage); on_GoodFeaturesToTrack(0, 0); waitKey(0); return(0); } void on_GoodFeaturesToTrack(int, void*) { //【1】对变量小于等于1时的处理 if (g_maxCornerNumber <= 1) { g_maxCornerNumber = 1; } //【2】Shi-Tomasi算法(goodFeaturesToTrack函数)的参数准备 vector<Point2f> corners; double qualityLevel = 0.01;//角点检测可接受的最小特征值 double minDistance = 10;//角点之间的最小距离 int blockSize = 3;//计算导数自相关矩阵时指定的邻域范围 double k = 0.04;//权重系数 Mat copy = g_srcImage.clone(); //复制源图像到一个临时变量中,作为感兴趣区域 //【3】进行Shi-Tomasi角点检测 goodFeaturesToTrack(g_grayImage,//输入图像 corners,//检测到的角点的输出向量 g_maxCornerNumber,//角点的最大数量 qualityLevel,//角点检测可接受的最小特征值 minDistance,//角点之间的最小距离 Mat(),//感兴趣区域 blockSize,//计算导数自相关矩阵时指定的邻域范围 false,//不使用Harris角点检测 k);//权重系数 //【4】输出文字信息 cout << "\t>此次检测到的角点数量为:" << corners.size() << endl; //【5】绘制检测到的角点 int r = 4; for (int i = 0; i < corners.size(); i++) { //以随机的颜色绘制出角点 circle(copy, corners[i], r, Scalar(g_rng.uniform(0, 255), g_rng.uniform(0, 255), g_rng.uniform(0, 255)), -1, 8, 0); } //【6】显示(更新)窗口 imshow(WINDOW_NAME, copy); }
***3、定制化创建角点检测子
- 使用 OpenCV 函数 cornerEigenValsAndVecs 来计算像素对应的本征值和本征向量来确定其是否是角点。
- 使用OpenCV 函数 cornerMinEigenVal 通过最小化本征值来进行角点检测。
- 用上述两个函数实现一个定制化的Harris detector,类似Shi-Tomasi检测子。
4、亚像素级的角点检测
- 使用OpenCV函数 cornerSubPix 寻找更精确的角点位置 (不是整数类型的位置,而是更精确的浮点类型位置).
即进行几何测量。
#include "opencv2/highgui/highgui.hpp" #include "opencv2/imgproc/imgproc.hpp" #include <iostream> #include <stdio.h> #include <stdlib.h> using namespace cv; using namespace std; /// Global variables Mat src, src_gray; int maxCorners = 10; int maxTrackbar = 25; RNG rng(12345); char* source_window = "Image"; /// Function header void goodFeaturesToTrack_Demo(int, void*); /** @function main */ int main(int argc, char** argv) { /// Load source image and convert it to gray src = imread("e:\\1.jpg"); cvtColor(src, src_gray, CV_BGR2GRAY); /// Create Window namedWindow(source_window, CV_WINDOW_AUTOSIZE); /// Create Trackbar to set the number of corners createTrackbar("Max corners:", source_window, &maxCorners, maxTrackbar, goodFeaturesToTrack_Demo); imshow(source_window, src); goodFeaturesToTrack_Demo(0, 0); waitKey(0); return(0); } /** * @function goodFeaturesToTrack_Demo.cpp * @brief Apply Shi-Tomasi corner detector */ void goodFeaturesToTrack_Demo(int, void*) { if (maxCorners < 1) { maxCorners = 1; } /// Parameters for Shi-Tomasi algorithm vector<Point2f> corners; double qualityLevel = 0.01; double minDistance = 10; int blockSize = 3; bool useHarrisDetector = false; double k = 0.04; /// Copy the source image Mat copy; copy = src.clone(); /// Apply corner detection goodFeaturesToTrack(src_gray, corners, maxCorners, qualityLevel, minDistance, Mat(), blockSize, useHarrisDetector, k); /// Draw corners detected 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); } /// Show what you got namedWindow(source_window, CV_WINDOW_AUTOSIZE); imshow(source_window, copy); /// Set the neeed parameters to find the refined corners Size winSize = Size(5, 5); Size zeroZone = Size(-1, -1); TermCriteria criteria = TermCriteria(CV_TERMCRIT_EPS + CV_TERMCRIT_ITER, 40, 0.001); /// Calculate the refined corner locations cornerSubPix(src_gray, corners, winSize, zeroZone, criteria); /// Write them down for (int i = 0; i < corners.size(); i++) { cout << " -- Refined Corner [" << i << "] (" << corners[i].x << "," << corners[i].y << ")" << endl; } }得到的窗口和之前的Shi-Tomasi 角点检测一致,区别在于在控制台窗口中输出了检测到的浮点型亚像素角点精确坐标值。
相关文章推荐
- 九个uname命令获取Linux系统详情的实例
- POJ 2443:Set Operation 经典位运算好题
- POJ 2443:Set Operation 经典位运算好题
- Linux中查看进程的多线程
- 精通Linux的“kill”命令
- 30个实例详解TOP命令
- Linux date命令 - 显示和设置系统日期与时间
- 用 Python 脚本实现对 Linux 服务器的监控
- Linux vmstat:报告虚拟内存统计的工具
- 我的Docker学习之旅<一>
- Linux 性能监控的18个命令行工具
- Linux字符设备驱动总结程序(二)
- Linux使用locate命令定位文件
- centos 6.5下快速搭建ftp服务器
- codeforces 581C. Developing Skills 解题报告
- LINUX常用命令
- tengine + tomcat 安装整合实现高可用负载均衡
- Linux下常用的shell命令记录
- Linux SSH远程文件/目录传输命令scp
- Linux下的进程管理