一、函数:
goodFeaturesToTrack
函数:
(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 );
CV_EXPORTS_W void goodFeaturesToTrack( InputArray image, OutputArray corners,
int maxCorners, double qualityLevel, double minDistance,
InputArray mask, int blockSize,
int gradientSize, bool useHarrisDetector = false,
double k = 0.04 );
(2)函数作用:
-
goodFeaturesToTrack
函数根据 Shi 和 Tomasi (1994) 的方法,找到图像中最突出的角点或在指定图像区域内的角点。
(3)质量度量计算:
-
函数使用
cornerMinEigenVal
或cornerHarris
在每个源图像像素处计算角点质量度量。
(4)非极大值抑制:
-
执行非极大值抑制,只保留 3x3 邻域内的局部最大值。
(5)质量阈值过滤:
- 质量度量小于
qualityLevel
与最大质量度量乘积的角点被拒绝。
(6)排序:
-
剩余的角点按质量度量降序排序。
(7)距离过滤:
- 如果距离小于
maxDistance
有更强的角点,则丢弃每个角点。
(8)初始化跟踪器:
- 该函数可用于初始化基于点的对象跟踪器。
(9)参数关系:
-
如果使用不同的
qualityLevel
参数值 A 和 B 调用函数,并且 A > B,则qualityLevel=A
返回的角点向量将是qualityLevel=B
输出向量的前缀。
(10)输入参数:
image
:输入的 8 位或浮点型 32 位单通道图像。corners
:输出的检测到的角点向量。maxCorners
:要返回的角点的最大数量。如果检测到的角点更多,则返回最强的角点。maxCorners <= 0
表示没有最大限制,返回所有检测到的角点。qualityLevel
:描述图像角点最小可接受质量的参数。该参数值乘以最佳角点质量度量(最小特征值或 Harris 函数响应),小于乘积的角点被拒绝。minDistance
:返回的角点之间的最小欧几里得距离。mask
:可选的兴趣区域。如果图像非空,它指定了检测角点的区域。blockSize
:计算每个像素邻域的导数协方差矩阵的块大小。useHarrisDetector
:参数,指示是否使用 Harris 检测器或最小特征值。k
:Harris 检测器的自由参数。
(11)相关函数:
-
cornerMinEigenVal
、cornerHarris
、calcOpticalFlowPyrLK
、estimateRigidTransform
等。
二、示例代码:
#include <opencv2/core/utils/logger.hpp>
#include <opencv2/opencv.hpp>
#include <opencv2/videoio.hpp>
#include <opencv2/objdetect.hpp>
#include <opencv2/highgui/highgui_c.h>
#include <iostream>
using namespace cv;
using namespace std;
VideoCapture createInput(bool useCamera, string videoPath);
int main() {
// 设置日志级别为不输出任何日志信息
utils::logging::setLogLevel(utils::logging::LOG_LEVEL_SILENT);
// 定义用于ShiTomasi角点检测的参数
vector<Point2f> corners; // 存储检测到的角点
double qualityLevel = 0.01; // 质量级别,用于确定强角点
double minDistance = 10; // 检测到的角点之间的最小距离
int blockSize = 3; // 对于每个像素,考虑的邻域的大小
int gradiantSize = 3; // 用于计算图像梯度的窗口大小
bool useHarrisDetector = false; // 是否使用Harris角点检测器
double k = 0.04; // Harris角点检测器的参数
//选择使用摄像头或视频文件
bool useCamera = 1;
string videoPath = "C:\\Users\\86173\\Desktop\\TI\\passerby.mp4";;
// 创建并打开视频输入
VideoCapture cap = createInput(useCamera, videoPath);
// 检查视频是否成功打开,如果失败打印错误信息并退出程序
if (!cap.isOpened()) {
std::cout << "fail to open video...\n" << std::endl;
return -1;
}
// 定义Mat对象用于存储帧、灰度图像和显示图像
Mat frame, grayMat, dispMat;
// 定义最大角点数量和跟踪条的值
int maxCorners = 23;
int maxTrackbar = 100;
// 初始化计数器
int cnt = 0;
// 循环读取视频帧直到视频结束
while (1) {
// 从视频流中读取下一帧
cap >> frame;
// 如果帧为空,则退出循环
if (frame.empty()) break;
// 复制当前帧到显示图像
frame.copyTo(dispMat);
// 将当前帧转换为灰度图像
cvtColor(frame, grayMat, COLOR_BGR2GRAY);
// 使用goodFeaturesToTrack函数检测角点
goodFeaturesToTrack(grayMat,
corners,
maxCorners,
qualityLevel,
minDistance,
Mat(),
blockSize,
gradiantSize,
useHarrisDetector,
k);
// 在检测到的角点位置绘制标记
for (size_t i = 0; i < corners.size(); i++) {
circle(dispMat, corners[i], 4, Scalar(255, 255, 255), -1, 8, 0);
}
// 显示带有角点标记的图像
imshow("angular point", dispMat);
// 等待用户按键,如果按下 'q' 键则退出循环
if (waitKey(30) == 'q') {
break;
}
}
// 程序结束,返回0
return 0;
}
// createInput函数定义,根据参数选择视频输入源
VideoCapture createInput(bool useCamera, string videoPath) {
// 创建VideoCapture对象
VideoCapture capVideo;
// 根据参数选择打开摄像头或视频文件
if (useCamera) {
capVideo.open(0); // 0是摄像头的默认设备索引
}
else {
capVideo.open(videoPath); // 打开指定路径的视频文件
}
// 返回VideoCapture对象
return capVideo;
}
三、运行结果: