OpenCV c++ 角点检测

18 篇文章 9 订阅

1.角点检测

void cornerHarris( InputArray src, OutputArray dst, int blockSize,int ksize,
                    double k, int borderType = BORDER_DEFAULT );
  • src:输入8bit 单通道灰度Mat矩阵
  • dst:用于保存Harris角点检测结果,32位单通道,大小与src相同
  • blockSize:滑块窗口的尺寸
  • ksize:Sobel边缘检测滤波器大小
  • k:Harries中间参数,经验值0.04~0.06
  • borderType=BORDER_DEFAULT:插值类型

1.1.(cv :: cornerHarris)Harris 角点检测

Harris角点检测是一种直接基于灰度图的角点提取算法,稳定性高,尤其对L型角点(也就是直角)检测精度高。缺点也是明显的,就是运算速度慢。

#include <opencv2/opencv.hpp>  
#include "opencv2/highgui/highgui.hpp"  
#include "opencv2/imgproc/imgproc.hpp"  


using namespace cv;
using namespace std;


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)
{
	g_srcImage = imread("./image/test15.jpg", 1);
	if (!g_srcImage.data)
	{
		printf("读取图片错误! \n");
		return -1;
	}
	imshow("原始图", g_srcImage);
	g_srcImage1 = g_srcImage.clone();
	//存留一张灰度图  
	cvtColor(g_srcImage1, g_grayImage, COLOR_BGR2GRAY);
	//创建窗口和滚动条  
	namedWindow("角点检测", WINDOW_AUTOSIZE);
	createTrackbar("阈值: ", "角点检测", &thresh, max_thresh, on_CornerHarris);
	//调用一次回调函数,进行初始化  
	on_CornerHarris(0, 0);
	waitKey(0);
	return(0);
}


void on_CornerHarris(int, void*)
{
	Mat dstImage;//目标图  
	Mat normImage;//归一化后的图  
	Mat scaledImage;//线性变换后的八位无符号整型的图  


	//置零当前需要显示的两幅图,即清除上一次调用此函数时他们的值  
	dstImage = Mat::zeros(g_srcImage.size(), CV_32FC1);
	g_srcImage1 = g_srcImage.clone();
	//进行角点检测  
	//第三个参数表示邻域大小,第四个参数表示Sobel算子孔径大小,第五个参数表示Harris参数
	cornerHarris(g_grayImage, dstImage, 2, 3, 0.04, BORDER_DEFAULT);
	// 归一化与转换  
	normalize(dstImage, normImage, 0, 255, NORM_MINMAX, CV_32FC1, Mat());
	convertScaleAbs(normImage, scaledImage);//将归一化后的图线性变换成8位无符号整型   
	// 将检测到的,且符合阈值条件的角点绘制出来  
	for (int j = 0; j < normImage.rows; j++)
	{
		for (int i = 0; i < normImage.cols; i++)
		{
			//Mat::at<float>(j,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);
			}
		}
	}
	imshow("角点检测", g_srcImage1);
	imshow("角点检测2", scaledImage);
}

执行结果:
在这里插入图片描述

1.2.Shi-Tomasi角点检测

除了上述的Harris角点检测方法,我们还可以采用Shi-Tomasi方法进行角点检测。Shi-Tomsi算法是Harris算法的加强版,性能当然也有相应的提高。

#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
#include <stdio.h>
#include <stdlib.h>


using namespace cv;
using namespace std;
Mat src, src_gray;
int maxCorners = 23;
int maxTrackbar = 100;
RNG rng(12345);  //RNG:random number generator,随机数产生器
const char* source_window = "Image";
void goodFeaturesToTrack_Demo(int, void*);
int main()
{
	//转化为灰度图
	src = imread("./image/test15.jpg", 1);
	cvtColor(src, src_gray, COLOR_BGR2GRAY);
	namedWindow(source_window, WINDOW_AUTOSIZE);
	//创建trackbar
	createTrackbar("MaxCorners:", source_window, &maxCorners, maxTrackbar, goodFeaturesToTrack_Demo);
	imshow(source_window, src);
	goodFeaturesToTrack_Demo(0, 0);
	waitKey(0);
	return(0);
}


void goodFeaturesToTrack_Demo(int, void*)
{
	if (maxCorners < 1) { maxCorners = 1; }
	//初始化 Shi-Tomasi algorithm的一些参数
	vector<Point2f> corners;
	double qualityLevel = 0.01;
	double minDistance = 10;
	int blockSize = 3;
	bool useHarrisDetector = false;
	double k = 0.04;
	//给原图做一次备份
	Mat copy;
	copy = src.clone();
	// 角点检测
	goodFeaturesToTrack(src_gray, corners, maxCorners, qualityLevel, minDistance, Mat(), blockSize, useHarrisDetector, k);
	//画出检测到的角点
	cout << "** Number of corners detected: " << corners.size() << endl;
	int r = 4;
	for (int i = 0; i < corners.size(); i++)
	{
		circle(copy, corners[i], r, Scalar(rng.uniform(0, 255), rng.uniform(0, 255),
			rng.uniform(0, 255)), -1, 8, 0);
	}
	namedWindow(source_window, WINDOW_AUTOSIZE);
	imshow(source_window, copy);
}

执行结果:
在这里插入图片描述

2.(cv :: setMouseCallback)人机交互

Void setMouseCallback(conststring& winname, MouseCallback onMouse, void* userdata = 0)
  • winname:窗口的名字;
  • onMouse:回调函数,这个函数原型的一般形式是void Foo(int event, int x, int y, int flags,
    void* param) (其中event代表的是发生的鼠标事件)(param是用户定义的传递到Setmousecallback函数调用的参数)
  • userdata:用户定义的传递到回调函数的参数,默认值为0
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
using namespace cv;
using namespace std;
//函数声明
void on_mouse(int event, int x, int y, int type, void* param);
void draw_rectangle(cv::Mat& img, cv::Rect box);
//变量声明
Mat image;
Rect rect;
bool drawimage = false;
int main()
{
	image = imread("./image/test3.jpg");
	Mat tempimage;	
	namedWindow("人机交互窗口");
	setMouseCallback("人机交互窗口", on_mouse, (void*)&image);
	while (1)
	{
		image.copyTo(tempimage);
		if (drawimage)
			draw_rectangle(tempimage, rect);
			imshow("人机交互窗口", tempimage);
		if (waitKey(10) == 27)
			break;
	}
	return 1;
}


void on_mouse(int event, int x, int y, int type, void* param)
{
	Mat& img = *(Mat*)param;
	switch (event)
	{
		case(EVENT_LBUTTONDOWN):
		{
			drawimage = true;
			rect = Rect(x, y, 0, 0);
		}
		break;
		case(EVENT_MOUSEMOVE):
		{
			if (drawimage)
			{
				rect.width = x - rect.x;
				rect.height = y - rect.y;
			}
		}
		break;
		case(EVENT_LBUTTONUP):
		{
			drawimage = false;
			draw_rectangle(img, rect);
		}
		break;
	}
}


void draw_rectangle(cv::Mat& img, cv::Rect box)
{
	rectangle(img, box.tl(), box.br(), Scalar(rand() & 255, rand() & 255, rand() & 255));
}
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

~晓广~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值