一、角點檢測的相關概念
二、Harris角點檢測——cornerHarris()
參考網址: http://www.cnblogs.com/ronny/p/4009425.html
#include "opencv2/opencv.hpp" #include<iostream> using namespace std; using namespace cv; void main() { Mat img = imread("E://3.jpg"); imshow("src", img); Mat result = img.clone(); Mat gray, dst , corner_img;//corner_img存放檢測后的角點圖像 cvtColor(img, gray, CV_BGR2GRAY); cornerHarris(gray, corner_img, 2, 3, 0.04);//cornerHarris角點檢測 //imshow("corner", corner_img); threshold(corner_img, dst, 0.015, 255, CV_THRESH_BINARY); imshow("dst", dst); int rowNumber = gray.rows; //獲取行數 int colNumber = gray.cols; //獲取每一行的元素 cout << rowNumber << endl; cout << colNumber << endl; cout << dst.type() << endl; for (int i = 0; i<rowNumber; i++) { for (int j = 0; j<colNumber; j++) { if (dst.at<float>(i, j) == 255)//二值化后,灰度值為255為角點 { circle(result, Point(j, i),3, Scalar(0, 255, 0), 2, 8); } } } imshow("result", result); waitKey(0); }
淺墨代碼
http://blog.csdn.net/poem_qianmo/article/details/29356187
#include "opencv2/opencv.hpp" #include<iostream> using namespace std; using namespace cv; #define WINDOW_NAME1 "【程序窗口1】" #define WINDOW_NAME2 "【程序窗口2】" Mat g_srcImage, g_srcImage1, g_grayImage; int thresh = 30; //當前閾值 int max_thresh = 175; //最大閾值 void on_CornerHarris(int, void*) { Mat dstImage;//目標圖 Mat normImage;//歸一化后的圖 Mat scaledImage;//線性變換后的八位無符號整型的圖 //初始化:置零當前需要顯示的兩幅圖,即清除上一次調用此函數時他們的值 dstImage = Mat::zeros(g_srcImage.size(), CV_32FC1); g_srcImage1 = g_srcImage.clone(); //進行角點檢測 cornerHarris(g_grayImage, dstImage, 2, 3, 0.04); // 歸一化與轉換 normalize(dstImage, normImage, 0, 255, NORM_MINMAX, CV_32FC1, Mat()); convertScaleAbs(normImage, scaledImage);//將歸一化后的圖線性變換成8位無符號整型 // 進行繪制:將檢測到的,且符合閾值條件的角點繪制出來 for (int j = 0; j < normImage.rows; j++) { for (int i = 0; i < normImage.cols; i++) { if ((int)normImage.at<float>(j, i) > thresh + 80) { circle(g_srcImage1, Point(i, j), 5, Scalar(10, 10, 255), 2, 8, 0); circle(scaledImage, Point(i, j), 5, Scalar(0, 10, 255), 2, 8, 0); } } } imshow(WINDOW_NAME1, g_srcImage1); imshow(WINDOW_NAME2, scaledImage); } static void ShowHelpText() { printf("\n\n\n\t\t\t【歡迎來到Harris角點檢測示例程序~】\n\n"); printf("\n\n\n\t請調整滾動條觀察圖像效果~\n\n"); printf("\n\n\t\t\t\t\t\t\t\t by淺墨"); } void main() { system("color 3F"); ShowHelpText(); //載入原始圖並進行克隆保存 g_srcImage = imread("E://1.jpg", 1); if (!g_srcImage.data) { printf("讀取圖片錯誤,請確定目錄下是否有imread函數指定的圖片存在~! \n"); return ; } imshow("原始圖", g_srcImage); g_srcImage1 = g_srcImage.clone(); cvtColor(g_srcImage1, g_grayImage, CV_BGR2GRAY); //創建窗口和滾動條 namedWindow(WINDOW_NAME1, CV_WINDOW_NORMAL); createTrackbar("閾值: ", WINDOW_NAME1, &thresh, max_thresh, on_CornerHarris); on_CornerHarris(0, 0);//調用一次回調函數,進行初始化 waitKey(0); }
三、Shi-Tomasi角點檢測——goodFeaturesToTrack()
#include "opencv2/opencv.hpp" #include<iostream> using namespace std; using namespace cv; void main() { Mat src = imread("E://0.jpg"); imshow("src", src); Mat result = src.clone(); Mat gray; cvtColor(src, gray,CV_BGR2GRAY); vector<Point2f>corners;//Point2f類型的向量:存儲每個角點的坐標 //輸入圖,向量,最大角點數量,角點的最小特征值,角點間最小距離,掩碼(Mat()表示掩碼為空),blocksize,是否使用Harris角點檢測,權重系數 goodFeaturesToTrack(gray, corners, 100,0.01,10,Mat(),3,false,0.04); cout << "角點數量" << corners.size() << endl; //畫圓標注角點 for (int i = 0; i < corners.size(); i++) circle(result, corners[i], 5, Scalar(0, 255, 0),2,8); imshow("result", result); waitKey(0); }
淺墨大神代碼(加了滑動條效果)
#include "opencv2/opencv.hpp" #include <iostream> using namespace cv; using namespace std; #define WINDOW_NAME "【Shi-Tomasi角點檢測】" Mat g_srcImage, g_grayImage; int g_maxCornerNumber = 33; int g_maxTrackbarNumber = 500; RNG g_rng(12345);//初始化隨機數生成器 //-----------------------------【on_GoodFeaturesToTrack( )函數】---------------------------- // 描述:響應滑動條移動消息的回調函數 //---------------------------------------------------------------------------------------------- void on_GoodFeaturesToTrack(int, void*) { //【1】對變量小於等於1時的處理 if (g_maxCornerNumber <= 1) { g_maxCornerNumber = 1; } //【2】Shi-Tomasi算法(goodFeaturesToTrack函數)的參數准備 vector<Point2f> corners; double qualityLevel = 0.01;//角點檢測可接受的最小特征值 double minDistance = 10;//角點之間的最小距離 int blockSize = 3;//計算導數自相關矩陣時指定的鄰域范圍 double k = 0.04;//權重系數 Mat copy = g_srcImage.clone(); //復制源圖像到一個臨時變量中,作為感興趣區域 //【3】進行Shi-Tomasi角點檢測 goodFeaturesToTrack(g_grayImage,//輸入圖像 corners,//檢測到的角點的輸出向量 g_maxCornerNumber,//角點的最大數量 qualityLevel,//角點檢測可接受的最小特征值 minDistance,//角點之間的最小距離 Mat(),//感興趣區域 blockSize,//計算導數自相關矩陣時指定的鄰域范圍 false,//不使用Harris角點檢測 k);//權重系數 //【4】輸出文字信息 cout << "\t>此次檢測到的角點數量為:" << corners.size() << endl; //【5】繪制檢測到的角點 int r = 4; for (int i = 0; i < corners.size(); i++) { //以隨機的顏色繪制出角點 circle(copy, corners[i], r, Scalar(g_rng.uniform(0, 255), g_rng.uniform(0, 255), g_rng.uniform(0, 255)), -1, 8, 0); } //【6】顯示(更新)窗口 imshow(WINDOW_NAME, copy); } static void ShowHelpText() { //輸出歡迎信息和OpenCV版本 printf("\n\n\t\t\t非常感謝購買《OpenCV3編程入門》一書!\n"); printf("\n\n\t\t\t此為本書OpenCV2版的第87個配套示例程序\n"); printf("\n\n\t\t\t 當前使用的OpenCV版本為:" CV_VERSION); printf("\n\n ----------------------------------------------------------------------------\n"); //輸出一些幫助信息 printf("\n\n\n\t歡迎來到【Shi-Tomasi角點檢測】示例程序\n"); printf("\n\t請調整滑動條觀察圖像效果\n\n"); } void main() { system("color 2F"); ShowHelpText(); //【1】載入源圖像並將其轉換為灰度圖 g_srcImage = imread("3.jpg", 1); cvtColor(g_srcImage, g_grayImage, CV_BGR2GRAY); //【2】創建窗口和滑動條,並進行顯示和回調函數初始化 namedWindow(WINDOW_NAME, CV_WINDOW_AUTOSIZE); createTrackbar("最大角點數", WINDOW_NAME, &g_maxCornerNumber, g_maxTrackbarNumber, on_GoodFeaturesToTrack); imshow(WINDOW_NAME, g_srcImage); on_GoodFeaturesToTrack(0, 0); waitKey(0); }
由於VS2015和opencv2有些兼容問題,會出現斷言錯誤(具體原因在上一篇博客有講),這里就不貼效果圖了。
四、亞像素角點檢測——cornerSubPix()
#include "opencv2/opencv.hpp" #include<iostream> using namespace std; using namespace cv; void main() { Mat img = imread("E://2.jpg"); imshow("src", img); Mat result = img.clone(); Mat gray; cvtColor(img, gray, CV_BGR2GRAY); //Shi-Tomasi角點檢測 vector<Point2f> corners; goodFeaturesToTrack(gray, corners, 100, 0.01, 10, Mat(), 3, false, 0.04); cout << "角點數量" << corners.size() << endl; for (int i = 0; i<corners.size(); i++) { cout << "像素坐標:(" << corners[i].x << ", " << corners[i].y << ")" << endl; circle(result, corners[i], 5, Scalar(0, 255, 0), 2, 8); } imshow("result", result); Size winSize = Size(5, 5); Size zeroZone = Size(-1, -1); //精度或最大迭代數目,其中任意一個達到 迭代次數40,精度0.001 TermCriteria criteria = TermCriteria(CV_TERMCRIT_EPS + CV_TERMCRIT_ITER, 40, 0.001); cornerSubPix(gray, corners, winSize, zeroZone, criteria); for (int j = 0; j<corners.size(); j++) { cout << "亞像素坐標:(" << corners[j].x << ", " << corners[j].y << ")" << endl; circle(img, corners[j], 5, Scalar(0, 255, 0), -1, 8); } imshow("subPix", img); waitKey(0); }