OPENCV 角点检测

本文深入探讨了多种角点检测算法,包括Shi-Tomasi、Harris-Stephens及自定义角点检测方法。通过OpenCV实现并演示了不同算法在实际图像中的应用效果,对比了各算法的优缺点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.CV_EXPORTS_W 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 );


/**
* @function goodFeaturesToTrack_Demo.cpp
* @brief Demo code for detecting corners using Shi-Tomasi method
* @author OpenCV team
*/

#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/imgproc.hpp"
#include <iostream>

using namespace cv;
using namespace std;

/// Global variables
Mat src, src_gray;

int maxCorners = 23;
int maxTrackbar = 100;

RNG rng(12345);
const char* source_window = "Image";

/// Function header
void goodFeaturesToTrack_Demo(int, void*);

/**
* @function main
*/
int main(int argc, char** argv)
{
	/// Load source image and convert it to gray
	CommandLineParser parser(argc, argv, "{@input | F://opencv//VS_demo//opencvdemo//data//pic3.png | input image}");
	src = imread(parser.get<String>("@input"));
	if (src.empty())
	{
		cout << "Could not open or find the image!\n" << endl;
		cout << "Usage: " << argv[0] << " <Input image>" << endl;
		return -1;
	}
	cvtColor(src, src_gray, COLOR_BGR2GRAY);

	/// Create Window
	namedWindow(source_window);

	/// Create Trackbar to set the number of corners
	createTrackbar("Max corners:", source_window, &maxCorners, maxTrackbar, goodFeaturesToTrack_Demo);

	imshow(source_window, src);

	goodFeaturesToTrack_Demo(0, 0);

	waitKey();
	return 0;
}

/**
* @function goodFeaturesToTrack_Demo.cpp
* @brief Apply Shi-Tomasi corner detector
*/
void goodFeaturesToTrack_Demo(int, void*)
{
	/// Parameters for Shi-Tomasi algorithm
	maxCorners = MAX(maxCorners, 1);
	vector<Point2f> corners;
	double qualityLevel = 0.01;
	double minDistance = 10;
	int blockSize = 3, gradientSize = 3;
	bool useHarrisDetector = false;
	double k = 0.04;

	/// Copy the source image
	Mat copy = src.clone();

	/// Apply corner detection
	goodFeaturesToTrack(src_gray,
		corners,
		maxCorners,
		qualityLevel,
		minDistance,
		Mat(),
		blockSize,
		gradientSize,
		useHarrisDetector,
		k);


	/// Draw corners detected
	cout << "** Number of corners detected: " << corners.size() << endl;
	int radius = 4;
	for (size_t i = 0; i < corners.size(); i++)
	{
		circle(copy, corners[i], radius, Scalar(rng.uniform(0, 255), rng.uniform(0, 256), rng.uniform(0, 256)), FILLED);
	}

	/// Show what you got
	namedWindow(source_window);
	imshow(source_window, copy);
}

CV_EXPORTS_W void cornerHarris( InputArray src, OutputArray dst, int blockSize,
                                int ksize, double k,
                                int borderType = BORDER_DEFAULT );

/**
* @function cornerHarris_Demo.cpp
* @brief Demo code for detecting corners using Harris-Stephens method
* @author OpenCV team
*/

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

using namespace cv;
using namespace std;

/// Global variables
Mat src, src_gray;
int thresh = 200;
int max_thresh = 255;

const char* source_window = "Source image";
const char* corners_window = "Corners detected";

/// Function header
void cornerHarris_demo(int, void*);

/**
* @function main
*/
int main(int argc, char** argv)
{
	/// Load source image and convert it to gray
	CommandLineParser parser(argc, argv, "{@input | F://opencv//VS_demo//opencvdemo//data//building.jpg | input image}");
	src = imread(parser.get<String>("@input"));
	if (src.empty())
	{
		cout << "Could not open or find the image!\n" << endl;
		cout << "Usage: " << argv[0] << " <Input image>" << endl;
		return -1;
	}
	cvtColor(src, src_gray, COLOR_BGR2GRAY);

	/// Create a window and a trackbar
	namedWindow(source_window);
	createTrackbar("Threshold: ", source_window, &thresh, max_thresh, cornerHarris_demo);
	imshow(source_window, src);

	cornerHarris_demo(0, 0);

	waitKey();
	return 0;
}

/**
* @function cornerHarris_demo
* @brief Executes the corner detection and draw a circle around the possible corners
*/
void cornerHarris_demo(int, void*)
{
	/// Detector parameters
	int blockSize = 2;
	int apertureSize = 3;
	double k = 0.04;

	/// Detecting corners
	Mat dst = Mat::zeros(src.size(), CV_32FC1);
	cornerHarris(src_gray, dst, blockSize, apertureSize, k);

	/// Normalizing
	Mat dst_norm, dst_norm_scaled;
	normalize(dst, dst_norm, 0, 255, NORM_MINMAX, CV_32FC1, Mat());
	convertScaleAbs(dst_norm, dst_norm_scaled);

	/// Drawing a circle around corners
	for (int i = 0; i < dst_norm.rows; i++)
	{
		for (int j = 0; j < dst_norm.cols; j++)
		{
			if ((int)dst_norm.at<float>(i, j) > thresh)
			{
				circle(dst_norm_scaled, Point(j, i), 5, Scalar(0), 2, 8, 0);
			}
		}
	}

	/// Showing the result
	namedWindow(corners_window);
	imshow(corners_window, dst_norm_scaled);
}

2.定制化创建角点检测子--cornerEigenValsAndVecs()和cornerMinEigenVal()

/**
* @function cornerDetector_Demo.cpp
* @brief Demo code for detecting corners using OpenCV built-in functions
* @author OpenCV team
*/

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

using namespace cv;
using namespace std;

/// Global variables
Mat src, src_gray;
Mat myHarris_dst, myHarris_copy, Mc;
Mat myShiTomasi_dst, myShiTomasi_copy;

int myShiTomasi_qualityLevel = 50;
int myHarris_qualityLevel = 50;
int max_qualityLevel = 100;

double myHarris_minVal, myHarris_maxVal;
double myShiTomasi_minVal, myShiTomasi_maxVal;

RNG rng(12345);

const char* myHarris_window = "My Harris corner detector";
const char* myShiTomasi_window = "My Shi Tomasi corner detector";

/// Function headers
void myShiTomasi_function(int, void*);
void myHarris_function(int, void*);

/**
* @function main
*/
int main(int argc, char** argv)
{
	/// Load source image and convert it to gray
	CommandLineParser parser(argc, argv, "{@input | F://opencv//VS_demo//opencvdemo//data/building.jpg | input image}");
	src = imread(parser.get<String>("@input"));
	if (src.empty())
	{
		cout << "Could not open or find the image!\n" << endl;
		cout << "Usage: " << argv[0] << " <Input image>" << endl;
		return -1;
	}
	cvtColor(src, src_gray, COLOR_BGR2GRAY);

	/// Set some parameters
	int blockSize = 3, apertureSize = 3;

	/// My Harris matrix -- Using cornerEigenValsAndVecs
	// 计算特征值和特整向量用于触点检测
	/*blockSize:领域尺寸;
		ksize:Sobel()算子的孔径参数;
		borderType:像素外推方式;*/
	cornerEigenValsAndVecs(src_gray, myHarris_dst, blockSize, apertureSize);


	/* calculate Mc */
	Mc = Mat(src_gray.size(), CV_32FC1);
	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.04f*pow((lambda_1 + lambda_2), 2);
		}
	}

	minMaxLoc(Mc, &myHarris_minVal, &myHarris_maxVal);

	/* Create Window and Trackbar */
	namedWindow(myHarris_window);
	createTrackbar("Quality Level:", myHarris_window, &myHarris_qualityLevel, max_qualityLevel, myHarris_function);
	myHarris_function(0, 0);

	/// My Shi-Tomasi -- Using cornerMinEigenVal
	cornerMinEigenVal(src_gray, myShiTomasi_dst, blockSize, apertureSize);

	minMaxLoc(myShiTomasi_dst, &myShiTomasi_minVal, &myShiTomasi_maxVal);

	/* Create Window and Trackbar */
	namedWindow(myShiTomasi_window);
	createTrackbar("Quality Level:", myShiTomasi_window, &myShiTomasi_qualityLevel, max_qualityLevel, myShiTomasi_function);
	myShiTomasi_function(0, 0);

	waitKey();
	return 0;
}

/**
* @function myShiTomasi_function
*/
void myShiTomasi_function(int, void*)
{
	myShiTomasi_copy = src.clone();
	myShiTomasi_qualityLevel = MAX(myShiTomasi_qualityLevel, 1);

	for (int i = 0; i < src_gray.rows; i++)
	{
		for (int j = 0; j < src_gray.cols; j++)
		{
			if (myShiTomasi_dst.at<float>(i, j) > myShiTomasi_minVal + (myShiTomasi_maxVal - myShiTomasi_minVal)*myShiTomasi_qualityLevel / max_qualityLevel)
			{
				circle(myShiTomasi_copy, Point(j, i), 4, Scalar(rng.uniform(0, 256), rng.uniform(0, 256), rng.uniform(0, 256)), FILLED);
			}
		}
	}
	imshow(myShiTomasi_window, myShiTomasi_copy);
}

/**
* @function myHarris_function
*/
void myHarris_function(int, void*)
{
	myHarris_copy = src.clone();
	myHarris_qualityLevel = MAX(myHarris_qualityLevel, 1);

	for (int i = 0; i < src_gray.rows; i++)
	{
		for (int j = 0; j < src_gray.cols; j++)
		{
			if (Mc.at<float>(i, j) > myHarris_minVal + (myHarris_maxVal - myHarris_minVal)*myHarris_qualityLevel / max_qualityLevel)
			{
				circle(myHarris_copy, Point(j, i), 4, Scalar(rng.uniform(0, 256), rng.uniform(0, 256), rng.uniform(0, 256)), FILLED);
			}
		}
	}
	imshow(myHarris_window, myHarris_copy);
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值