hough變換檢測直線和圓


圖像測量和機器視覺作業:

     提取圖像中的直線和點的位置坐標,將其按一定順序編碼存入一文本文件,並在原圖像上疊加顯示出來。

 

下午實驗了一下:


程序環境: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");


}

實驗結果:

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM