本系列代码托管于:https://github.com/chintsan-code/opencv4-tutorials

本篇使用的项目为:corner_detect

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

using namespace cv;
using namespace std;

void harris_demo(Mat &image);
void shitomas_demo(Mat &image);
int main(int argc, const char** argv) {
	VideoCapture capture("../sample/color_object.mp4");
	if (!capture.isOpened()) {
		printf("could not open the camera...\n");
	}
	namedWindow("frame", WINDOW_AUTOSIZE);
	Mat frame;
	while (true) {
		bool ret = capture.read(frame);
		if (!ret) break;
		imshow("frame", frame);
		shitomas_demo(frame);
		imshow("result", frame);
		char c = waitKey(1);
		if (c == 27) { // ESC
			break;
		}
	}
	capture.release();
	
	waitKey(0);
	destroyAllWindows();
	return 0;
}

void harris_demo(Mat &image) {
	Mat gray;
	cvtColor(image, gray, COLOR_BGR2GRAY);
	Mat dst;
	double k = 0.04;
	int blocksize = 2;
	int ksize = 3;
	cornerHarris(gray, dst, blocksize, ksize, k);
	Mat dst_norm = Mat::zeros(dst.size(), dst.type());
	normalize(dst, dst_norm, 0, 255, NORM_MINMAX, -1, Mat());
	convertScaleAbs(dst_norm, dst_norm);

	// draw corners
	RNG rng(12345);
	for (int row = 0; row < image.rows; row++) {
		for (int col = 0; col < image.cols; col++) {
			int rsp = dst_norm.at<uchar>(row, col);
			if (rsp > 150) {
				int b = rng.uniform(0, 255);
				int g = rng.uniform(0, 255);
				int r = rng.uniform(0, 255);
				circle(image, Point(col, row), 5, Scalar(b, g, r), 2, 8, 0);
			}
		}
	}
}

void shitomas_demo(Mat &image) {
	Mat gray;
	cvtColor(image, gray, COLOR_BGR2GRAY);
	vector<Point2f> corners;
	double quality_level = 0.01;
	RNG rng(12345);
	goodFeaturesToTrack(gray, corners, 200, quality_level, 3, Mat(), 3, false);
	for (int i = 0; i < corners.size(); i++) {
		int b = rng.uniform(0, 255);
		int g = rng.uniform(0, 255);
		int r = rng.uniform(0, 255);
		circle(image, corners[i], 5, Scalar(b, g, r), 2, 8, 0);
	}
}

角点定义

在X方向和Y方向都有最大的梯度变化的像素点

opencv4入门笔记(38):图像角点检测-萤火

cornerHarris:Harris角点检测

void cornerHarris( InputArray src, OutputArray dst, int blockSize, int ksize, double k, int borderType = BORDER_DEFAULT );
  • src:输入图像,单通道的8-bit或浮点图像
  • dst:存储着Harris角点检测的图像矩阵,与src具有相同的尺寸,类型为CV_32FC1
  • blockSize:邻域大小
  • ksize:Sobel算子的卷积核尺寸
  • k:Harris角点检测器中的k,一般取值0.04~0.06
  • borderType:边缘处理方式
opencv4入门笔记(38):图像角点检测-萤火
opencv4入门笔记(38):图像角点检测-萤火

\(\lambda_1和\lambda_2都比较小,认为是平坦区域(FlatRegion)\)

\(\lambda_1>>\lambda_2或\lambda_2>>\lambda_1,认为是边缘(Edge)\)

\(\lambda_1和\lambda_2都比较大是,才认为是角点(Corner)\)

goodFeaturesToTrack:Shi-tomasi角点检测

Shi-tomasi是对Harris角点检测计算的简化

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 );
  • image: 输入图像,单通道的8-bit或32-bit浮点图像
  • corners:角点,vector
  • maxCorners:最多检测多少角点,如果设为0或负数,检测全部
  • qualityLevel:用于过滤角点。例如最佳角点的响应为1500,qualityLevel为0.01,那么响应小于15的角点都会被过滤掉
  • minDistance:角点间的最小距离,用于过滤。如果小于这个值,就认为是同一个角点
  • mask:掩模
  • blockSize:邻域大小
  • useHarrisDetector:使用Harris角点检测
  • k:Harris角点检测器中的k,一般取值0.04~0.06。只有在使用Harris角点检测器时才起作用
opencv4入门笔记(38):图像角点检测-萤火

计算\(min(\lambda_1,\lambda_2)\)超过一定阈值即认为是角点