OpenCV之feature2d 模块. 2D特征框架(1)Harris 角点检测子 Shi-Tomasi角点检测子 定制化创建角点检测子 亚像素级的角点检测 特征点检测
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角点检测子 定制化创建角点检测子 亚像素级的角点检测 特征点检测的全部内容,希望文章能够帮你解决所遇到的问题。
- 上一篇: OpenCV之calib3d 模块. 相
- 下一篇: OpenCV之feature2d 模块.