用霍夫變換HoughLines檢測直線3

書名:OpenCV計算機視覺編程攻略(第3版)
作者:[加]羅伯特·拉戈尼爾
譯者:相銀初
出版社:人民郵電出版社
出版時間:2018-05
ISBN:9787115480934

一、實現原理

1、累加器

  • 霍夫變換的目的是在二值圖像中找出全部直線,並且這些直線必須穿過足夠多的像素點。
    它的處理方法是,檢查輸入的二值分佈圖中每個獨立的像素點,識別出穿過該像素點的所有可能直線。
    如果同一條直線穿過很多像素點,就說明這條直線明顯到足以被認定。

  • 爲了統計某條直線被標識的次數,霍夫變換使用了一個二維累加器。
    累加器的大小依據(ρ, θ)的步長確定,其中(ρ, θ)參數用來表示一條直線。
    爲了說明霍夫變換的功能,我們建立一個180×200的矩陣(對應θ的步長爲π/180, ρ的步長爲1):

        // 創建霍夫累加器
        // 這裏的圖像類型爲uchar;實際使用時應該用int
        cv::Mat acc(200,180, CV_8U, cv::Scalar(0));
  • 累加器是不同於(ρ, θ)值的映射表。
    因此,矩陣的每個入口都對應一條特定的直線。
    現在假定某個像素點的座標爲(50,30),這樣就能通過循環遍歷所有可能的θ值(步長π/180),並計算對應的(四捨五入)ρ值,標識出穿過這個像素點的全部直線:
        // 選取一個像素點
        int x=50, y=30;
        // 循環遍歷所有角度
        for (int i=0; i<180; i++) {
          double theta= i*PI/180.;
          // 找到對應的rho值
          double rho= x*std::cos(theta)+y*std::sin(theta);
          // j對應-100~100 的rho
          int j= static_cast<int>(rho+100.5);
          std::cout << i << ", " << j << std::endl;
          // 增值累加器
          acc.at<uchar>(j, i)++;
        }
  • 每次計算得到(ρ, θ)對後,其對應的累加器入口的數值就會增加,表示對應的直線穿過了圖像中的某個像素點(或者說每個像素點爲一批候選直線投票)。
    如果把累加器作爲圖像顯示(翻轉過來,並乘以100,以便數字1能顯示),結果如下所示。


  • 上面的曲線表示穿過這個點的所有直線的集合。現在用像素點(30, 10)重複上述過程,得到的累加器如下所示。


  • 可以看到,這兩條曲線在一個位置相交,這個位置表示對應的直線通過了這兩個像素點。累加器的對應入口收到了兩次投票,表明有兩個像素點在這條直線上。

  • 如果對二值分佈圖中的所有像素點重複上述過程,那麼同一條直線上的像素點會使累加器的同一個入口增長很多次。
    最後,爲了檢測圖像中的直線(即像素點對齊的位置),只需要標識出累加器中的局部限值,該累加器用於接收大量投票數。
    cv::HoughLines函數的最後一個參數表示最低投票數,只有不低於這個數的直線纔會被檢測到。這表明最低投票數越小,檢測到的直線數量就越多。

  • 如果把例子中的數值降爲50,檢測到的直線就如下圖所示。


2、概率霍夫變換

  • 概率霍夫變換對基本算法做了一些修正。
    首先,概率霍夫變換在二值分佈圖上隨機選擇像素點,而不是系統性地逐行掃描圖像。一旦累加器的某個入口達到了預設的最小值,就沿着對應的直線掃描圖像,並移除在這條直線上的所有像素點(包括還沒投票的像素點)。
    這個掃描過程還檢測可以接受的線段長度。
    爲此,算法定義了兩個額外的參數:一個是允許的線段最小長度,另一個是組成連續線段時允許的最大像素間距。
    這個額外的步驟增加了算法的複雜度,但也得到了一定的補償——由於在掃描直線的過程中已經清除了部分像素點,因此減少了投票過程中用到的像素點。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章