圖像測量和機器視覺作業:
提取圖像中的直線和點的位置坐標,將其按一定順序編碼存入一文本文件,並在原圖像上疊加顯示出來。
下午實驗了一下:
程序環境:vs2013(活動平台為x64)+opencv3.1 (活動平台也要改)
程序運行時會在程序源文件目錄下生成:
1)textRecord.txt文件,記錄檢測到的直線和圓的信息;
2)hough_trans.bmp文件,為在原圖上標記有檢測到直線和圓的圖像;
3)canny_result.bmp文件,為在邊沿提取的圖上標記提取的直線,還可以調節閾值,觀察效果;
4)HoughTranslation文件夾為程序工程;houghTranslation.cpp文件為源代碼文件。
分析:從檢測結果可以看出:
1)對直線的檢測不是特比理想,在程序中只用到了HoughLinesP函數簡單處理;可能以后需要更好的處理方法。
2)對圓的檢測還比較理想,程序中運用了HoughCircles函數處理,但是需要精細的調整參數,達到理想的效果。
/*! * \file houghTranslation.cpp * * \author ranjiewen * \date 2016/12/25 16:31 * * */ #include <opencv2/opencv.hpp> #include <opencv2/highgui/highgui.hpp> #include <opencv2/imgproc/imgproc.hpp> #include <iostream> #include <fstream> using namespace std; using namespace cv; //全局變量申明 Mat g_srcImage, g_dstImage, g_midImage, circleImage;//原始圖、中間圖和效果圖 vector<Vec4i> g_lines;//定義一個矢量結構g_lines用於存放得到的線段矢量集合 vector<Vec3f> circles; //變量接收的TrackBar位置參數 int g_nthreshold=100; ofstream text; //輸出流寫文件 //函數申明 static void on_HoughLines(int, void*);//回調函數 static void ShowHelpText(); void drawDetectLines(Mat& image, const vector<Vec4i>& lines, Scalar & color); void drawDetectCircles(Mat& image, const vector<Vec3f> &circles, Scalar & color); int main(int agrc,char** argv[]) { //改變console字體顏色 system("color 4F"); ShowHelpText(); //載入原始圖和Mat變量定義 Mat g_srcImage = imread("CAL_GRAY768_Pro.bmp"); //工程目錄下應該有一張名為1.jpg的素材圖 //顯示原始圖 //imshow("【原始圖】", g_srcImage); //創建滾動條 namedWindow("【效果圖】",1); createTrackbar("值", "【效果圖】",&g_nthreshold,200,on_HoughLines); //createTrackbar("值", "【效果圖】", &g_nthreshold, 200, on_HoughCircle); //進行邊緣檢測和轉化為灰度圖 Canny(g_srcImage, g_midImage, 50, 150, 3);//進行一次canny邊緣檢測 //imshow("邊緣圖",g_midImage); cvtColor(g_midImage,g_dstImage, COLOR_GRAY2BGR);//轉化邊緣檢測后的圖為灰度圖 //調用一次回調函數,調用一次HoughLinesP函數 on_HoughLines(g_nthreshold,0); HoughLinesP(g_midImage, g_lines, 1, CV_PI/180, 80, 50, 10 ); cvtColor(g_srcImage, circleImage, COLOR_BGR2GRAY); GaussianBlur(circleImage, circleImage, Size(9, 9), 2, 2); //數的調整是關鍵,一定要知道各參數的調整才能調出合適的參數,感覺最小投票數對結果影響較大 HoughCircles(circleImage, circles, HOUGH_GRADIENT, 1, 5, 100, 25, 0, 50); text.open("textRecord.txt",ios::out); drawDetectLines(g_srcImage, g_lines, Scalar(0, 255, 0)); drawDetectCircles(g_srcImage, circles, Scalar(0, 255, 0)); text.close(); //顯示效果圖 imshow("【效果圖】", g_dstImage); imshow("效果圖", g_srcImage); imwrite("canny_result.bmp", g_dstImage); //保存圖 imwrite("hough_trans.bmp", g_srcImage); //保存圖 waitKey(0); return 0; } void drawDetectLines(Mat& image, const vector<Vec4i>& lines, Scalar & color) { text << "檢測到的直線總數:" << lines.size() <<"兩個坐標為一組。"<< endl; // 將檢測到的直線在圖上畫出來 vector<Vec4i>::const_iterator it = lines.begin(); while (it != lines.end()) { Point pt1((*it)[0], (*it)[1]); Point pt2((*it)[2], (*it)[3]); line(image, pt1, pt2, color, 2); // 線條寬度設置為2 ++it; } for (int i = 0; i < lines.size(); i++) { char str[_MAX_PATH]; sprintf_s(str, _MAX_PATH, "第%d條直線兩個端點坐標:", i + 1); text << str << " (" << (lines.at(i)) << ")" << endl; } text << endl; } void drawDetectCircles(Mat& image, const vector<Vec3f> &circles, Scalar & color) { text << "檢測到的圓的總數:" << circles.size() << endl; 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]); char str[_MAX_PATH]; sprintf_s(str, _MAX_PATH, "第%d個圓心坐標: ", i + 1); text << str << " (" << circles[i][0] << "," << circles[i][1] << ") " << "圓的半徑:" << radius << endl; //繪制圓心 circle(image, center, 3, Scalar(0, 255, 0), -1, 8, 0); //繪制圓輪廓 circle(image, center, radius, Scalar(155, 50, 255), 3, 8, 0); } } static void on_HoughCircle(int ,void*) { GaussianBlur(g_midImage, g_midImage, Size(9, 9), 2, 2); //【4】進行霍夫圓變換 vector<Vec3f> circles; HoughCircles(g_midImage, circles, HOUGH_GRADIENT, 1.5, 10, 200, 100, 0, 0); //【5】依次在圖中繪制出圓 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(g_srcImage, center, 3, Scalar(0, 255, 0), -1, 8, 0); //繪制圓輪廓 circle(g_srcImage, center, radius, Scalar(155, 50, 255), 3, 8, 0); } } //---【on_HoughLines( )函數】------------------- // 描述:【頂帽運算/黑帽運算】窗口的回調函數 //---------------------------------------------- static void on_HoughLines(int, void*) { //定義局部變量儲存全局變量 Mat dstImage=g_dstImage.clone(); Mat midImage=g_midImage.clone(); //調用HoughLinesP函數 vector<Vec4i> mylines; HoughLinesP(midImage, mylines, 1, CV_PI/180, g_nthreshold+1, 50, 10 ); //循環遍歷繪制每一條線段 for( size_t i = 0; i < mylines.size(); i++ ) { Vec4i l = mylines[i]; line( dstImage, Point(l[0], l[1]), Point(l[2], l[3]), Scalar(23,180,55), 1, LINE_AA); } //顯示圖像 imshow("【效果圖】",dstImage); } static void ShowHelpText() { //輸出歡迎信息和OpenCV版本 printf("\n\n\t\t\t 當前使用的OpenCV版本為:" CV_VERSION ); printf("\n\n ----------------------------------------------------------------------------\n"); //輸出一些幫助信息 printf("\n\n\n\t請調整滾動條觀察圖像效果~\n\n"); }
實驗結果: