當前位置: 妍妍網 > 碼農

OpenCV 筆記(19):霍夫直線檢測

2024-01-29碼農

1. 霍夫空間和霍夫變換

1.1 霍夫空間

霍夫空間 (Hough space)是一種用於影像分析的 特征空間 ,用於描述影像中具有相同形狀的線段或曲線。

霍夫空間是指將影像空間中的點對映到 參數空間 後形成的空間。參數空間的維度由形狀的描述參數的個數決定。例如,對於直線檢測,參數空間的維度為 2,其中一個維度表示直線的斜率,另一個維度表示直線的截距。對於圓檢測,參數空間的維度為 3,這三個參數分別是圓心座標和圓的半徑。

霍夫空間具有以下特性:

  • 霍夫空間的維度等於直線或曲線的特征參數的個數。

  • 霍夫空間中的每個點都對應於影像空間中的一條特征線。

  • 霍夫空間中的點的值表示該特征線在影像空間中的出現頻率。

  • 1.2 霍夫變換

    霍夫變換 (Hough transform)是一種基於 霍夫空間 的影像特征提取演算法。它可以用於檢測影像中的直線、圓形、橢圓等形狀。

    霍夫變換具有以下優點:

  • 速度快,適合處理大尺寸的影像。

  • 可以檢測任意形狀的影像。

  • 霍夫變換也具有以下缺點:

  • 對影像雜訊敏感。

  • 容易受到幹擾。

  • 霍夫變換的步驟:

  • 對影像進行預處理,提取邊緣點。

  • 將邊緣點對映到霍夫空間中。

  • 在霍夫空間中計算累加函式。

  • 根據累加函式的值來檢測影像中的形狀。

  • 2. 霍夫直線檢測

    2.1 直線檢測的霍夫空間

    在影像空間中,直線可以用 y = mx+b 表示,其中 m 是直線的斜率,b 是直線的截距。

    在參數空間中,直線可以用 (m,b) 表示,其中 m 是直線的斜率,b 是直線的截距。

    影像空間中的每條直線在參數空間中都對應著單獨 一個點 來表示。影像空間中的直線上任何一部份線段在參數空間對應的是 同一個點

    將影像空間中的直線對映到參數空間中的點,其中 θ 是直線的傾斜角,r 是直線與原點的距離。

    影像空間中的點.PNG

    r 所在的直線跟直線 y = mx + b 的交點可得

    由於

    所以,

    這樣,影像空間**(直角座標系x-y)**的一個點在參數空間( 極座標系𝜌-𝜃 )中就對應為一條曲線。

    其中:(x,y) 表示線上點的座標,𝜌 表示線距原點的距離,𝜃 表示線與 x 軸的方向。

    影像空間對映到參數空間.png

    影像空間的一個點在參數空間中就對應為一條曲線 ρ = xcos(θ) + ysin(θ),而參數空間的每個點 (θ, ρ) 都對應了影像空間的一條直線。

    霍夫變換預設使用極座標系來檢測影像中的線,因為笛卡爾座標系中線的斜率範圍無限大,導致計算量較高。

    2.2 投票機制

    在霍夫直線檢測中,有一個重要的投票機制,它的過程如下:

  • 邊緣檢測:使用邊緣檢測演算法辨識影像中的邊緣像素。

  • 參數空間對映:每個邊緣點為其可能所屬的參數空間(霍夫空間)中的每條潛線上「投票」。投票的位置取決於線的角度 (θ) 和距原點的距離 (ρ)。

  • 累加器陣列:在霍夫空間中,每當邊緣像素符合該線參數化時,對應於特定 (θ, ρ) 組合的每個單元都會收到投票。投票被累加在累加器陣列中。

  • 峰值檢測:叠代所有邊緣像素後,分析累加器陣列以尋找具有最高投票計數(峰值)的單元格。這些峰值代表由最多數量的邊緣點支持的線,並且被認為是影像中最可能出現的線。

  • 線參數提取:最後利用峰值的(θ,ρ)值重建原始影像空間中的直線方程式,提供最終檢測到的線。

  • 投票機制好處在於:

  • 對雜訊和部份遮擋的魯棒性

  • 能夠同時檢測多條直線

  • 基於邊緣高效辨識直線

  • 總體而言,投票機制是霍夫直線檢測的核心優勢,使其能夠有效地從雜訊和復雜影像中辨識直線。

    2.3 例子

    下面的例子,透過 Canny 尋找提取影像的邊緣,然後對映到霍夫空間進行直線檢測,最後繪制找到的直線。

    #include"opencv2/imgproc.hpp"
    #include"opencv2/highgui.hpp"
    usingnamespacestd;
    usingnamespace cv;
    intmain(int argc, char **argv){
    Mat src = imread(".../country_road.jpg");
    imshow("src", src);
    Mat gray;
    cvtColor(src, gray, cv::COLOR_BGR2GRAY);
    GaussianBlur(gray,gray,Size(7,7),0);
    Mat edge;
    Canny(gray,edge,100,300,3);
    imshow("edge", edge);
    std::vector<Vec4f> lines;
    cv::HoughLinesP(edge, lines, 1, CV_PI / 180.080505);
    cv::Scalar color = cv::Scalar(00255);
    for(size_t i = 0; i < lines.size(); i++){
    line(src, cv::Point(lines[i][0], lines[i][1]), cv::Point(lines[i][2], lines[i][3]), color, 8, cv::LINE_AA);
    }
    imshow("result", src);
    waitKey(0);
    return0;
    }





    公路的原圖.png

    透過canny提取公路的邊緣.png

    標記公路中的直線.png

    HoughLinesP() 函式是基於**累積機率霍夫變換(PPHT)**的一種實作。PPHT 演算法比標準霍夫變換演算法更準確,但也更耗時。

    voidHoughLinesP( InputArray image, OutputArray lines,
    double rho, double theta, int threshold,
    double minLineLength = 0double maxLineGap = 0 )
    ;

    第一個參數 image:輸入影像,必須是單鍊結的灰度影像或二值影像。

    第二個參數 lines:輸出陣列,其中儲存檢測到的直線。每個直線由四個元素的向量表示,分別為直線的起點 (x1, y1)、終點 (x2, y2)。

    第三個參數 rho:參數空間中 ρ 的範圍。

    第四個參數 theta:參數空間中 θ 的範圍。

    第五個參數 threshold:累加器中用於判定線段是否有效的閾值。

    第六個參數 minLineLength:線段的最小長度。

    第七個參數 maxLineGap:線段之間的最大間隔。

    HoughLinesP() 函式對雜訊敏感,因此在使用前應對影像進行降噪處理。

    下面的例子,同樣是基於 Canny 尋找影像的邊緣,然後進行直線檢測。

    #include"opencv2/imgproc.hpp"
    #include"opencv2/highgui.hpp"
    usingnamespacestd;
    usingnamespace cv;
    intmain(int argc, char **argv){
    Mat src = imread(".../paper.jpg");
    imshow("src", src);
    Mat gray;
    cvtColor(src, gray, cv::COLOR_BGR2GRAY);
    Mat edge;
    Canny(gray,edge,40,80,3);
    imshow("edge", edge);
    std::vector<Vec4f> lines;
    cv::HoughLinesP(edge, lines, 1, CV_PI / 180.02010030);
    cv::Scalar color = cv::Scalar(00255);
    for(size_t i = 0; i < lines.size(); i++){
    line(src, cv::Point(lines[i][0], lines[i][1]), cv::Point(lines[i][2], lines[i][3]), color, 8, cv::LINE_AA);
    }
    imshow("result", src);
    waitKey(0);
    return0;
    }




    paper原圖.png

    標記paper中的直線.png

    HoughLinesP() 函式在使用時,需要註意的是:

  • threshold:投票閾值,閾值越高,檢測到的直線越少。

  • minLineLength:直線的最小長度,小於此值的直線將被拒絕。minLineLength 越大,檢測到的直線越長。

  • maxLineGap:最大允許的直線間距,以使它們被視為單一線段。maxLineGap 越大,檢測到的直線越可能被視為單一線段。

  • 3. 總結

    霍夫直線檢測是影像處理中用於檢測影像中直線的一種常用方法。可以檢測出影像中任意方向的直線,包括水平直線、垂直直線以及斜直線。也可以檢測出影像中多條直線,即使這些直線重疊或被遮擋。它是一種簡單而有效的影像處理方法,在許多套用中得到了廣泛的套用。

    掃碼學習YOLOv8視訊課程

    推薦閱讀