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

2023-05-16

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);
}

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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

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

  • Matlab 中 interp2 的类似 OpenCV Api

    有没有类似的功能 其工作原理与 interp2 x y frame z xd yd linear 0 在 OpenCV 中 功能cv remap 几乎可以满足您的要求 请参阅文档here http docs opencv org modul
  • 使用 cmake 和 opencv 对符号“gzclose”的未定义引用[关闭]

    Closed 这个问题是无法重现或由拼写错误引起 help closed questions 目前不接受答案 我尝试构建该项目 doppia https bitbucket org rodrigob doppia 但发生链接错误 我想这是一
  • cv2.imread:检查图像是否正在被读取

    我正在用 python 编写一个 OpenCV 程序 在某些时候我有类似的东西 import cv2 import numpy as np img cv2 imread myImage jpg do stuff with image her
  • 在opencv中保存帧而不压缩

    我正在尝试使用写 OpenCV 函数 我想保存帧 TIFF扩大 我遇到的问题是保存的图像被压缩 所以我无法使用它们 知道如何摆脱这种压缩吗 提前致谢 不要介意西奇说的话 TIFF 标志通过 LZW 压缩硬编码在 opencv 二进制文件中
  • cv2.cv.BoxPoints(rect) 返回什么?

    rect cv2 minAreaRect largest contour rect rect 0 0 self scale down rect 0 1 self scale down rect 1 0 self scale down rec
  • 如何提取图像中的表格

    我想从图像中提取表格 这个 python 模块https pypi org project ExtractTable https pypi org project ExtractTable 与他们的网站https www extractta
  • 屏幕截图中低分辨率文本的 OCR

    我正在编写一个 OCR 应用程序来从屏幕截图图像中读取字符 目前 我只关注数字 我的方法部分基于这篇博文 http blog damiles com 2008 11 basic ocr in opencv http blog damiles
  • opencv如何使用compareHist函数

    img cv2 imread mandrill png histg cv2 calcHist img 0 None 256 0 256 if len sys argv lt 2 print gt gt sys stderr Usage sy
  • 如何使用requirements.txt 在 Heroku python Web 应用程序中安装 Dlib?

    我构建了一个涉及机器学习的 Python Flask Web API 但在 Heroku 上部署它时遇到了很多挫折 问题是 我的应用程序依赖于 Dlib 一个库 我似乎找不到在我的 Heroku 服务器中安装的方法 我正在试图解决这个问题
  • opencv 视频上的颜色阈值

    I am thresholding for a color range in an opencv video The goal is to seperate the B mode black and white information on
  • 使用相位相关和对数极坐标变换获得旋转位移

    我一直在编写一个脚本 它使用 cv2 计算两个图像之间的旋转位移phaseCorrelate method 我有两张图像 第二张是第一张图像的 90 度旋转版本 加载图像后 我将它们转换为对数极坐标 然后将它们传递到phaseCorrela
  • 在 Python 3.5 64 位上通过 pip 安装 OpenCV

    我尝试安装 OpenCV 但找不到任何合适的 pip 软件包 我决定上网查找有关如何安装它的官方文档 并发现this https opencv python tutroals readthedocs io en latest py tuto
  • opencv中矩阵的超快中值(与matlab一样快)

    我正在 openCV 中编写一些代码 想要找到一个非常大的矩阵数组 单通道灰度 浮点数 的中值 我尝试了几种方法 例如对数组进行排序 使用 std sort 和选择中间条目 但与 matlab 中的中值函数相比 它非常慢 准确地说 在 ma
  • 相机标定(OpenCV 2.3)-如何使用畸变参数?

    我有一组带有一些附加标记的刚体图像 我在这些标记之一中定义了一个原点坐标系 我想获得该坐标系与在相机原点定义的坐标系之间的旋转和平移 我尝试了一段时间 POSIT 以下this http goo gl cUYYt 但从未获得可接受的结果 直
  • Opencv matchTemplate 和 np.where():仅保留唯一值

    继带有马里奥硬币的 opencv 教程 https opencv python tutroals readthedocs io en latest py tutorials py imgproc py template matching p
  • 使用 opencv warpPerspective() 生成道路的自上而下视图

    我正在尝试实施逆透视映射计算与道路上另一辆车的距离 我知道在应用该函数之前我需要生成一个包含源点和目标点的变换矩阵warpPerspective 但我不知道如何计算目的地点 我在这个论坛和其他网站中搜索 但无法将第一张图片转换为第二张图片
  • 提高 pytesseract 从图像中正确识别文本的能力

    我正在尝试使用读取验证码pytesseract模块 大多数时候它都能提供准确的文本 但并非总是如此 这是读取图像 操作图像以及从图像中提取文本的代码 import cv2 import numpy as np import pytesser
  • 来自连接到远程机器的相机的 Opencv 流

    我正在用 python 开发一个 wx 应用程序 用于流式传输和显示来自两个不同网络摄像头的视频 这工作正常 但现在我需要在不同的场景中执行此操作 其中两个摄像头连接在通过网络连接的 Windows 上运行的单独计算机中 我的应用程序将在机
  • 如何使用 python、openCV 计算图像中的行数

    我想数纸张 所以我正在考虑使用线条检测 我尝试过一些方法 例如Canny HoughLines and FLD 但我只得到处理过的照片 我不知道如何计算 有一些小线段就是我们想要的线 我用过len lines or len contours
  • OpenCV 2.4.3 中的阴影去除

    我正在使用 OpenCV 2 4 3 最新版本 使用内置的视频流检测前景GMG http docs opencv org modules gpu doc video html highlight gmg gpu 3a 3aGMG GPU算法

随机推荐