opencv图像角点提取

opencv图像角点提取opencv角点检测(二)改进的Harris角点检测算法harris角点检测算法的结果一定程度上取决于系数k,有人对Harris的角点检测算法进行了改进,直接利用像素点协方差矩阵的特征值提取角点。而且不在进行非极大值抑制,而是采用一种容忍距离的形式,在角点的一定范围内只有一个角点。具体原理:首先计算图像每个像素点的协方差矩阵,并求取对应的特征值,将最小的特征值最大的那个像素点作为第

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺

opencv角点检测(二)


改进的Harris角点检测算法

<span style="font-size:18px;">harris角点检测算法的结果一定程度上取决于系数k,有人对Harris的角点检测算法进行了改进,直接利用像素点协方差矩阵的特征值提取角点。而且不在进行非极大值抑制,而是采用一种容忍距离的形式,在角点的一定范围内只有一个角点。</span>
<span style="font-size:18px;">具体原理:首先计算图像每个像素点的协方差矩阵,并求取对应的特征值,将最小的特征值最大的那个像素点作为第一个角点(具体来说,就是求出每个像素点的协方差矩阵对应的特征值,找出最小的那个,所有最小的特征值中哪个最大,就将哪个所对应的像素点作为角点max(min(e1,e2)),e1、e2为像素协方差矩阵的特征值)。然后依次按照最大最小特征值的顺序寻找角点,并保证在容忍距离内只有一个角点。</span>
<span style="font-size:18px;">opencv测试代码:</span>
<span style="font-size:18px;"></span><pre name="code" class="cpp">#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp><img src="https://img-blog.csdn.net/20150322224206153?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxNDI2MDg5Mg==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" /><img src="https://img-blog.csdn.net/20150322224206153?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxNDI2MDg5Mg==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" />
#include <opencv2/imgproc/imgproc.hpp>

#include <iostream>
using namespace std;
using namespace cv;

Mat src,src_gray;
int cornernum = 20;
int maxnum = 200;
char* windowname = "Imagecorners";

void goodFeaturesdemo(int,void*);
int main(int argc,char* argv[])
{
	src = imread("road.jpg");
	cvtColor(src,src_gray,CV_BGR2GRAY);//将图像转化为灰度图;

	namedWindow(windowname,CV_WINDOW_AUTOSIZE);
	createTrackbar("CornersNum:",windowname,&cornernum,maxnum,goodFeaturesdemo);//创建控制条,与cornernum变量相        //关联

	imshow(windowname,src);
	goodFeaturesdemo(0,0);

	waitKey(0);
	return 0;
}

void goodFeaturesdemo(int,void*)
{
	if(cornernum < 1){ cornernum = 1;}

	vector<Point2f> points;
	double qualityLevel = 0.02;
	double minDistance = 10;
	int blockSize = 3;
	bool useHarrisDetector = false;
	double k = 0.04;

	Mat copy;
	copy = src.clone();
        //进行角点检测
	goodFeaturesToTrack(src_gray,              //要进行检测的图像
		                points,            //存储检测到的角点坐标,Point2f类型
		                cornernum,         //检测到的角点的最大数目
				qualityLevel,      //角点的阈值条件,即角点的质量等级:qualityLevel*max(min(e1,e2))
				minDistance,       //容忍距离,单位像素
				Mat(),
				blockSize,
				useHarrisDetector,
				k);
	cout<<"Number of corners detected: "<<points.size()<<endl;
	int r = 4;
	for(int i = 0; i < points.size(); i++)
	{
		circle(copy,points[i],r,Scalar(0,0,255),1,8);
	}

	//namedWindow(windowname,CV_WINDOW_AUTOSIZE);
	imshow(windowname,copy);
}

检测结果如下:


<img src="https://img-blog.csdn.net/20150322224206153?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxNDI2MDg5Mg==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" />
<span style="font-size:18px;">可以看出检测到的角点比较均匀,不会在一个小区域产生角点聚集的情况。</span>
<span style="font-size:18px;">
</span>
<span style="font-size:18px;"></span><pre name="code" class="cpp">定制自己的角点检测算法:
opencv提供了求取特征值和特征向量的函数,可以实现自己设计的角点提取算法,主要包括下面两个函数:
cornerEigenCalsAndVecs:计算像素对应的特征值和特征向量;
cornerMinEigenVal:求取像素点最小的特征值;
下面程序实现了一个定制化的Harris角点检测算法,和类似的Shi-Tomsi算法:
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>

#include <iostream>
using namespace std;
using namespace cv;

Mat src,src_gray;
Mat myHarris_dst,myHarris_copy,Mc;
Mat myShiTomsi_dst,myShiTomsi_copy;

int myST_qualityLevel = 50;
int myH_qualityLevel = 50;
int max_qualityLevel =100;

double myHarris_minVal,myHarris_maxVal;
double myST_minVal,myST_maxVal;

RNG rng(2444);

char* myHarris = "myHarris Corner:";
char* myST = "myST Corner:";

void myHarris_function(int,void*);
void myST_function(int,void*);

int main(int argc,char* argv[])
{
	src = imread("road.jpg");

	cvtColor(src,src_gray,CV_BGR2GRAY);

	int blocksize = 3;
	int aperture = 3;
	myHarris_dst = Mat::zeros(src_gray.size(),CV_32FC(6));
	Mc =  Mat::zeros(src_gray.size(),CV_32FC1);

	cornerEigenValsAndVecs(src_gray,myHarris_dst,blocksize,aperture,BORDER_DEFAULT);//求取像素点特征值和特征向         
        //量,具体参数意义见用户手册;论坛上应该有。
	for( int i = 0; i < src_gray.rows; i++)
	{
		for(int j = 0; j < src_gray.cols; j++)
		{
			float lambda_1 = myHarris_dst.at<Vec6f>(i,j)[0];//取出两个特征值,后几位是特征向量;
			float lambda_2 = myHarris_dst.at<Vec6f>(i,j)[1];
			Mc.at<float>(i,j) = lambda_1*lambda_2 - 0.04*pow((lambda_1+lambda_2),2);//harris角点检测法
		}
	}

	minMaxLoc(Mc,&myHarris_minVal,&myHarris_maxVal);//求出最大值和最小值,用来筛选角点;

	namedWindow(myHarris,CV_WINDOW_AUTOSIZE);
	createTrackbar("Quality Level",myHarris,&myH_qualityLevel,max_qualityLevel,myHarris_function);
	myHarris_function(0,0);

	myShiTomsi_dst = Mat::zeros(src_gray.size(),CV_32FC1);
	cornerMinEigenVal(src_gray,myShiTomsi_dst,blocksize,aperture,4);

	minMaxLoc(myShiTomsi_dst,&myST_minVal,&myST_maxVal);
	namedWindow(myST,CV_WINDOW_AUTOSIZE);
	createTrackbar("Quality Level",myST,&myST_qualityLevel,max_qualityLevel,myST_function);
	myST_function(0,0);

	waitKey();
	return 0;
}

void myHarris_function(int,void*)
{
	myHarris_copy = src.clone();

	if(myST_qualityLevel < 1)
	{ myST_qualityLevel = 1;}

	for(int j = 0; j < src_gray.rows ; j++)
	{
		for(int i = 0; i < src_gray.cols ; i++)
		{
		    if( Mc.at<float>(j,i) > myHarris_minVal + (float)(myHarris_maxVal - myHarris_minVal)*
			myH_qualityLevel/max_qualityLevel)
			     circle(myHarris_copy,Point(i,j),3,Scalar(rng.uniform(0,255),rng.uniform(0,255),rng.uniform(0,255)),-1,8,0);//在检测到的焦点位                             //置画圆
		}
	}
	imshow(myHarris,myHarris_copy);
}

void myST_function(int,void*)
{
	myShiTomsi_copy = src.clone();

	for(int i = 0; i < src.rows; i++)
	{
		for(int j = 0; j < src.cols ; j++)
		{
			if(myShiTomsi_dst.at<float>(i,j) > myST_minVal + (myST_maxVal - myST_minVal)*
				myH_qualityLevel/max_qualityLevel)
				circle(myShiTomsi_copy,Point(j,i),3,Scalar(rng.uniform(0,255),rng.uniform(0,255),rng.uniform(0,255)),-1,8,0);
		}
	}
	imshow(myST,myShiTomsi_copy);
}

定制化的Harris焦点检测结果:


<span style="font-size:18px;"><img src="https://img-blog.csdn.net/20150322224743120?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxNDI2MDg5Mg==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" />
</span>
<span style="font-size:18px;">定制化的Shi-Tomsi算法检测结果:</span>
<span style="font-size:18px;"><img src="https://img-blog.csdn.net/20150322224845286?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxNDI2MDg5Mg==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" />
</span>
<span style="font-size:18px;">
</span>
<span style="font-size:18px;">亚像素角点检测:</span>
<span style="font-size:18px;"></span><pre name="code" class="cpp">opencv提供函数cornerSubPixel函数进行亚像素精度的角点检测。具体代码如下:
<pre name="code" class="cpp">#include <iostream>
using namespace std;
using namespace cv;

Mat src,src_gray;
int cornersnum = 20;
int maxnum = 50;
RNG rng(342);

char* imgwindow = "Image";

void subPixelCorner(int,void*);
int main(int argc,char* argv[])
{
	src = imread("cat.jpg");

	cvtColor(src,src_gray,CV_BGR2GRAY);
	namedWindow(imgwindow,CV_WINDOW_AUTOSIZE);
	createTrackbar("Corners NUM:",imgwindow,&cornersnum,maxnum,subPixelCorner);
	subPixelCorner(0,0);

	//imshow(imgwindow,src);

	waitKey(0);
	return 0;
}

void subPixelCorner(int,void*)
{
	if(cornersnum < 1) { cornersnum = 1;}

	Mat copy = src.clone();

	vector<Point2f> points;
	double qualityLevel = 0.03;
	double minDistance = 10;
	int blocksize = 3;
	bool useHarrisDetector = false;
	double k = 0.045;

	goodFeaturesToTrack(src_gray,
		            points,
		            cornersnum,
			    qualityLevel,
			    minDistance,
			    Mat(),
			    blocksize,
			    useHarrisDetector,
			    k);

	cout<<"Number of detected corners:"<<points.size()<<endl;
	int r = 4;
	for( int i = 0; i < points.size(); i++)
	{
		circle(copy,points[i],r,Scalar(rng.uniform(0,255),rng.uniform(0,255),rng.uniform(0,255)),-1,8,0);
	}

	imshow(imgwindow,copy);

	Size size = Size(5,5);
	Size zerosize = Size(-1,-1);

	TermCriteria criteria = TermCriteria(CV_TERMCRIT_EPS + CV_TERMCRIT_ITER,30,0.01);//设置迭代结束的条件
	cornerSubPix(src_gray,points,size,zerosize,criteria);//亚像素精度角点检测

	for(int j = 0; j < points.size(); j++)
	{ cout<<"Refined Corner ["<<j<<"] : ("<<points[j].x<<","<<points[j].y<<")"<<endl;}
}

cornernum阈值为36时的运行结果:

opencv图像角点提取


重新定位的亚像素精度的角点:
<img src="https://img-blog.csdn.net/20150322225130178?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxNDI2MDg5Mg==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" />

至此,利用opencv检测角点的算法总结完毕,本文的程序是在VC2010+opencv2.4.9+win7下可直接运行;下篇总结不同的特征检测算子。敬请期待!


<span style="font-size:18px;">
</span>

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/179735.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

  • pycharm添加conda虚拟环境[通俗易懂]

    pycharm添加conda虚拟环境[通俗易懂]

  • 一周信创舆情观察(12.7~12.13)

    一周信创舆情观察(12.7~12.13)一、一周舆情要点行业方面,2020年集成电路设计行业销售额预计为3819.4亿元,比2019年的3084.9亿元增长23.8%。日前,我国自主研发的一项物联网安全测试技术(TRAIS-PTEST)由国际标准化组织/国际电工委员会(ISO/IEC)发布成为国际标准。拉勾近日发布人才白皮书,至2020年底我国新基建相关核心技术人才缺口已达426万。国际方面,微软为ARM版本Win10推出64位模拟器。欧盟新法规定,超大型科技公司需监督互联网,否则罚款年营业额6%。近日,思科和英国云通信软件公司IMImo

  • origin画图数据_origin多元线性回归拟合

    origin画图数据_origin多元线性回归拟合制图完成效果图如下。1.原始数据为真实值与预测值。2.另外两列是制作中间的标准线。优化直线。3.4.对预测值与真实值的图进行优化。5.将标准线图层复制到当前页面,ctrl+C,V就行了。将标准线的网格删除。将线移动到该有的位置即可。对周围的字体大小等修正后即可。…

  • 【转载】TCP和TCP/IP的区别

    【转载】TCP和TCP/IP的区别

    2021年11月18日
  • 作为Java开发,你一定要了解面向对象编程中为什么要使用get和set方法

    一、由一个问题开始在进行面向对象开发中,在编写一个Class的时候,会定义这个Class的属性(字段)为Private,然后去生成对应的get和set方法,通过这样的方式去对属性进行操作,那你有没有思考过为什么要这样做呢?这样做有哪些好处呢?请先自行思考30秒,在看下面的内容。二、回顾相关知识回答这个问题之前,让我们先回顾一些的基础知识:1、访问修饰符,从访问的范围由小及大依次是:pri…

  • 100行Html5+CSS3+JS代码实现元旦倒计时界面

    一、前言二、圣诞树效果展示:三、步骤如果之前看过我这篇文章的1.下载VSCode下载链接:VSCode在Hbuilder、idea运行也是可以的,这里推荐使用VSCode2.配置插件三个插件对应的功能:改写标签后自动完善 切换成中文页面 让代码在网页中打开,默认键Alt+B3.构建三个文件在桌面新建一个空的文件夹,用VSCode打开 在VSCode新建三个文件index.htmldomtree….

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号