OpenCV图像特征提取与检测C++(二)Harris角点检测、Shi-Tomasi 角点检测、亚像素级别角点检测
图像特征类型可以分为三种:
边缘,角点,斑点。
其中,角点是个很特殊的存在,他们在图像中可以轻松定位,因为角点位于两条边缘的交点,代表了两条边缘变化的方向上的点,所以他们是可以精确定位的二维特征,甚至可以达到亚像素精度。
角点定义:如果某一点在任意方向的一个微小变动都会引起灰度很大的变化,则称为角点。
角点通常被定义为两条边的交点,更严格的说,角点的局部邻域应该具有两个不同区域的不同方向的边界
1,一阶导数(灰度的梯度)的局部最大化所对应的像素点
2,两天及两条以上边缘的交点
3,图像中梯度值和梯度方向的变化速率都很高的点
4,角点处的一阶导数最大,二阶导数为0,指示物体边缘变化不连续的方向
角点检测算法分为三类:
1,基于灰度图像的角点检测
2,基于二值图像的角点检测
3,基于轮廓曲线的角点检测
角点检测(Corner Detection)是计算机视觉系统中用来获得图像特征的一种方法,广泛应用于运动检测、图像匹配、视频跟踪、三维建模和目标识别等领域中。也称为特征点检测。
角点响应函数R为:
R=λ1*λ2-k(λ1+λ2)的平方,k在0.04-0.06之间
Harris角点检测:
角点响应函数R为:
R=λ1*λ2-k(λ1+λ2)的平方,k在0.04-0.06之间
API:
void cornerHarris(InputArray src, 源图像,填Mat类的对象即可,且需为单通道8位或者浮点型图像 OutputArray dst, 这个参数用于存放Harris角点检测的输出结果,和源图片有一样的尺寸和类型。 int blockSize, 领域的大小即计算y1y2时候矩阵的大小 int ksize, 表示Sobel()算子的孔径大小 double k, k在0.04-0.06之间 intborderType=BORDER_DEFAULT 图像像素的边界模式 )
步骤:
- 转为灰度图像
- 角点检测找出角点
- 转为二值图像
代码:
#include <opencv2/opencv.hpp> #include<iostream> #include<math.h> #include <string> #include<fstream> using namespace cv; using namespace std; Mat src,graysrc; int thresh_v = 130; int thresh_max = 255; void m_harris(int, void*) { Mat dst,nordst,scadst,retdst; dst = Mat::zeros(src.size(), CV_32FC1); cornerHarris(graysrc, dst, 2, 3, 0.04); normalize(dst, nordst, 0, 255, NORM_MINMAX,CV_32FC1 );// 检测出的元素值范围不确定,而且有正有负,归一化 convertScaleAbs(nordst, scadst, 1, 0);// 将元素值取绝对值,且将输出图像深度变为 CV_8U retdst = src.clone(); for (int row = 0; row < retdst.rows; row++) { uchar* curRow = scadst.ptr(row); for (int col = 0; col < retdst.cols; col++) { int value = (int)*curRow; if (value > thresh_v) { // 过滤,角点响应值 大于 阈值才显示 circle(retdst, Point(col, row), 2, Scalar(0, 0, 255), 2); } curRow++; } } imshow("output", retdst); } int main() { src = imread("C:/Users/Administrator/Desktop/pic/1-H.jpg"); cvtColor(src, graysrc, CV_BGR2GRAY); imshow("input", src); m_harris(0, 0); createTrackbar("yuzhi", "output", &thresh_v, thresh_max, m_harris); waitKey(0); }
结果:
Shi-Tomasi 角点检测
Shi-Tomasi 算法是Harris 算法的改进。Harris 算法最原始的定义是将矩阵 M 的行列式值与 M 的迹相减,再将差值同预先给定的阈值进行比较。后来Shi 和Tomasi 提出改进的方法,若两个特征值中较小的一个大于最小阈值,则会得到强角点。
唯一不同的是在使用矩阵 特征值 λ1 λ2 计算角度响应的时候
R = min(λ1, λ2)
API:
void goodFeaturesToTrack( // Shi-Tomasi角点检测 InputArray image, // 灰度图像 OutputArray corners, // 检测出来的角点在输入图像的Point int maxCorners, // -maxCorners 表示返回角点的数目,如果检测出来的角点数目大于最大数目则返回响应值最强前maxCorners数目。 double qualityLevel, // -qualityLevel表示最小可接受的向量值1500, 0.01, 15 double minDistance, // -minDistance两个角点之间的最小距离(欧几里得距离) InputArray mask = noArray(), int blockSize = 3, // -blockSize 计算导数微分不同的窗口大小 bool useHarrisDetector = false, // -useHarrisDetector是否使用Harris角点检测,设置为false的时候 下一个参数 k 无效 double k = 0.04 // 最好 0.04~0.06 );
代码:
#include <opencv2/opencv.hpp> #include<iostream> #include<math.h> #include <string> #include<fstream> using namespace cv; using namespace std; Mat src, graysrc; int thresh_v = 5; int thresh_max = 255; void shi_tomasi(int, void*) { vector<Point2f>corners; Mat dst = src.clone(); goodFeaturesToTrack(graysrc, corners, thresh_v, 0.01, 10); for (int i = 0; i < corners.size(); i++) { circle(dst, corners[i], 2, Scalar(255, 0, 233), 2); } imshow("output", dst); } int main() { src = imread("C:/Users/Administrator/Desktop/pic/1-H.jpg"); imshow("input", src); cvtColor(src, graysrc, CV_BGR2GRAY); shi_tomasi(0, 0); createTrackbar("yuhzi", "output", &thresh_v, thresh_max, shi_tomasi); waitKey(0); }
结果:
亚像素级别角点检测
提高检测精准度
理论与现实总是不一致的,实际情况下几乎所有的角点不会是一个真正的准确像素点。
检测出的点(100, 5) 实际上可能是(100.234, 5.789),可以使用亚像素定位确定准确位置
- 跟踪
- 三维重建
- 相机校正
亚像素定位方法
- 插值方法
- 基于图像矩计算
- 曲线拟合方法 -(高斯曲面(最常用)、多项式、椭圆曲面)
代码:
#include <opencv2/opencv.hpp> #include<iostream> #include<math.h> #include <string> #include<fstream> using namespace cv; using namespace std; Mat src, graysrc; int thresh_v = 50; int thresh_max = 255; void sub_dip(int, void*) { vector<Point2f>corners; goodFeaturesToTrack(graysrc, corners, thresh_v, 0.01, 10); cout << "corner_size:" << corners.size() << endl; Mat dst = src.clone(); for (int i = 0; i < corners.size(); i++) { cout << i << ".point[x,y]=" << corners[i].x << "," << corners[i].y << endl; circle(dst, corners[i], 2, Scalar(0, 255, 255), 2); } imshow("output", dst); Size winsize = Size(5, 5);//窗口不要太大,不然亚像素可能会被干扰 Size zerozone = Size(-1, -1);// 拟合时使用 零区域 //TermCriteria类是用来作为迭代算法的终止条件的,参数:类型(EPS表示迭代到阈值终止), //第二个参数为迭代的最大次数,最后一个是特定的阈值 TermCriteria tc = TermCriteria(TermCriteria::EPS + TermCriteria::MAX_ITER, 40, 0.001); cornerSubPix(graysrc, corners, winsize, zerozone, tc);//亚像素定位,为后续计算提供更高精确度的值 cout << "subpix corner_size:" << corners.size() << endl; for (size_t i = 0; i < corners.size(); i++) { cout << i << ".point[x,y]=" << corners[i].x << "," << corners[i].y << endl;// 亚像素定位出来的,精确度较高,浮点值 } }
结果:
- OpenCV图像特征提取与检测C++(四)仿射变换、积分图计算
- 【图像特征提取18】Harris及Shi-Tomasi原理及源码解析
- OpenCV图像特征提取与检测C++(五)特征描述子--Brute-Force匹配、FLANN特征匹配、平面对象识别、AKAZE局部特征检测与匹配、BRISK特征检测与匹配、ORB特征提检测与匹配
- Opencv Shi-Tomasi 角点检测 & 适合于跟踪的图像特征
- OpenCV图像特征提取与检测C++(七) 级联分类器 HAAR与LBP– 人脸检测(图像和视频)
- OpenCV图像特征提取与检测C++(八)视频中人脸检测与眼睛跟踪
- 图像处理——角点检测(Harris、Shi-Tomasi、亚像素检测)
- 目标检测的图像特征提取之(四)OpenCV中BLOB特征提取与几何形状分类
- 基于C++和OpenCv的SIFT_图像局部特征检测算法代码的实现
- moravec、harris、Shi-Tomasi角点检测的简介及OpenCV代码实现
- 图像边缘检测原理&何谓角点及Harris角点的基本原理&SURF特征提取简介
- android openCV检测图像的基本特征,包括Canny边缘检测、Harris角点检测、霍夫直线检测-基于Android studio
- OpenCV之feature2d 模块. 2D特征框架(1)Harris 角点检测子 Shi-Tomasi角点检测子 定制化创建角点检测子 亚像素级的角点检测 特征点检测
- OpenCV环境下用算法moravec、harris、Shi-Tomasi进行角点检测
- OpenCV3_C++_Akaze()图像的特征点提取 实例
- OPENCV的学习:图像特征检测之Harris角点算法
- 【图像特征提取12】OpenCv的SIFT图像局部特征提取描述算法C++代码的实现
- 《python+opencv实践》四、图像特征提取与描述——31 Shi-Tomasi 角点检测& 适合于跟踪的图像特征
- opencv图像特征检测及匹配(harris,sift,surf,fast,breif,orb,BFmatch,FlannBasedMatcher)