【翻譯:OpenCV-Python教程】霍夫線性變換

⚠️由於自己的拖延症,3.4.3翻到一半,OpenCV發佈了4.0.0了正式版,所以接下來是按照4.0.0翻譯的。

⚠️除了版本之外,其他還是照舊,Hough Line Transform,原文

目標

在本章,

  • 我們將會理解霍夫變換的概念。
  • 我們將看到如何使用它來檢測圖像中的線條。
  • 我們將看到以下函數:cv.HoughLines()cv.HoughLinesP()

理論

霍夫變換是一種可以檢測任何形狀的流行技術,如果你能用數學形式來表示這種形狀的話。它可以檢測形狀,即使形狀被破壞破或扭曲了一點。我們來看看它是如何作用於直線的。

一條直線可以被表示成 y=mx+c 或者是參量形式 ρ=xcosθ+ysinθ 其中 ρ 是從原點到直線的垂直距離,θ 是這條垂線與水平軸逆時針方向構成的角度(這個方向取決於你如何定義座標系。現在提到的這種表示方案是在OpenCV中使用的方案)。看下面的示意圖:

所以如果這條線經過原點以下,它會有一個小於180度的正角度。如果它在原點上方,我們不是取一個大於180的角,而是取一個小於180的負角度。任何垂直線都是0度,水平線是90度。

現在我們來看看霍夫變換是怎麼作用於直線的。任何線都可以被表示成這兩項,(ρ,θ)。所以首先他創建了一個二維數組,或者是累加器(來保存着兩個參數的值)然後他設置0作爲初始值。 and it is set to 0 initially. Let rows denote the ρ and columns denote the θ. Size of array depends on the accuracy you need. Suppose you want the accuracy of angles to be 1 degree, you will need 180 columns. For ρ, the maximum distance possible is the diagonal length of the image. So taking one pixel accuracy, the number of rows can be the diagonal length of the image.

Consider a 100x100 image with a horizontal line at the middle. Take the first point of the line. You know its (x,y) values. Now in the line equation, put the values θ=0,1,2,....,180 and check the ρ you get. For every (ρ,θ) pair, you increment value by one in our accumulator in its corresponding (ρ,θ) cells. So now in accumulator, the cell (50,90) = 1 along with some other cells.

Now take the second point on the line. Do the same as above. Increment the values in the cells corresponding to (rho, theta) you got. This time, the cell (50,90) = 2. What you actually do is voting the (ρ,θ) values. You continue this process for every point on the line. At each point, the cell (50,90) will be incremented or voted up, while other cells may or may not be voted up. This way, at the end, the cell (50,90) will have maximum votes. So if you search the accumulator for maximum votes, you get the value (50,90) which says, there is a line in this image at a distance 50 from the origin and at angle 90 degrees. It is well shown in the below animation (Image Courtesy: Amos Storkey )

houghlinesdemo.gif

This is how hough transform works for lines. It is simple, and may be you can implement it using Numpy on your own. Below is an image which shows the accumulator. Bright spots at some locations denote they are the parameters of possible lines in the image. (Image courtesy: Wikipedia )

houghlines2.jpg

Hough Transform in OpenCV

Everything explained above is encapsulated in the OpenCV function, cv.HoughLines(). It simply returns an array of :math:(rho, theta)` values. ρ is measured in pixels and θ is measured in radians. First parameter, Input image should be a binary image, so apply threshold or use canny edge detection before applying hough transform. Second and third parameters are ρ and θ accuracies respectively. Fourth argument is the threshold, which means the minimum vote it should get to be considered as a line. Remember, number of votes depends upon the number of points on the line. So it represents the minimum length of line that should be detected.

import cv2 as cv

import numpy as np

img = cv.imread(cv.samples.findFile('sudoku.png'))

gray = cv.cvtColor(img,cv.COLOR_BGR2GRAY)

edges = cv.Canny(gray,50,150,apertureSize = 3)

lines = cv.HoughLines(edges,1,np.pi/180,200)

for line in lines:

rho,theta = line[0]

a = np.cos(theta)

b = np.sin(theta)

x0 = a*rho

y0 = b*rho

x1 = int(x0 + 1000*(-b))

y1 = int(y0 + 1000*(a))

x2 = int(x0 - 1000*(-b))

y2 = int(y0 - 1000*(a))

cv.line(img,(x1,y1),(x2,y2),(0,0,255),2)

cv.imwrite('houghlines3.jpg',img)

Check the results below:

houghlines3.jpg

image

Probabilistic Hough Transform

In the hough transform, you can see that even for a line with two arguments, it takes a lot of computation. Probabilistic Hough Transform is an optimization of the Hough Transform we saw. It doesn't take all the points into consideration. Instead, it takes only a random subset of points which is sufficient for line detection. Just we have to decrease the threshold. See image below which compares Hough Transform and Probabilistic Hough Transform in Hough space. (Image Courtesy : Franck Bettinger's home page )

houghlines4.png

image

OpenCV implementation is based on Robust Detection of Lines Using the Progressive Probabilistic Hough Transform by Matas, J. and Galambos, C. and Kittler, J.V. [133]. The function used is cv.HoughLinesP(). It has two new arguments.

  • minLineLength - Minimum length of line. Line segments shorter than this are rejected.
  • maxLineGap - Maximum allowed gap between line segments to treat them as a single line.

Best thing is that, it directly returns the two endpoints of lines. In previous case, you got only the parameters of lines, and you had to find all the points. Here, everything is direct and simple.

import cv2 as cv

import numpy as np

img = cv.imread(cv.samples.findFile('sudoku.png'))

gray = cv.cvtColor(img,cv.COLOR_BGR2GRAY)

edges = cv.Canny(gray,50,150,apertureSize = 3)

lines = cv.HoughLinesP(edges,1,np.pi/180,100,minLineLength=100,maxLineGap=10)

for line in lines:

x1,y1,x2,y2 = line[0]

cv.line(img,(x1,y1),(x2,y2),(0,255,0),2)

cv.imwrite('houghlines5.jpg',img)

See the results below:

houghlines5.jpg

image

Additional Resources

  1. Hough Transform on Wikipedia

Exercises


上篇:【翻譯:OpenCV-Python教程】模板匹配

下篇:【翻譯:OpenCV-Python教程】圖像金字塔

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章