OpenCV-特征提取与检测(02、Shi-Tomasi角点检测)

版权声明:本文由 Micheal 超 博客 创作,未经博主允许不得转载。 https://blog.csdn.net/qq_42887760/article/details/86628640
  • J.Shi和C.Tomasi在1994年在其论文“Good Features to Track”中,提出了一种对Harris角点检测算子的改进算法——Shi-Tomasi角点检测算子,可以看到,Opencv中函数goodFeaturesToTrack就是直接取自他们论文的名字。
  • 在了解Shi-Tomasi角点检测理论之前,读者最好需要了解一下 Harris角点检测 理论的相关知识

Shi-Tomasi角点检测理论

  • 跟Harris角点检测的理论几乎完全一致,唯一不同的是在使用矩阵 特征值 λ λ 1 λ λ 2 计算角度响应的时候。
  • Harris角点检测 时候计算角点响应时候使用的公式
    在这里插入图片描述
  • Shi-Tomasi角点检测 时候计算角点响应时使用的公式:
    R = m i n ( λ 1 λ 2 ) R = min(λ1, λ2)
    如果 R 值超过阈值,我们就认为它是一个角点。我们可以把它绘制到λ1~λ2空间中,就会得到下图
    在这里插入图片描述
    从这幅图中,我们可以看出来只有当λ1和λ2都大于最小值时,才被认为是角点(绿色区域)。

API参数说明

opencv提供了goodFeaturesToTrack函数用来实现Shi-Tomasi算子,goodFeaturesToTrack有比cornerHarris更多的控制参数,其API函数接口为:
在这里插入图片描述

void goodFeaturesToTrack( // Shi-Tomasi角点检测
    InputArray image,  // 灰度图像
    OutputArray corners, // 检测出来的角点在输入图像的Point
    int maxCorners, // -maxCorners 表示返回角点的数目,如果检测出来的角点数目大于最大数目则返回响应值最强前maxCorners数目。
    double qualityLevel, // -qualityLevel表示最小可接受的向量值1500, 0.01, 15
    double minDistance, // -minDistance两个角点之间的最小距离(欧几里得距离)
    InputArray mask = noArray(), 
    int blockSize = 3, // -blockSize 计算导数微分不同的窗口大小
    bool useHarrisDetector = false, // -useHarrisDetector是否使用Harris角点检测,设置为false的时候 下一个参数 k 无效
    double k = 0.04 // 最好 0.04~0.06 
);
  • 第一个参数image:输入图像,须为8位或浮点型32位单通道图像。
  • 第二个参数corners:位置点向量,保存的是检测到的角点的坐标;
  • 第三个参数maxCorners:定义可以检测到的角点的数量的最大值;
  • 第四个参数qualityLevel :double类型,角点检测可接受的最小特征值。其实际用于过滤角点的最小特征值是qualityLevel与图像中最大特征值的乘积。所以qualityLevel通常不会超过1(常用的值为0.10或者0.01)。而检测完所有的角点后,还要进一步剔除掉一些距离较近的角点。
  • 第五个参数minDistance:两个角点间最小间距,以像素为单位;此参数用于保证返回的焦点之间的距离不小于minDistance个像素。
  • 第六个参数mask:可选参数,表示感兴趣区域,有默认值noArray()。指定检测区域,若检测整幅图像,mask置为空Mat();
  • 第七个参数blockSize :int类型,有默认值3,计算协方差矩阵时窗口大小;
  • 第八个参数useHarrisDetector :bool类型,默认值false,是否使用Harris角点检测,为false,则使用Shi-Tomasi算子;
  • 第九个参数k :double类型,有默认值0.04,为用于设置Hessian自相关矩阵行列式的相对权重的权重系数,一般取经验值0.04~0.06。第八个参数为false时,该参数不起作用;

程序代码

#include <opencv2/opencv.hpp>
#include <iostream>

using namespace cv;
using namespace std;

int num_corners = 25;
int max_corners = 200;
const char* output_title = "ShiTomasi Detector";
Mat src, gray_src;
RNG rng(12345);

void ShiTomasi_Demo(int, void*);

int main(int argc, char** argv) {
	src = imread("E:/Experiment/OpenCV/Pictures/ShiTomasiTest.jpg");
	if (src.empty()) {
		printf("could not load image...\n");
		return -1;
	}
	namedWindow("input image", CV_WINDOW_AUTOSIZE);
	imshow("input image", src);

	cvtColor(src, gray_src, COLOR_BGR2GRAY);
	namedWindow(output_title, CV_WINDOW_AUTOSIZE);
	createTrackbar("Num Corners:", output_title, &num_corners, max_corners, ShiTomasi_Demo);
	ShiTomasi_Demo(0, 0);

	waitKey(0);
	return 0;
}

void ShiTomasi_Demo(int, void*) {
	if (num_corners < 5) {
		num_corners = 5;
	}
	vector<Point2f> corners;
	double qualityLevel = 0.01;
	double minDistance = 10;
	int blockSize = 3;
	bool useHarris = false;
	double k = 0.04;
	Mat resultImg = gray_src.clone();
	cvtColor(resultImg, resultImg, COLOR_GRAY2BGR);// 让原图灰度,角点彩色
	// opencv中的所有函数都有对应的 cv 开头的函数,那是没有使用命名空间时使用的,函数作用一致
    // shi-tomasi 角点检测,运算速度比harris角点检测要快很多,但是harris找出的角点比ShiTomasi要多。不过ShiTomasi的检测结果是能接受的
	goodFeaturesToTrack(gray_src, corners, num_corners, qualityLevel, minDistance, Mat(), blockSize, useHarris, k);
	printf("Number of Detected Corners:  %d\n", corners.size());

	for (size_t t = 0; t < corners.size(); t++) {
		circle(resultImg, corners[t], 2, Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255)), 2, 8, 0);
	}
	imshow(output_title, resultImg);
}

运行截图

在这里插入图片描述

参考博客:

  1. https://blog.csdn.net/dcrmg/article/details/52551637
  2. https://blog.csdn.net/lly_117/article/details/80324947
  3. https://blog.csdn.net/qq_36387683/article/details/80550964
  4. https://blog.csdn.net/chaipp0607/article/details/54697457
  5. https://blog.csdn.net/huanghuangjin/article/details/81262115

猜你喜欢

转载自blog.csdn.net/qq_42887760/article/details/86628640
今日推荐