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 模块.