iT邦幫忙

2026 iThome 鐵人賽

DAY 28
0
Software Development

從像素到 Computer Vision:30 天理解數位影像處理系列 第 28

Day 28 | Hough Transform:電腦怎麼從一張圖片中找出直線?

  • 分享至 

  • xImage
  •  

上一篇介紹了 SIFT 和 ORB。

它們可以找到圖片中的特徵點,並建立 Descriptor,方便不同圖片之間進行匹配。

不過有時候我們想找的不是特徵點。

例如道路的車道線、桌子的邊緣、建築物的牆壁,甚至是交通標誌的圓形。

這些都是具有規律幾何形狀的物體。

那電腦要怎麼從一張圖片中,把這些直線或圓形找出來?

今天要介紹的,就是 Hough Transform(霍夫轉換)

為什麼不能直接找直線?

既然圖片裡已經有 Edge,那是不是沿著 Edge 一路找下去就能知道哪裡是一條直線?

欸?我們來仔細思考一下。

一條直線可能會因為光線、遮擋或雜訊而中斷,有些地方甚至只剩下一小段。

如果只是沿著邊緣往前找,很容易就判斷失敗。

所以,Hough Transform 換了一種思考方式。

它在找之前會先問一個問題:哪些 Edge,有可能屬於同一條直線?

Hough Transform 在做什麼?

假設圖片中有很多 Edge Pixel。

每一個 Pixel 都可能屬於很多不同的直線。

Hough Transform 會讓每一個 Edge Pixel 都去「投票」。

如果很多 Pixel 都投給同一條直線。

那就代表,這條直線很有可能真的存在。

所以可以想成,Hough Transform 是透過投票,找出最有可能存在的幾何形狀。

為什麼需要另一種表示方式?

如果用大家熟悉的直線方程式,一條直線可以寫成:


y = mx + b

不過,這個表示方法有一個問題:

如果今天遇到垂直線,斜率就會變成無限大。

因此 Hough Transform 使用了另一種表示方法:


ρ = xcosθ + ysinθ

其中:

  • ρ(rho) 表示直線到原點的距離。
  • θ(theta) 表示直線的角度。

利用這種表示方式,任何方向的直線都可以用同樣的方法表示。

投票是怎麼進行的?

假設現在有一個 Edge Pixel。

它不知道自己屬於哪一條直線。

那就可以把所有可能的角度都試一次。

每試一個角度,就能算出一個對應的 ρ。

也就是說,一個 Pixel 其實可以對應到很多組 (ρ, θ)。

當圖片中很多 Pixel 最後都得到相同的 (ρ, θ)。

就表示,它們很可能都位於同一條直線上。

這組 (ρ, θ) 就會累積很多票數。

最後,票數最高的位置就是偵測到的直線。

實作:使用 Hough Line Transform

在 OpenCV 中可以直接使用 cv2.HoughLinesP()

它會回傳偵測到的線段。

今天,我們不用前面用的狗狗照片,改成使用道路圖片,方便大家觀察。

import cv2
import math
import matplotlib.pyplot as plt

img = cv2.imread("road.jpeg")

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

edges = cv2.Canny(gray, 100, 200)

lines = cv2.HoughLinesP(
    edges,
    rho=1,
    theta=math.pi / 180,
    threshold=80,
    minLineLength=50,
    maxLineGap=10
)

result = img.copy()

if lines is not None:
    for line in lines:
        x1, y1, x2, y2 = line[0]
        cv2.line(result, (x1, y1), (x2, y2), (0, 0, 255), 2)

接著把結果畫出來。

plt.figure(figsize=(10,4))

plt.subplot(1,2,1)
plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
plt.title("Original")
plt.axis("off")

plt.subplot(1,2,2)
plt.imshow(cv2.cvtColor(result, cv2.COLOR_BGR2RGB))
plt.title("Hough Lines")
plt.axis("off")

plt.tight_layout()
plt.show()

結果如下:

https://ithelp.ithome.com.tw/upload/images/20260914/20181780akeqefjjnG.png

可以看到,原本只有一張普通的道路圖片。

經過 Canny 找到邊緣之後,再利用 Hough Transform,就能把車道線邊界偵測出來。

再仔細觀察,可以看到,同一條道路可能會被偵測成多個線段。這是因為 HoughLinesP() 回傳的是線段,而不是一條無限延伸的直線,因此實際應用中通常還會再進行線段合併或篩選。

Hough Transform 可以找圓嗎?

答案是,可以。

Hough Transform 並不只能找直線。

只要知道某種幾何圖形的數學表示方式,就有機會利用類似的方法進行投票。

例如 OpenCV 就提供了:

cv2.HoughCircles(...)

可以用來偵測圖片中的圓形。

像是硬幣、瓶蓋、交通標誌,甚至是人的瞳孔都是常見的應用。

今天總結

今天介紹了 Hough Transform。

它和前面介紹過的方法很不一樣。

它透過「投票」的概念,把屬於同一個幾何形狀的 Edge 聚集起來,進而找出圖片中的直線或圓形。

到這邊為止,我們已經介紹了許多的數位影像處理方法。

從最基本的 Pixel、Histogram、Convolution,到 Edge、Corner、Feature,再到今天的 Hough Transform,它們至今仍然是許多電腦視覺演算法的重要基礎。

下一篇,我們將一起回顧學過的內容,並討論傳統影像處理與深度學習之間的關係,看看它們在現代的電腦視覺技術中,各自扮演著什麼樣的角色。


上一篇
Day 27 | SIFT / ORB:電腦怎麼知道兩張照片拍的是同一個地方?
下一篇
Day 29 | 傳統影像處理與深度學習的分工
系列文
從像素到 Computer Vision:30 天理解數位影像處理30
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言