1. 程式人生 > >利用Opencv中的Houghline方法進行直線檢測---python語言

利用Opencv中的Houghline方法進行直線檢測---python語言

利用Opencv中的Houghline方法進行直線檢測—python語言

這是給Python部落翻譯的文章,請在這裡看原文

在影象處理中,霍夫變換用來檢測任意能夠用數學公式表達的形狀,即使這個形狀被破壞或者有點扭曲。

下面我們將看到利用HoughLine演算法來闡述霍夫變化進行直線檢測的原理,把此演算法應用到特點影象的邊緣檢測是可取的。邊緣檢測方法請參考這篇文章–邊緣檢測

Houghline演算法基礎

直線可以表示為y=mx+c,或者以極座標形式表示為r=xcosθ+ysinθ,其中r是原點到直線的垂直距離,θ是水平軸順時針方向到垂直線的夾角(這個方向取決於座標的形式,在OpenCV就是採用這種極座標形式)。

這裡寫圖片描述

因此任意的曲線都可以用兩個引數(r,θ)表示。

HoughLine演算法原理:

  • 首先建立一個二維的陣列或者累加器(用來儲存這兩個引數),並初始化為零;
  • 這個二維陣列的行代表不同的r,而列代表角度θ
  • 陣列的大小取決於演算法的精度。假設所需角度的精度精確到1,那麼就需要180列(直線的最大角度是180)。
  • 對於r,最大的可能距離是影象的對角長度,因此若需要一個畫素的精度,那麼需要把行數設為影象對角線的長度。

例子:

假設一幅100x100的影象,在影象中間有一條水平直線。設直線的第一個點的座標為(x,y),在直線方程中,令引數θ=0,12,,180,觀查引數r變化。對每一個引數對(r

,θ),在累加器中將(r,θ)對應的單元格中的值遞增1,比如現在在累加器中,某個單元(50,90)的值等於1,其它的值也如此。

對於直線上的第二個點,重複上述操作。將得到的引數對(r,θ)的對應值繼續遞增,然後(50,90)對應的值等於2。實現上我們是對引數對(r,θ)進行投票,對直線上的每一個點重複上述操作,對每一個點,單元格(50,90)對應的值會遞增,或者說投票給引數對(50,90),而會或者不會投票給其它引數對。以這種方式,最後單元格(50,90)的值將會是最大的值。然後搜尋累加器的最大值,將會找到引數對(50,90)。也就是說,在影象中找到了到原點距離為50,角度為90的一條直線。

這裡寫圖片描述

上述演算法的過程被封裝成OpenCV函式cv2.HoughLines()

,函式返回(r,θ)的一個數組,其中r的單位為畫素,θ的單位為弧度。

# Python program to illustrate HoughLine
# method for line detection
import cv2
import numpy as np

# Reading the required image in 
# which operations are to be done. 
# Make sure that the image is in the same 
# directory in which this python program is
img = cv2.imread('xyz.jpg')

# Convert the img to grayscale
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)

# Apply edge detection method on the image
edges = cv2.Canny(gray,50,150,apertureSize = 3)

# This returns an array of r and theta values
lines = cv2.HoughLines(edges,1,np.pi/180, 200)

# The below for loop runs till r and theta values 
# are in the range of the 2d array
for r,theta in lines[0]:

    # Stores the value of cos(theta) in a
    a = np.cos(theta)

    # Stores the value of sin(theta) in b
    b = np.sin(theta)

    # x0 stores the value rcos(theta)
    x0 = a*r

    # y0 stores the value rsin(theta)
    y0 = b*r

    # x1 stores the rounded off value of (rcos(theta)-1000sin(theta))
    x1 = int(x0 + 1000*(-b))

    # y1 stores the rounded off value of (rsin(theta)+1000cos(theta))
    y1 = int(y0 + 1000*(a))

    # x2 stores the rounded off value of (rcos(theta)+1000sin(theta))
    x2 = int(x0 - 1000*(-b))

    # y2 stores the rounded off value of (rsin(theta)-1000cos(theta))
    y2 = int(y0 - 1000*(a))

    # cv2.line draws a line in img from the point(x1,y1) to (x2,y2).
    # (0,0,255) denotes the colour of the line to be 
    #drawn. In this case, it is red. 
    cv2.line(img,(x1,y1), (x2,y2), (0,0,255),2)

# All the changes made in the input image are finally
# written on a new image houghlines.jpg
cv2.imwrite('houghlines3.jpg', img)

函式(cv2.HoughLines(edges, 1, np.pi/180,200))

  1. 第一個引數是輸入影象,且必須是二值影象,在進行霍夫變換之前需要採用閾值方法的邊緣檢測;
  2. 第二和第三個引數分別是r,θ對應的精度;
  3. 第四個引數是閾值,判定為直線投票數的最小值;
  4. 注意,投票數取決於直線上點的個數,因此這個閾值代表了檢測到的直線的最短長度。

這裡寫圖片描述

總結

  • 在影象分析應用中,邊緣分割點的座標(即X,Y)是已知的,在直線的引數方程中作為輸入,而r,θ是我們要找的未知變數;
  • 對每一個角度θ,求出r的值,也就是將笛卡爾影象空間的點對映到霍夫引數極座標空間的曲線,這種點到曲線的變換就是直線的霍夫變換;
  • 這種變換是通過量化霍夫引數為有限的間隔或者累加器單元來實現的,隨著演算法的執行,每一個(X,Y)轉換成離散的(r,θ)曲線,曲線上的點對應的累加器(二維陣列)的值會遞增;
  • 累加器中的峰值就代表了影象中有相應直線的存在。

霍夫變換的應用

  1. 用於分離影象中特殊形狀的特徵;
  2. 可以容忍特徵邊界描述的誤差,並且不受噪聲的干擾;
  3. 廣泛用於條形碼掃描、驗證和識別。

文章作者是Pratima Upadhyay,如果你喜歡GeeksforGeeks,並且願意分享,可以利用contribute.geeksforgeeks.org寫文章,然後傳送到[email protected],在GeeksforGeeks中看到自己的文章,幫助更多的Geeks。

若發現錯誤歡迎指正,也歡迎評論。