在现实世界中,角点对应于物体的拐角,道路的十字路口、丁字路口等。从图像分析的角度来定义角点可以有以下两种定义:
角点可以是两个边缘的角点;
角点是邻域内具有两个主方向的特征点;
一提到角点检测,最常用的方法莫过于Harris
角点检测,opencv
中也提供了Harris
角点检测的接口,即cornerHarris()
,但是Harris
角点检测存在很多缺陷(如角点是像素级别的,速度较慢等),opencv
中有另一个功能更为强大的函数—goodFeaturesToTrack()
,它不仅支持Harris
角点检测,也支持Shi Tomasi
算法的角点检测。但是,该函数检测到的角点依然是像素级别的,若想获取更为精细的角点坐标,有时候我们需要这种精度的角点检测(跟踪、三维重建、相机校正),则需要调用cv::cornerSubPix()
函数进一步细化处理,即亚像素。
插值方法
基于图像矩计算
曲线拟合方法(高斯曲面、多项式、椭圆曲面)
函数api
void cv::cornerSubPix(
cv::InputArray image, // 输入图像
cv::InputOutputArray corners, // 角点(既作为输入也作为输出)
cv::Size winSize, // 区域大小为 NXN; N=(winSize*2+1)
cv::Size zeroZone, // 类似于winSize,但是总具有较小的范围,Size(-1,-1)表示忽略
cv::TermCriteria criteria // 停止优化的标准
);
参数说明
cv::goodFeaturesToTrack()
中的输入图像是同一个图像。NXN
; N=(winSize*2+1)
。winSize
,但是总是具有较小的范围,通常忽略(即Size(-1, -1)
)。cv::TermCriteria::MAX_ITER
、cv::TermCriteria::EPS
(可以是两者其一,或两者均选),前者表示迭代次数达到了最大次数时停止,后者表示角点位置变化的最小值已经达到最小时停止迭代。二者均使用cv::TermCriteria()
构造函数进行指定。#include
#include
#include
using namespace std;
using namespace cv;
#define Pic_Path "E:\\picture\\"
#define Pic_Name "harris1.jpg"
int main(void)
{
Mat src,gray_src;
int threshold = 100;
int threshold_max = 255;
string pic = string(Pic_Path) + string(Pic_Name);
cout << "图片详细信息:" << pic << endl;
src = imread(pic);
if (src.empty())
{
cout << "图片不存在" << endl;
return -1;
}
namedWindow("原始图片", WINDOW_AUTOSIZE);
imshow("原始图片", src);
cvtColor(src, gray_src, COLOR_BGR2GRAY);
Mat dst;
vector<Point2f> corners;
int maxCorners = 100; //获取角点的最大数目限值
double qualityLevel = 0.01; //阈值 最大值的1%
double minDistance = 10; //角点检测最小的间距
//获取角点
goodFeaturesToTrack(gray_src, corners, maxCorners, qualityLevel, minDistance, Mat(), 3, false, 0.04);
dst = src.clone();
for (size_t i = 0; i < corners.size(); i++)
{
circle(dst, corners[i], 4, Scalar(0, 0, 255), 2, 8, 0);
cout << "int[x,y]" << corners[i].x << "," << corners[i].y << endl;
}
namedWindow("检测图像", WINDOW_AUTOSIZE);
imshow("检测图像", dst);
//对获取到的角点进行亚像素反推
Size winSize = Size(5, 5); // 区域大小为 NXN; N=(winSize*2+1)
Size zeroZone = Size(-1, -1); // 类似于winSize,但是总具有较小的范围,Size(-1,-1)表示忽略
TermCriteria tc = TermCriteria(TermCriteria::EPS + TermCriteria::MAX_ITER, 40, 0.001); //定义迭代算子 精度 次数双限制
cornerSubPix(gray_src, corners, winSize, zeroZone, tc);
for (size_t i = 0; i < corners.size(); i++)
{
cout << "float[x,y]" << corners[i].x << "," << corners[i].y << endl;
}
waitKey(0);
destroyAllWindows();
return 0;
}
图片详细信息:E:\picture\harris1.jpg
int[x,y]22,1001
int[x,y]61,999
int[x,y]87,952
int[x,y]48,1005
。。。
int[x,y]543,557
int[x,y]557,113
int[x,y]329,519
int[x,y]359,980
int[x,y]110,886
int[x,y]391,755
float[x,y]18.7803,998.23
float[x,y]62.6927,997.423
float[x,y]88.4064,952.118
。。。
float[x,y]333.192,517.411
float[x,y]360.236,979.549
float[x,y]108.555,886.046
float[x,y]392.311,753.397
参考链接:https://blog.csdn.net/qq_30815237/article/details/87179830