2022-6-12:OpenCV入门(十一)feature2d组件——角点检测

Harris角点检测

如果某一点在任意方向的一个微小变动都会引起灰度很大的变化,那么我们就把它称之为角点。
角点作为图像上的特征点,包含有重要的信息,在图像融合和目标跟踪及三维重建中有重要的应用价值。它们在图像中可以轻易地定位,同时,在人造物体场景,比如门、窗、桌等处也随处可见。因为角点位于两条边缘的交点处,代表了两个边缘变化的方向上的点,所以它们是可以精确定位的二维特征,甚至可以达到亚像素的精度。又由于其图像梯度有很高的变化,这种变化是可以用来帮助检测角点的。需要注意的是,角点与位于相同强度区域上的点不同,与物体轮廓上的点也不同,因为轮廓点难以在相同的其他物体上精确定位。

harris角点检测是一种直接基于灰度图像的角点提取算法,稳定性高,尤其对L型角点检测精度高。但由于采用了高斯滤波,运算速度相对较慢,角点信息有丢失和位置偏移的现象,而且角点提取有聚簇现象。

void cornerHarris(InputArray src,outputArray dst, int blockSize,int ksize,double k, intborderType=BORDER_DEFAULT )
//第一个参数:输入图像,即源图像且须为单通道8位或者浮点型图像;第二个参数:用于存放 Harris角点检测的输出结果,和源图片有一样的尺寸和类型;第三个参数:表示邻域的大小;第四个参数:表示Sobel()算子的孔径大小;第五个参数:Harris参数;第六个参数:图像像素的边界模式。
#include <opencv2/opencv.hpp>
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
using namespace cv;
using namespace std;

#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(int argc, char** argv)
{
	//【1】载入原始图并进行克隆保存
	g_srcImage = imread("1.jpg", 1);
	if (!g_srcImage.data) { printf("读取图片错误,请确定目录下是否有imread函数指定的图片存在~! \n"); return false; }
	imshow("原始图", g_srcImage);
	g_srcImage1 = g_srcImage.clone();

	//【2】存留一张灰度图
	cvtColor(g_srcImage1, g_grayImage, COLOR_BGR2GRAY);

	//【3】创建窗口和滚动条
	namedWindow(WINDOW_NAME1, WINDOW_AUTOSIZE);
	createTrackbar("阈值: ", WINDOW_NAME1, &thresh, max_thresh, on_CornerHarris);

	//【4】调用一次回调函数,进行初始化
	on_CornerHarris(0, 0);

	waitKey(0);
	return(0);
}

//-----------------------------------【on_HoughLines( )函数】--------------------------------
//		描述:回调函数
//----------------------------------------------------------------------------------------------
void on_CornerHarris(int, void*)
{
	//---------------------------【1】定义一些局部变量-----------------------------
	Mat dstImage;//目标图
	Mat normImage;//归一化后的图
	Mat scaledImage;//线性变换后的八位无符号整型的图

	//---------------------------【2】初始化---------------------------------------
	//置零当前需要显示的两幅图,即清除上一次调用此函数时他们的值
	dstImage = Mat::zeros(g_srcImage.size(), CV_32FC1);
	g_srcImage1 = g_srcImage.clone();

	//---------------------------【3】正式检测-------------------------------------
	//进行角点检测
	cornerHarris(g_grayImage, dstImage, 2, 3, 0.04, BORDER_DEFAULT);

	// 归一化与转换
	normalize(dstImage, normImage, 0, 255, NORM_MINMAX, CV_32FC1, Mat());
	convertScaleAbs(normImage, scaledImage);//将归一化后的图线性变换成8位无符号整型 

	//---------------------------【4】进行绘制-------------------------------------
	// 将检测到的,且符合阈值条件的角点绘制出来
	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, 8, 0);
				circle(scaledImage, Point(i, j), 5, Scalar(0, 10, 255), 2, 8, 0);
			}
		}
	}
	//---------------------------【4】显示最终效果---------------------------------
	imshow(WINDOW_NAME1, g_srcImage1);
	imshow(WINDOW_NAME2, scaledImage);

}

在这里插入图片描述

Shi-Tomasi角点检测

void goodFeaturesToTrack (InputArray image,outputArray corners,int maxCorners,double qualityLevel,double minDistance,InputArray mask=noArray () ,int blockSize=3,bool useHarrisDetector=false,double k=0.04 )
//第一个参数:输入图像,须为8位或浮点型 32位单通道图像;第二个参数:检测到的角点的输出向量;第三个参数:角点的最大数量;第四个参数:角点检测可接受的最小特征值;其实实际用于过滤角点的最小特征值是qualityLevel 与图像中最大特征值的乘积。所以 qualityLevel通常不会超过1(常用的值为0.10或者0.01)。而检测完所有的角点后,还要进一步剔除掉一些距离较近的角点;第五个参数:double类型的minDistance,角点之间的最小距离,此参数用于保证返回的角点之间的距离不小于minDistance个像素。
//第六个参数:InputArray类型的mask,可选参数,表示感兴趣区域,有默认值 noArray();第七个参数:int类型的 blockSize,有默认值3,是计算导数自相关矩阵时指定的邻域范围;第八个参数:bool类型的useHarrisDetector,默认值 false,指示是否使用Harris角点检测;第九个参数:double类型的k,有默认值0.04,为用于设置Hessian自相关矩阵行列式的相对权重的权重系数。
#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);//初始化随机数生成器

//-----------------------------【on_GoodFeaturesToTrack( )函数】----------------------------
//          描述:响应滑动条移动消息的回调函数
//----------------------------------------------------------------------------------------------
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);
}

int main()
{
	//【1】载入源图像并将其转换为灰度图
	g_srcImage = imread("1.jpg", 1);
	cvtColor(g_srcImage, g_grayImage, COLOR_BGR2GRAY);

	//【2】创建窗口和滑动条,并进行显示和回调函数初始化
	namedWindow(WINDOW_NAME, 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 cornerSubPix(InputArray image,InputoutputArray corners,size winsize,size zerozone,TermCriteria criteria)
//第一个参数:输入图像;第二个参数:提供输入角点的初始坐标和精确的输出坐标;第三个参数:搜索窗口的一半尺寸;第四个参数:表示死区的一半尺寸,而死区为不对搜索区的中央位置做求和运算的区域,用来避免自相关矩阵出现的某些可能的奇异性,值为(-1,-1)表示没有死区;
//第五个参数:求角点的迭代过程的终止条件;即角点位置的确定,要么迭代数大于某个设定值,或者是精确懂达到某个设定值,criteria可以是最大迭代数目,或者是设定的精确度,也可以是它们的组合。
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
using namespace cv;
using namespace std;

#define WINDOW_NAME "【亚像素级角点检测】"        //为窗口标题定义的宏 

Mat g_srcImage, g_grayImage;
int g_maxCornerNumber = 33;
int g_maxTrackbarNumber = 500;
RNG g_rng(12345);//初始化随机数生成器

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 << "\n\t>-------------此次检测到的角点数量为:" << corners.size() << endl;

	//【5】绘制检测到的角点
	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, 8, 0);
	}

	//【6】显示(更新)窗口
	imshow(WINDOW_NAME, copy);

	//【7】亚像素角点检测的参数设置
	Size winSize = Size(5, 5);
	Size zeroZone = Size(-1, -1);
	TermCriteria criteria = TermCriteria(TermCriteria::EPS + TermCriteria::MAX_ITER, 40, 0.001);

	//【8】计算出亚像素角点位置
	cornerSubPix(g_grayImage, corners, winSize, zeroZone, criteria);

	//【9】输出角点信息
	for (int i = 0; i < corners.size(); i++)
	{
		cout << " \t>>精确角点坐标[" << i << "]  (" << corners[i].x << "," << corners[i].y << ")" << endl;
	}


}

int main()
{
	//【1】载入源图像并将其转换为灰度图
	g_srcImage = imread("1.jpg", 1);
	cvtColor(g_srcImage, g_grayImage, COLOR_BGR2GRAY);

	//【2】创建窗口和滑动条,并进行显示和回调函数初始化
	namedWindow(WINDOW_NAME, WINDOW_AUTOSIZE);
	createTrackbar("最大角点数", WINDOW_NAME, &g_maxCornerNumber, g_maxTrackbarNumber, on_GoodFeaturesToTrack);
	imshow(WINDOW_NAME, g_srcImage);
	on_GoodFeaturesToTrack(0, 0);

	waitKey(0);
	return(0);
}

在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值