opencv学习之路(32)、角点检测

时间:2021-11-21 07:24:21

一、角点检测的相关概念

opencv学习之路(32)、角点检测

opencv学习之路(32)、角点检测

opencv学习之路(32)、角点检测

二、Harris角点检测——cornerHarris()

opencv学习之路(32)、角点检测

参考网址: http://www.cnblogs.com/ronny/p/4009425.html

opencv学习之路(32)、角点检测

#include "opencv2/opencv.hpp"
#include<iostream>
using namespace std;
using namespace cv; void main()
{
Mat img = imread("E://3.jpg");
imshow("src", img);
Mat result = img.clone();
Mat gray, dst , corner_img;//corner_img存放检测后的角点图像
cvtColor(img, gray, CV_BGR2GRAY); cornerHarris(gray, corner_img, , , 0.04);//cornerHarris角点检测
//imshow("corner", corner_img);
threshold(corner_img, dst, 0.015, , CV_THRESH_BINARY);
imshow("dst", dst); int rowNumber = gray.rows; //获取行数
int colNumber = gray.cols; //获取每一行的元素
cout << rowNumber << endl;
cout << colNumber << endl;
cout << dst.type() << endl; for (int i = ; i<rowNumber; i++)
{
for (int j = ; j<colNumber; j++)
{
if (dst.at<float>(i, j) == )//二值化后,灰度值为255为角点
{
circle(result, Point(j, i),, Scalar(, , ), , );
}
}
} imshow("result", result);
waitKey();
}

opencv学习之路(32)、角点检测

浅墨代码

http://blog.csdn.net/poem_qianmo/article/details/29356187

#include "opencv2/opencv.hpp"
#include<iostream>
using namespace std;
using namespace cv; #define WINDOW_NAME1 "【程序窗口1】"
#define WINDOW_NAME2 "【程序窗口2】"
Mat g_srcImage, g_srcImage1, g_grayImage;
int thresh = ; //当前阈值
int max_thresh = ; //最大阈值 void on_CornerHarris(int, void*)
{
Mat dstImage;//目标图
Mat normImage;//归一化后的图
Mat scaledImage;//线性变换后的八位无符号整型的图 //初始化:置零当前需要显示的两幅图,即清除上一次调用此函数时他们的值
dstImage = Mat::zeros(g_srcImage.size(), CV_32FC1);
g_srcImage1 = g_srcImage.clone(); //进行角点检测
cornerHarris(g_grayImage, dstImage, , , 0.04);
// 归一化与转换
normalize(dstImage, normImage, , , NORM_MINMAX, CV_32FC1, Mat());
convertScaleAbs(normImage, scaledImage);//将归一化后的图线性变换成8位无符号整型 // 进行绘制:将检测到的,且符合阈值条件的角点绘制出来
for (int j = ; j < normImage.rows; j++)
{
for (int i = ; i < normImage.cols; i++)
{
if ((int)normImage.at<float>(j, i) > thresh + )
{
circle(g_srcImage1, Point(i, j), , Scalar(, , ), , , );
circle(scaledImage, Point(i, j), , Scalar(, , ), , , );
}
}
}
imshow(WINDOW_NAME1, g_srcImage1);
imshow(WINDOW_NAME2, scaledImage); } static void ShowHelpText()
{
printf("\n\n\n\t\t\t【欢迎来到Harris角点检测示例程序~】\n\n");
printf("\n\n\n\t请调整滚动条观察图像效果~\n\n");
printf("\n\n\t\t\t\t\t\t\t\t by浅墨");
} void main()
{
system("color 3F");
ShowHelpText(); //载入原始图并进行克隆保存
g_srcImage = imread("E://1.jpg", );
if (!g_srcImage.data) { printf("读取图片错误,请确定目录下是否有imread函数指定的图片存在~! \n"); return ; }
imshow("原始图", g_srcImage);
g_srcImage1 = g_srcImage.clone();
cvtColor(g_srcImage1, g_grayImage, CV_BGR2GRAY); //创建窗口和滚动条
namedWindow(WINDOW_NAME1, CV_WINDOW_NORMAL);
createTrackbar("阈值: ", WINDOW_NAME1, &thresh, max_thresh, on_CornerHarris);
on_CornerHarris(, );//调用一次回调函数,进行初始化 waitKey();
}

opencv学习之路(32)、角点检测

三、Shi-Tomasi角点检测——goodFeaturesToTrack()

opencv学习之路(32)、角点检测

opencv学习之路(32)、角点检测

#include "opencv2/opencv.hpp"
#include<iostream>
using namespace std;
using namespace cv; void main()
{
Mat src = imread("E://0.jpg");
imshow("src", src);
Mat result = src.clone();
Mat gray;
cvtColor(src, gray,CV_BGR2GRAY); vector<Point2f>corners;//Point2f类型的向量:存储每个角点的坐标
//输入图,向量,最大角点数量,角点的最小特征值,角点间最小距离,掩码(Mat()表示掩码为空),blocksize,是否使用Harris角点检测,权重系数
goodFeaturesToTrack(gray, corners, ,0.01,,Mat(),,false,0.04);
cout << "角点数量" << corners.size() << endl; //画圆标注角点
for (int i = ; i < corners.size(); i++)
circle(result, corners[i], , Scalar(, , ),,);
imshow("result", result);
waitKey();
}

opencv学习之路(32)、角点检测

浅墨大神代码(加了滑动条效果)

#include "opencv2/opencv.hpp"
#include <iostream>
using namespace cv;
using namespace std; #define WINDOW_NAME "【Shi-Tomasi角点检测】"
Mat g_srcImage, g_grayImage;
int g_maxCornerNumber = ;
int g_maxTrackbarNumber = ;
RNG g_rng();//初始化随机数生成器 //-----------------------------【on_GoodFeaturesToTrack( )函数】----------------------------
// 描述:响应滑动条移动消息的回调函数
//----------------------------------------------------------------------------------------------
void on_GoodFeaturesToTrack(int, void*)
{
//【1】对变量小于等于1时的处理
if (g_maxCornerNumber <= ) { g_maxCornerNumber = ; } //【2】Shi-Tomasi算法(goodFeaturesToTrack函数)的参数准备
vector<Point2f> corners;
double qualityLevel = 0.01;//角点检测可接受的最小特征值
double minDistance = ;//角点之间的最小距离
int blockSize = ;//计算导数自相关矩阵时指定的邻域范围
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 = ;
for (int i = ; i < corners.size(); i++)
{
//以随机的颜色绘制出角点
circle(copy, corners[i], r, Scalar(g_rng.uniform(, ), g_rng.uniform(, ),
g_rng.uniform(, )), -, , );
} //【6】显示(更新)窗口
imshow(WINDOW_NAME, copy);
} static void ShowHelpText()
{
//输出欢迎信息和OpenCV版本
printf("\n\n\t\t\t非常感谢购买《OpenCV3编程入门》一书!\n");
printf("\n\n\t\t\t此为本书OpenCV2版的第87个配套示例程序\n");
printf("\n\n\t\t\t 当前使用的OpenCV版本为:" CV_VERSION);
printf("\n\n ----------------------------------------------------------------------------\n");
//输出一些帮助信息
printf("\n\n\n\t欢迎来到【Shi-Tomasi角点检测】示例程序\n");
printf("\n\t请调整滑动条观察图像效果\n\n"); } void main()
{
system("color 2F");
ShowHelpText(); //【1】载入源图像并将其转换为灰度图
g_srcImage = imread("3.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(, ); waitKey();
}

由于VS2015和opencv2有些兼容问题,会出现断言错误(具体原因在上一篇博客有讲),这里就不贴效果图了。

四、亚像素角点检测——cornerSubPix()

opencv学习之路(32)、角点检测

#include "opencv2/opencv.hpp"
#include<iostream>
using namespace std;
using namespace cv; void main()
{
Mat img = imread("E://2.jpg");
imshow("src", img);
Mat result = img.clone();
Mat gray;
cvtColor(img, gray, CV_BGR2GRAY); //Shi-Tomasi角点检测
vector<Point2f> corners;
goodFeaturesToTrack(gray, corners, , 0.01, , Mat(), , false, 0.04);
cout << "角点数量" << corners.size() << endl; for (int i = ; i<corners.size(); i++)
{
cout << "像素坐标:(" << corners[i].x << ", " << corners[i].y << ")" << endl;
circle(result, corners[i], , Scalar(, , ), , );
}
imshow("result", result); Size winSize = Size(, );
Size zeroZone = Size(-, -);
//精度或最大迭代数目,其中任意一个达到 迭代次数40,精度0.001
TermCriteria criteria = TermCriteria(CV_TERMCRIT_EPS + CV_TERMCRIT_ITER, , 0.001);
cornerSubPix(gray, corners, winSize, zeroZone, criteria); for (int j = ; j<corners.size(); j++)
{
cout << "亚像素坐标:(" << corners[j].x << ", " << corners[j].y << ")" << endl;
circle(img, corners[j], , Scalar(, , ), -, );
}
imshow("subPix", img); waitKey();
}

opencv学习之路(32)、角点检测