一:内容介绍
本节主要介绍OpenCV的imgproc模块的角点检测(Feature Detection)部分:
1. Harris角点检测
2. Shi-Tomasi角点检测
3. 亚像素级角点检测
二:学习笔记
1. harris角点还是挺常见的,Harris角点 这篇文章介绍的比较好。
————————–补充于16/11/10————————————-
昨天帮老师做几页关于harris的PPT,又回顾了一遍harris算法,这里有几页比较好的讲解,分享一下。另参考wiki Corner detection
PPT上字写的烂,不要介意,哈哈。
—————————————————————
2. 亚像素级角点检测这一点,书中介绍的比较简略。定理是:在角点q附近的点的灰度梯度均垂直于该点与角点的连线。根据这条定理,我们可以找到多个关于p和q的方程组,从而求解出q的位置。深入探讨,详见Harris角点提取实现亚像素级摄像机自标定
3 . 本节函数清单
三:相关源码及解析
本章示例较多,示例列表:
1.Harris角点检测与绘制
2.Shi-Tomasi角点检测
3.亚像素级角点检测
1 . Harris角点检测与绘制
源码:
#include
#include
using namespace std;
using namespace cv;
#define WINDOW_NAME1 "【程序窗口1】"
#define WINDOW_NAME2 "【程序窗口2】"
Mat g_srcImage, g_srcImage1, g_grayImage;
int thresh = 30; //当前阈值
int max_thresh = 175; //最大阈值
void on_CornerHarris(int, void*); //回调函数
int main() {
g_srcImage = imread("poster_house.jpg");
imshow("【原始图】", g_srcImage);
g_srcImage1 = g_srcImage.clone();
cvtColor(g_srcImage1, g_grayImage, COLOR_BGR2GRAY);
namedWindow(WINDOW_NAME1);
createTrackbar("阈值:", WINDOW_NAME1, &thresh, max_thresh, on_CornerHarris);
on_CornerHarris(0, 0);
while (waitKey(9)!=27);
return 0;
}
void on_CornerHarris(int, void*) {
Mat dstImage, normImage, scaledImage;
dstImage = Mat::zeros(g_srcImage.size(), CV_32FC1);
g_srcImage1 = g_srcImage.clone();
cornerHarris(g_grayImage, dstImage, 2, 3, 0.04); //进行角点检测
normalize(dstImage, normImage, 0, 255, NORM_MINMAX); //归一化
convertScaleAbs(normImage, scaledImage); //转换为8位无符号整形
//将检测到的,且符合阈值条件的角点绘制出来
for (int j = 0; j < normImage.rows; j++) {
for (int i = 0; i < normImage.cols; i++) {
if ((int)normImage.at<float>(j, i)>thresh+80) {
circle(g_srcImage1, Point(i, j), 5, Scalar(10, 10, 255), 2);
circle(scaledImage, Point(i, j), 5, Scalar(10, 10, 255), 2);
}
}
}
imshow(WINDOW_NAME1, g_srcImage1);
imshow(WINDOW_NAME2, scaledImage);
}
素材:
效果图:
提示:
无
2 . Shi-Tomasi角点检测
源码:
#include
#include
using namespace std;
using namespace cv;
#define WINDOW_NAME "【Shi-Tomasi 角点检测】"
Mat g_srcImage, g_grayImage;
int g_maxCornerNumber = 33, g_maxTrackbarNumber=500;
RNG g_rng;
void on_GoodFeaturesToTrack(int, void*);
int main() {
g_srcImage = imread("poster_castle_1.jpg");
cvtColor(g_srcImage, g_grayImage, COLOR_BGR2GRAY);
namedWindow(WINDOW_NAME);
createTrackbar("最大角点数", WINDOW_NAME, &g_maxCornerNumber, g_maxTrackbarNumber, on_GoodFeaturesToTrack);
imshow(WINDOW_NAME, g_srcImage);
on_GoodFeaturesToTrack(0, 0);
while (waitKey(9)!=27);
return 0;
}
void on_GoodFeaturesToTrack(int, void*) {
if (g_maxCornerNumber <= 1) g_maxCornerNumber = 1;
vector corners;
double qualityLevel = 0.01; //角点检测可接受的最小特征值
double minDistance = 10; //角点之间的最小距离
goodFeaturesToTrack(g_grayImage, //输入图像
corners, //检测到角点的
g_maxCornerNumber, //角点的最大数量
qualityLevel, //角点检测可接受的最小特征值
minDistance ); //角点之间的最小距离
cout << "此次检测到的角点数量为:" << corners.size() << endl;
Mat copy = g_srcImage.clone(); //复制源图像到一个临时变量
int r = 4;
for (unsigned 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);
imshow(WINDOW_NAME, copy);
}
素材:
效果图:
提示:
无
3 . 亚像素级角点检测
源码:
#include
#include
using namespace std;
using namespace cv;
#define WINDOW_NAME "【Shi-Tomasi 角点检测】"
Mat g_srcImage, g_grayImage;
int g_maxCornerNumber = 33, g_maxTrackbarNumber = 500;
RNG g_rng;
void on_GoodFeaturesToTrack(int, void*);
int main() {
g_srcImage = imread("poster_building_2.jpg");
cvtColor(g_srcImage, g_grayImage, COLOR_BGR2GRAY);
namedWindow(WINDOW_NAME);
createTrackbar("最大角点数", WINDOW_NAME, &g_maxCornerNumber, g_maxTrackbarNumber, on_GoodFeaturesToTrack);
imshow(WINDOW_NAME, g_srcImage);
on_GoodFeaturesToTrack(0, 0);
while (waitKey(9) != 27);
return 0;
}
void on_GoodFeaturesToTrack(int, void*) {
if (g_maxCornerNumber <= 1) g_maxCornerNumber = 1;
vector corners;
double qualityLevel = 0.01; //角点检测可接受的最小特征值
double minDistance = 10; //角点之间的最小距离
goodFeaturesToTrack(g_grayImage, //输入图像
corners, //检测到角点的
g_maxCornerNumber, //角点的最大数量
qualityLevel, //角点检测可接受的最小特征值
minDistance); //角点之间的最小距离
cout << "此次检测到的角点数量为:" << corners.size() << endl;
Mat copy = g_srcImage.clone(); //复制源图像到一个临时变量
int r = 4;
for (unsigned 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);
imshow(WINDOW_NAME, copy);
cornerSubPix(g_grayImage, corners, Size(5, 5), Size(-1, -1), TermCriteria(TermCriteria::EPS+TermCriteria::MAX_ITER, 40, 0.001));
for (int i = 0; i < corners.size(); i++) {
cout << ">>精确点坐标[" << i << "] (" << corners[i].x << "," << corners[i].y << ")" << endl;
}
}