shi-Tomas角点检测实现

本文介绍了一种基于Shi-tomasi算法的角点检测方法,并提供了详细的Python实现过程。该方法通过计算图像梯度并利用非极大值抑制来定位角点。

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

参考:Shi-tomasi角点检测python实现及基于opencv实现 (角点检测、非极大值抑制

/**
 * @description:		Shi-tomasi角点检测
 * @param src			输入图像
 * @param dst			输出图像
 * @param maxCorners	最大的角点数
 * @param qualityLevel	图像角点的最小可接受参数
 * @param minDistance	角点之间的最小欧式距离
 */
void shi_tomas(cv::Mat& src, cv::Mat& dst, int maxCorners, float qualityLevel, int minDistance)
{
	int block_size = 3;
	int ksize = 3; 
	float k = 0.04;

	dst = src.clone();
	src.convertTo(src, CV_32F);

	double scale = 1.0 / ((ksize - 1) * 2 * block_size * 255);

	cv::Mat img_x, img_y;
	cv::Sobel(src, img_x, -1, 1, 0, ksize, scale);
	cv::Sobel(src, img_y, -1, 0, 1, ksize, scale);

	cv::Mat img_xx, img_yy, img_xy;
	cv::boxFilter(img_x.mul(img_x), img_xx, -1, cv::Size(block_size, block_size));
	cv::boxFilter(img_y.mul(img_y), img_yy, -1, cv::Size(block_size, block_size));
	cv::boxFilter(img_x.mul(img_y), img_xy, -1, cv::Size(block_size, block_size));

	int radius = int((block_size - 1) / 2);
	int N_pre = radius;
	int N_post = block_size - radius - 1;
	int row_s = N_pre;
	int col_s = N_pre;
	int row_e = src.rows - N_post;
	int col_e = src.cols - N_post;

	cv::Mat cim = cv::Mat::zeros(src.rows, src.cols, CV_32F);
	for (int i = row_s; i < row_e; ++i)
	{
		for (int j = col_s; j < col_e; ++j)
		{
			float sum_xx = img_xx.at<float>(i, j);
			float sum_yy = img_yy.at<float>(i, j);
			float sum_xy = img_xy.at<float>(i, j);
			cim.at<float>(i, j) = 0.5 * (sum_xx + sum_yy) - 0.5 * sqrt(pow(sum_xx - sum_yy, 2) + 4 * pow(sum_xy, 2));
		}
	}

	double minv, maxv;
	cv::Point pt_min, pt_max;
	cv::minMaxLoc(cim, &minv, &maxv, &pt_min, &pt_max);
 
	for (int i = 0; i < cim.rows; ++i)
	{
		for (int j = 0; j < cim.cols; ++j)
		{
			if (cim.at<float>(i, j) < maxv * qualityLevel)
			{
				cim.at<float>(i, j) = 0;
			}
		}
	}

	cv::Mat element = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(3, 3)), dilated;
	cv::dilate(cim, dilated, element);

	for (int i = 0; i < cim.rows; ++i)
	{
		for (int j = 0; j < cim.cols; ++j)
		{
			if (cim.at<float>(i, j) != dilated.at<float>(i, j))
			{
				cim.at<float>(i, j) = 0;
			}
		}
	}

	int num = 0;
	cv::cvtColor(dst, dst, cv::COLOR_GRAY2BGR);
	while (num < maxCorners)
	{
		cv::minMaxLoc(cim, &minv, &maxv, &pt_min, &pt_max);
		if (maxv == 0)
			break;

		dst.at<cv::Vec3b>(pt_max.y, pt_max.x) = cv::Vec3b(0, 0, 255);
		num++;

		for (int y = pt_max.y - minDistance; y <= pt_max.y + minDistance; ++y)
		{
			if (y < 0 || y >= cim.rows)
				continue;
			for (int x = pt_max.x - minDistance; x <= pt_max.x + minDistance; ++x)
			{
				if (x < 0 || x >= cim.cols)
					continue;
				if (sqrt(pow(y - pt_max.y, 2) + pow(x - pt_max.x, 2)) <= minDistance)
				{
					cim.at<float>(y, x) = 0;
				}
			}
		}
	} 
	
	std::cout << num << std::endl;
}

代码传送门:https://github.com/taifyang/OpenCV-algorithm

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

给算法爸爸上香

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

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

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

打赏作者

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

抵扣说明:

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

余额充值