標籤:
本系列學習筆記參考自OpenCV2.4.10之opencv\sources\samples\cpp\tutorial_code和http://www.opencv.org.cn/opencvdoc/2.3.2/html/genindex.html
在映像中我們往往需要檢測出一定形狀的圖形,比如圓等。霍夫變換就是用來檢測映像中特定形狀的變換,本文將介紹霍夫變換進行檢測員和霍夫變換檢測線的應用。
1.HoughCircle_Demo.cpp(霍夫圓變換)示意demo源碼及注釋如下:
#include "stdafx.h" //先行編譯標頭檔 /**霍夫圓變換demo */#include "opencv2/highgui/highgui.hpp"#include "opencv2/imgproc/imgproc.hpp"#include <iostream>using namespace cv;namespace{ // 滑動條命名 const std::string windowName = "Hough Circle Detection Demo"; const std::string cannyThresholdTrackbarName = "Canny threshold"; const std::string accumulatorThresholdTrackbarName = "Accumulator Threshold"; const std::string usage = "Usage : tutorial_HoughCircle_Demo <path_to_input_image>\n"; // 初始值和最大值 const int cannyThresholdInitialValue = 200; const int accumulatorThresholdInitialValue = 50; const int maxAccumulatorThreshold = 200; const int maxCannyThreshold = 255;//霍夫圓檢測主函數 void HoughDetection(const Mat& src_gray, const Mat& src_display, int cannyThreshold, int accumulatorThreshold) { // 儲存檢測到的圓 std::vector<Vec3f> circles; // 霍夫圓檢測函數 HoughCircles( src_gray, circles, CV_HOUGH_GRADIENT, 1, src_gray.rows/8, cannyThreshold, accumulatorThreshold, 0, 0 ); // 顯示 Mat display = src_display.clone(); for( size_t i = 0; i < circles.size(); i++ ) { Point center(cvRound(circles[i][0]), cvRound(circles[i][1])); int radius = cvRound(circles[i][2]); // 圓中心 circle( display, center, 3, Scalar(0,255,0), -1, 8, 0 ); // 圓周線 circle( display, center, radius, Scalar(0,0,255), 3, 8, 0 ); } // 顯示檢測結果 imshow( windowName, display); }}int main(int argc, char** argv){ Mat src, src_gray; // 讀入映像 src = imread("D:\\opencv\\lena.png", 1 ); if( !src.data ) { std::cerr<<"Invalid input image\n"; std::cout<<usage; return -1; } // 轉換成灰階圖 cvtColor( src, src_gray, COLOR_BGR2GRAY ); // 減少映像雜訊以避免錯誤的檢測 GaussianBlur( src_gray, src_gray, Size(9, 9), 2, 2 ); //初始化 int cannyThreshold = cannyThresholdInitialValue; int accumulatorThreshold = accumulatorThresholdInitialValue; // 建立視窗和滑動條 namedWindow( windowName, WINDOW_AUTOSIZE ); createTrackbar(cannyThresholdTrackbarName, windowName, &cannyThreshold,maxCannyThreshold); createTrackbar(accumulatorThresholdTrackbarName, windowName, &accumulatorThreshold, maxAccumulatorThreshold); // 無限迴圈顯示 // 更新檢測映像直到輸入q或者Q int key = 0; while(key != 'q' && key != 'Q') { //確保這些參數不為0 cannyThreshold = std::max(cannyThreshold, 1); accumulatorThreshold = std::max(accumulatorThreshold, 1); //檢測與顯示 HoughDetection(src_gray, src, cannyThreshold, accumulatorThreshold); key = waitKey(10); } return 0;}運行:
核心函數為HouguCircles,該函數用於使用霍夫曼變換在灰階圖中檢測圓,函數原型為:C++: void HoughCircles(InputArray image, OutputArray circles, int method, double dp, double minDist, double param1=100, double param2=100, int minRadius=0, int maxRadius=0 )第一個參數image為待檢測的8位單通道灰階圖,第二個參數circles為檢測到的圓,該參數為一個向量,其中向量每個元素為一個三個元素的向量(x,y,radius),x和y代表圓心座標,radius代表半徑。method為檢測方式,當前的檢測方式為CV_HOUGH_GRADIENT,即梯度檢測。第三個參數dp為解析度比率,一般為1。我的感覺是該值越大,檢測到的圓越多。第四個參數minDist為檢測到的圓的圓心之間的最小距離,該值太大會導致檢測多個相鄰的圓被錯誤的檢測成一個。如果該值過大,會發生漏檢情況。param1為canny邊緣檢測閾值,param2為蓄能器閾值,param3和param4為檢測圓的最小半徑和最大半徑。
1.HoughLines_Demo.cpp(霍夫線變換)
執行個體Demo源碼及注釋如下:
#include "stdafx.h" //先行編譯標頭檔 /**霍夫線變化Demo */#include "opencv2/highgui/highgui.hpp"#include "opencv2/imgproc/imgproc.hpp"#include <iostream>#include <stdio.h>using namespace cv;using namespace std;/// 全域變數Mat src, edges;Mat src_gray;Mat standard_hough, probabilistic_hough;int min_threshold = 50;int max_trackbar = 150;const char* standard_name = "Standard Hough Lines Demo";const char* probabilistic_name = "Probabilistic Hough Lines Demo";int s_trackbar = max_trackbar;int p_trackbar = max_trackbar;/// 函式宣告void Standard_Hough( int, void* );void Probabilistic_Hough( int, void* );/** 主函數 */int main( int, char** argv ){ ///讀入映像 src = imread("D:\\opencv\\lena.png", 1 ); ///將映像轉換為灰階圖 cvtColor( src, src_gray, COLOR_RGB2GRAY ); ///進行Canny邊緣檢測 Canny( src_gray, edges, 50, 200, 3 ); ///建立閾值滑動條 char thresh_label[50]; sprintf( thresh_label, "Thres: %d + input", min_threshold ); namedWindow( standard_name, WINDOW_AUTOSIZE ); createTrackbar( thresh_label, standard_name, &s_trackbar, max_trackbar, Standard_Hough); namedWindow( probabilistic_name, WINDOW_AUTOSIZE ); createTrackbar( thresh_label, probabilistic_name, &p_trackbar, max_trackbar, Probabilistic_Hough); ///開始 Standard_Hough(0, 0); Probabilistic_Hough(0, 0); waitKey(0); return 0;}/** * 標準霍夫變換 */void Standard_Hough( int, void* ){ vector<Vec2f> s_lines; cvtColor( edges, standard_hough, CV_GRAY2BGR ); /// 標準霍夫變換 HoughLines( edges, s_lines, 1, CV_PI/180, min_threshold + s_trackbar, 0, 0 ); /// 顯示 for( size_t i = 0; i < s_lines.size(); i++ ) { float r = s_lines[i][0], t = s_lines[i][1]; double cos_t = cos(t), sin_t = sin(t); double x0 = r*cos_t, y0 = r*sin_t; double alpha = 1000; Point pt1( cvRound(x0 + alpha*(-sin_t)), cvRound(y0 + alpha*cos_t) ); Point pt2( cvRound(x0 - alpha*(-sin_t)), cvRound(y0 - alpha*cos_t) ); line( standard_hough, pt1, pt2, Scalar(255,0,0), 3, CV_AA); } imshow( standard_name, standard_hough );}/** * @機率霍夫變換 */void Probabilistic_Hough( int, void* ){ vector<Vec4i> p_lines; cvtColor( edges, probabilistic_hough, CV_GRAY2BGR ); /// 機率霍夫變換 HoughLinesP( edges, p_lines, 1, CV_PI/180, min_threshold + p_trackbar, 30, 10 ); ///顯示 for( size_t i = 0; i < p_lines.size(); i++ ) { Vec4i l = p_lines[i]; line( probabilistic_hough, Point(l[0], l[1]), Point(l[2], l[3]), Scalar(255,0,0), 3, CV_AA); } imshow( probabilistic_name, probabilistic_hough );}運行結果如下:
HoughLines函數的功能使用標準霍夫變換在一張二值映像中檢測直線。函數原型:C++: void HoughLines(InputArray image, OutputArray lines, double rho, double theta, int threshold, double srn=0, double stn=0 )image表示輸入的二值映像,lines為檢測到的線向量,向量每個值用 極座標表示。rho為像素的距離解析度。theta為像素的角度解析度,threshold為累加器閾值
HoughLinesP函數的功能使用機率霍夫變換在一張二值映像中檢測直線。
函數原型為:C++: void HoughLinesP(InputArray image, OutputArray lines, double rho, double theta, int threshold, double minLineLength=0, doublemaxLineGap=0 )參數說明參照HoughLines。
OpenCV2.4.10之samples_cpp_tutorial-code_learn-----ImgTrans(Hough變換)