欢迎访问 生活随笔!

生活随笔

当前位置: 首页 > 编程资源 > 编程问答 >内容正文

编程问答

OpenCV之feature2d 模块. 2D特征框架(1)Harris 角点检测子 Shi-Tomasi角点检测子 定制化创建角点检测子 亚像素级的角点检测 特征点检测

发布时间:2025/3/21 编程问答 38 豆豆

Harris 角点检测子

目标

本教程中我们将涉及:

  • 有哪些特征?它们有什么用?
  • 使用函数 cornerHarris 通过 Harris-Stephens方法检测角点.

理论

有哪些特征?

在计算机视觉中,我们通常需要寻找两张图上的匹配关键点。为什么?因为一旦我们知道了两张图是相关联的,我们就可以使用 *both 图像来提取它们中的信息。

是指

  • 匹配关键点 是指在场景中可以很容易识别出来的 特性 . 这些特性就是这里所说的 特征 。
  • 因此,特征应该有什么样的特性呢?
    • 应该具有 可识别的独一无二性

图像特征类型

图像特征类型:

  • 边缘
  • 角点 (感兴趣关键点)
  • 斑点(Blobs) (感兴趣区域)

本教程涉及 角点 特征。

为什么角点是特殊的?

  • 因为角点是两个边缘的连接点,它代表了两个边缘变化的方向上的点。图像梯度有很高的变化。这种变化是可以用来帮助检测角点的。

如何工作?

  • 由于角点代表了图像像素梯度变化,我们将寻找这个”变化”。

  • 考虑到一个灰度图像 . 划动窗口  (with displacements  在x方向和  方向)  计算像素灰度变化。

    其中:

    •  is the window at position 
    •  is the intensity at 
    •  is the intensity at the moved window 
  • 为了寻找带角点的窗口,我们搜索像素灰度变化较大的窗口。于是, 我们期望最大化以下式子:

  • 使用 泰勒(Taylor)展开式:

  • 式子可以展开为:

  • 一个举证表达式可以写为:

  • 表示为:

  • 因此我们有等式:

  • 每个窗口中计算得到一个值。这个值决定了这个窗口中是否包含了角点:

    其中:

    • det(M) = 
    • trace(M) = 

    一个窗口,它的分数  大于一个特定值,这个窗口就可以被认为是”角点”

代码

这个教程的代码如下所示。还可以通过 这个链接下载到源代码

#include "opencv2/highgui/highgui.hpp" #include "opencv2/imgproc/imgproc.hpp" #include <iostream> #include <stdio.h> #include <stdlib.h>using namespace cv; using namespace std;/// Global variables Mat src, src_gray; int thresh = 200; int max_thresh = 255;char* source_window = "Source image"; 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 graysrc = imread( argv[1], 1 );cvtColor( src, src_gray, CV_BGR2GRAY );/// Create a window and a trackbarnamedWindow( source_window, CV_WINDOW_AUTOSIZE );createTrackbar( "Threshold: ", source_window, &thresh, max_thresh, cornerHarris_demo );imshow( source_window, src );cornerHarris_demo( 0, 0 );waitKey(0);return(0); }/** @function cornerHarris_demo */ void cornerHarris_demo( int, void* ) {Mat dst, dst_norm, dst_norm_scaled;dst = Mat::zeros( src.size(), CV_32FC1 );/// Detector parametersint blockSize = 2;int apertureSize = 3;double k = 0.04;/// Detecting cornerscornerHarris( src_gray, dst, blockSize, apertureSize, k, BORDER_DEFAULT );/// Normalizingnormalize( dst, dst_norm, 0, 255, NORM_MINMAX, CV_32FC1, Mat() );convertScaleAbs( dst_norm, dst_norm_scaled );/// Drawing a circle around cornersfor( int j = 0; j < dst_norm.rows ; j++ ){ for( int i = 0; i < dst_norm.cols; i++ ){if( (int) dst_norm.at<float>(j,i) > thresh ){circle( dst_norm_scaled, Point( i, j ), 5, Scalar(0), 2, 8, 0 );}}}/// Showing the resultnamedWindow( corners_window, CV_WINDOW_AUTOSIZE );imshow( corners_window, dst_norm_scaled ); }

解释

实验结果

原始图像:

检测到的角点被黑色圈标记了









Shi-Tomasi角点检测子

目标

在这个教程中我们将涉及:

  • 使用函数 goodFeaturesToTrack 来调用Shi-Tomasi方法检测角点。

理论

代码

这个教程的代码如下所示。源代码还可以从 这个链接下载得到

#include "opencv2/highgui/highgui.hpp" #include "opencv2/imgproc/imgproc.hpp" #include <iostream> #include <stdio.h> #include <stdlib.h>using namespace cv; using namespace std;/// Global variables Mat src, src_gray;int maxCorners = 23; int maxTrackbar = 100;RNG rng(12345); 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 graysrc = imread( argv[1], 1 );cvtColor( src, src_gray, CV_BGR2GRAY );/// Create WindownamedWindow( source_window, CV_WINDOW_AUTOSIZE );/// Create Trackbar to set the number of cornerscreateTrackbar( "Max corners:", source_window, &maxCorners, maxTrackbar, goodFeaturesToTrack_Demo );imshow( source_window, src );goodFeaturesToTrack_Demo( 0, 0 );waitKey(0);return(0); }/** * @function goodFeaturesToTrack_Demo.cpp * @brief Apply Shi-Tomasi corner detector */ void goodFeaturesToTrack_Demo( int, void* ) {if( maxCorners < 1 ) { maxCorners = 1; }/// Parameters for Shi-Tomasi algorithmvector<Point2f> corners;double qualityLevel = 0.01;double minDistance = 10;int blockSize = 3;bool useHarrisDetector = false;double k = 0.04;/// Copy the source imageMat copy;copy = src.clone();/// Apply corner detectiongoodFeaturesToTrack( src_gray,corners,maxCorners,qualityLevel,minDistance,Mat(),blockSize,useHarrisDetector,k );/// Draw corners detectedcout<<"** Number of corners detected: "<<corners.size()<<endl;int r = 4;for( int i = 0; i < corners.size(); i++ ){ circle( copy, corners[i], r, Scalar(rng.uniform(0,255), rng.uniform(0,255),rng.uniform(0,255)), -1, 8, 0 ); }/// Show what you gotnamedWindow( source_window, CV_WINDOW_AUTOSIZE );imshow( source_window, copy ); }

解释

结果¶









定制化创建角点检测子

目标

在这个教程中我们将涉及:

  • 使用 OpenCV 函数 cornerEigenValsAndVecs 来计算像素对应的本征值和本征向量来确定其是否是角点。
  • 使用OpenCV 函数 cornerMinEigenVal 通过最小化本征值来进行角点检测。
  • 用上述两个函数实现一个定制化的Harris detector,类似Shi-Tomasi检测子。

解释

代码

这个教程的代码如下所示。源代码还可以从 这个链接下载得到

#include "opencv2/highgui/highgui.hpp" #include "opencv2/imgproc/imgproc.hpp" #include <iostream> #include <stdio.h> #include <stdlib.h>using namespace cv; using namespace std;/// Global variables Mat src, src_gray; Mat myHarris_dst; Mat myHarris_copy; Mat Mc; Mat myShiTomasi_dst; Mat myShiTomasi_copy;int myShiTomasi_qualityLevel = 50; int myHarris_qualityLevel = 50; int max_qualityLevel = 100;double myHarris_minVal; double myHarris_maxVal; double myShiTomasi_minVal; double myShiTomasi_maxVal;RNG rng(12345);char* myHarris_window = "My Harris corner detector"; 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 graysrc = imread( argv[1], 1 );cvtColor( src, src_gray, CV_BGR2GRAY );/// Set some parametersint blockSize = 3; int apertureSize = 3;/// My Harris matrix -- Using cornerEigenValsAndVecsmyHarris_dst = Mat::zeros( src_gray.size(), CV_32FC(6) );Mc = Mat::zeros( src_gray.size(), CV_32FC1 );cornerEigenValsAndVecs( src_gray, myHarris_dst, blockSize, apertureSize, BORDER_DEFAULT );/* calculate Mc */for( int j = 0; j < src_gray.rows; j++ ){ for( int i = 0; i < src_gray.cols; i++ ){float lambda_1 = myHarris_dst.at<float>( j, i, 0 );float lambda_2 = myHarris_dst.at<float>( j, i, 1 );Mc.at<float>(j,i) = lambda_1*lambda_2 - 0.04*pow( ( lambda_1 + lambda_2 ), 2 );}}minMaxLoc( Mc, &myHarris_minVal, &myHarris_maxVal, 0, 0, Mat() );/* Create Window and Trackbar */namedWindow( myHarris_window, CV_WINDOW_AUTOSIZE );createTrackbar( " Quality Level:", myHarris_window, &myHarris_qualityLevel, max_qualityLevel,myHarris_function );myHarris_function( 0, 0 );/// My Shi-Tomasi -- Using cornerMinEigenValmyShiTomasi_dst = Mat::zeros( src_gray.size(), CV_32FC1 );cornerMinEigenVal( src_gray, myShiTomasi_dst, blockSize, apertureSize, BORDER_DEFAULT );minMaxLoc( myShiTomasi_dst, &myShiTomasi_minVal, &myShiTomasi_maxVal, 0, 0, Mat() );/* Create Window and Trackbar */namedWindow( myShiTomasi_window, CV_WINDOW_AUTOSIZE );createTrackbar( " Quality Level:", myShiTomasi_window, &myShiTomasi_qualityLevel, max_qualityLevel,myShiTomasi_function );myShiTomasi_function( 0, 0 );waitKey(0);return(0); }/** @function myShiTomasi_function */ void myShiTomasi_function( int, void* ) {myShiTomasi_copy = src.clone();if( myShiTomasi_qualityLevel < 1 ) { myShiTomasi_qualityLevel = 1; }for( int j = 0; j < src_gray.rows; j++ ){ for( int i = 0; i < src_gray.cols; i++ ){if( myShiTomasi_dst.at<float>(j,i) > myShiTomasi_minVal + ( myShiTomasi_maxVal -myShiTomasi_minVal )*myShiTomasi_qualityLevel/max_qualityLevel ){ circle( myShiTomasi_copy, Point(i,j), 4, Scalar( rng.uniform(0,255),rng.uniform(0,255), rng.uniform(0,255) ), -1, 8, 0 ); }}}imshow( myShiTomasi_window, myShiTomasi_copy ); }/** @function myHarris_function */ void myHarris_function( int, void* ) {myHarris_copy = src.clone();if( myHarris_qualityLevel < 1 ) { myHarris_qualityLevel = 1; }for( int j = 0; j < src_gray.rows; j++ ){ for( int i = 0; i < src_gray.cols; i++ ){if( Mc.at<float>(j,i) > myHarris_minVal + ( myHarris_maxVal - myHarris_minVal )*myHarris_qualityLevel/max_qualityLevel ){ circle( myHarris_copy, Point(i,j), 4, Scalar( rng.uniform(0,255), rng.uniform(0,255),rng.uniform(0,255) ), -1, 8, 0 ); }}}imshow( myHarris_window, myHarris_copy ); }

解释

结果









亚像素级的角点检测

目标

在本教程中我们将涉及以下内容:

  • 使用OpenCV函数 cornerSubPix 寻找更精确的角点位置 (不是整数类型的位置,而是更精确的浮点类型位置).

理论

代码

这个教程的代码如下所示。源代码还可以从 这个链接下载得到

#include "opencv2/highgui/highgui.hpp" #include "opencv2/imgproc/imgproc.hpp" #include <iostream> #include <stdio.h> #include <stdlib.h>using namespace cv; using namespace std;/// Global variables Mat src, src_gray;int maxCorners = 10; int maxTrackbar = 25;RNG rng(12345); 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 graysrc = imread( argv[1], 1 );cvtColor( src, src_gray, CV_BGR2GRAY );/// Create WindownamedWindow( source_window, CV_WINDOW_AUTOSIZE );/// Create Trackbar to set the number of cornerscreateTrackbar( "Max corners:", source_window, &maxCorners, maxTrackbar, goodFeaturesToTrack_Demo);imshow( source_window, src );goodFeaturesToTrack_Demo( 0, 0 );waitKey(0);return(0); }/** * @function goodFeaturesToTrack_Demo.cpp * @brief Apply Shi-Tomasi corner detector */ void goodFeaturesToTrack_Demo( int, void* ) {if( maxCorners < 1 ) { maxCorners = 1; }/// Parameters for Shi-Tomasi algorithmvector<Point2f> corners;double qualityLevel = 0.01;double minDistance = 10;int blockSize = 3;bool useHarrisDetector = false;double k = 0.04;/// Copy the source imageMat copy;copy = src.clone();/// Apply corner detectiongoodFeaturesToTrack( src_gray,corners,maxCorners,qualityLevel,minDistance,Mat(),blockSize,useHarrisDetector,k );/// Draw corners detectedcout<<"** Number of corners detected: "<<corners.size()<<endl;int r = 4;for( int i = 0; i < corners.size(); i++ ){ circle( copy, corners[i], r, Scalar(rng.uniform(0,255), rng.uniform(0,255),rng.uniform(0,255)), -1, 8, 0 ); }/// Show what you gotnamedWindow( source_window, CV_WINDOW_AUTOSIZE );imshow( source_window, copy );/// Set the neeed parameters to find the refined cornersSize winSize = Size( 5, 5 );Size zeroZone = Size( -1, -1 );TermCriteria criteria = TermCriteria( CV_TERMCRIT_EPS + CV_TERMCRIT_ITER, 40, 0.001 );/// Calculate the refined corner locationscornerSubPix( src_gray, corners, winSize, zeroZone, criteria );/// Write them downfor( int i = 0; i < corners.size(); i++ ){ cout<<" -- Refined Corner ["<<i<<"] ("<<corners[i].x<<","<<corners[i].y<<")"<<endl; } }

解释

结果

亚像素级的角点检测结果:







特征点检测

目标

在本教程中,我们将涉及:

  • 使用 FeatureDetector 接口来发现感兴趣点。特别地:
    • 使用 SurfFeatureDetector 以及它的函数 detect 来实现检测过程
    • 使用函数 drawKeypoints 来绘制检测到的关键点

理论

代码

这个教程的代码如下所示。你还可以从 这个链接下载到源代码

#include <stdio.h> #include <iostream> #include "opencv2/core/core.hpp" #include "opencv2/features2d/features2d.hpp" #include "opencv2/highgui/highgui.hpp"using namespace cv;void readme();/** @function main */ int main( int argc, char** argv ) {if( argc != 3 ){ readme(); return -1; }Mat img_1 = imread( argv[1], CV_LOAD_IMAGE_GRAYSCALE );Mat img_2 = imread( argv[2], CV_LOAD_IMAGE_GRAYSCALE );if( !img_1.data || !img_2.data ){ std::cout<< " --(!) Error reading images " << std::endl; return -1; }//-- Step 1: Detect the keypoints using SURF Detectorint minHessian = 400;SurfFeatureDetector detector( minHessian );std::vector<KeyPoint> keypoints_1, keypoints_2;detector.detect( img_1, keypoints_1 );detector.detect( img_2, keypoints_2 );//-- Draw keypointsMat img_keypoints_1; Mat img_keypoints_2;drawKeypoints( img_1, keypoints_1, img_keypoints_1, Scalar::all(-1), DrawMatchesFlags::DEFAULT );drawKeypoints( img_2, keypoints_2, img_keypoints_2, Scalar::all(-1), DrawMatchesFlags::DEFAULT );//-- Show detected (drawn) keypointsimshow("Keypoints 1", img_keypoints_1 );imshow("Keypoints 2", img_keypoints_2 );waitKey(0);return 0;}/** @function readme */void readme(){ std::cout << " Usage: ./SURF_detector <img1> <img2>" << std::endl; }

解释

结果

  • 这是第一张图的特征点检测结果:

  • 这是第二张图的特征点检测:






  • from: http://www.opencv.org.cn/opencvdoc/2.3.2/html/doc/tutorials/features2d/table_of_content_features2d/table_of_content_features2d.html#table-of-content-feature2d

    总结

    以上是生活随笔为你收集整理的OpenCV之feature2d 模块. 2D特征框架(1)Harris 角点检测子 Shi-Tomasi角点检测子 定制化创建角点检测子 亚像素级的角点检测 特征点检测的全部内容,希望文章能够帮你解决所遇到的问题。

    如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。