天天看點

hough變換檢測圓周_hough變換原理以及實作(轉載)

原理連結如下:陌歸:霍夫(Hough)變換之直線檢測

代碼連結:Ganso:Fundamentals——從車道線檢測談到霍夫變換

同樣是一篇講解原理的番外,這一篇主要講解CV中常用的霍夫變換的數學原理。

霍夫變換的由來

“霍夫變換于1962年由Paul Hough首次提出,最初的Hough變換是設計用來檢測直線和曲線,起初的方法要求知道物體邊界線的解析方程,但不需要有關區域位置的先驗知識。後于1972年由Richard Duda & Peter Hart推廣使用。”

其實,霍夫變換的中心思想就是通過坐标變換來檢測直線,後來經過改進,就可以檢測橢圓等。

霍夫線變換

坐标系的角度:

說起直線,我們會想到笛卡爾坐标系(即x-y坐标系)下的直線方程,細分之則有點斜式、截距式等,

hough變換檢測圓周_hough變換原理以及實作(轉載)

是我們最熟悉的一種。但直線垂直于x軸時斜率

hough變換檢測圓周_hough變換原理以及實作(轉載)

不存在,這給我們帶來許多不便之處。

這時極坐标就carry全場了,它與笛卡爾坐标系的轉換關系:

hough變換檢測圓周_hough變換原理以及實作(轉載)

,變形可得

hough變換檢測圓周_hough變換原理以及實作(轉載)

hough變換檢測圓周_hough變換原理以及實作(轉載)

為原點到直線的距離,也常用

hough變換檢測圓周_hough變換原理以及實作(轉載)

表示,示意圖如下:

hough變換檢測圓周_hough變換原理以及實作(轉載)

由此極坐标下,直線可用

hough變換檢測圓周_hough變換原理以及實作(轉載)

表示。這就啟發我們,同一直線上的點具有相同的

hough變換檢測圓周_hough變換原理以及實作(轉載)

hough變換檢測圓周_hough變換原理以及實作(轉載)

x-y坐标系下的一個點在rho-theta坐标系下為正弦曲線

hough變換檢測圓周_hough變換原理以及實作(轉載)

同一直線上的點會有相同的rho和theta,即在rho-theta下交于一點

統計學的角度:
内容出自:Opencv學習筆記-----霍夫變換直線檢測及原理了解 - CSDN部落格
hough變換檢測圓周_hough變換原理以及實作(轉載)

如上圖,假定在一個8*8的平面像素中有一條直線,并且從左上角

hough變換檢測圓周_hough變換原理以及實作(轉載)

像素點開始分别計算

hough變換檢測圓周_hough變換原理以及實作(轉載)

為0°、45°、90°、135°、180°時的

hough變換檢測圓周_hough變換原理以及實作(轉載)

,圖中可以看出

hough變換檢測圓周_hough變換原理以及實作(轉載)

分别為

hough變換檢測圓周_hough變換原理以及實作(轉載)

,并給這5個值分别記一票,同理計算像素點

hough變換檢測圓周_hough變換原理以及實作(轉載)

hough變換檢測圓周_hough變換原理以及實作(轉載)

為0°、45°、90°、135°、180°時的

hough變換檢測圓周_hough變換原理以及實作(轉載)

,再給計算出來的5個

hough變換檢測圓周_hough變換原理以及實作(轉載)

值分别記一票,此時就會發現

hough變換檢測圓周_hough變換原理以及實作(轉載)

的這個值已經記了兩票了,以此類推,周遊完整個8*8的像素空間的時候

hough變換檢測圓周_hough變換原理以及實作(轉載)

就記了5票, 别的

hough變換檢測圓周_hough變換原理以及實作(轉載)

值的票數均小于5票,是以得到該直線在這個8*8的像素坐标中的極坐标方程為

hough變換檢測圓周_hough變換原理以及實作(轉載)

,到此該直線方程就求出來了。

霍夫圓變換

霍夫圓變換使用的算法叫霍夫梯度法,對應的函數為HoughCircles,這個函數實際上是對正常找圓算法的一種改進,這裡不展開講,想學習這個原理的同學請參考找圓算法((HoughCircles)總結與優化 - CSDN部落格

1. base

導入必要的包,順便寫一個列印圖像的函數,cv2與plt顔色通道不一緻(是以為什麼不用plt導入呢)。

import numpy as np
import matplotlib.pyplot as plt
import cv2

# opencv的顔色通道順序為[B,G,R],而matplotlib的顔色通道順序為[R,G,B]。
def plotImg(img):
    if len(img.shape)==3:
        img = img[:,:,(2,1,0)]
        plt.imshow(img)
    else:
        plt.imshow(img, cmap='gray')
    plt.show()
           

導入圖檔,感覺如果幹擾很多效果也不會太好。

image = cv2.imread('test_image.jpg')
plotImg(image)
           
hough變換檢測圓周_hough變換原理以及實作(轉載)
canny

灰階,模糊,canny三連擊。

canny輸入需求如此。

def canny(image):
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    blur = cv2.GaussianBlur(gray,(5,5),0)
    canny = cv2.Canny(blur, 50, 150)
    return canny

lane_image = np.copy(image)
canny = canny(lane_image)
plotImg(canny)
           
hough變換檢測圓周_hough變換原理以及實作(轉載)
region_of_interest

手工特征區域?作者的思路也是蠻清奇的。

簡單來說就是對于視角前面的三角形區域做了一個mask,全部填充255,與原圖像bitwise。

def region_of_interest(image):
    height = image.shape[0]
    polygons = np.array([
        [(200,height), (1100,height), (550,250)]
    ])
    mask = np.zeros_like(image)
    cv2.fillPoly(mask, polygons, 255)
    masked_image= cv2.bitwise_and(image,mask)
    return masked_image

cropped_image = region_of_interest(canny)
plotImg(cropped_image)
           
hough變換檢測圓周_hough變換原理以及實作(轉載)
hough變換檢測圓周_hough變換原理以及實作(轉載)

2. Hough Transform

将圖像提取邊緣之後獲得了很多雜亂的點,而我們需要做的就是找到過這些點的公共直線。

點斜式方程

點斜式方程是

hough變換檢測圓周_hough變換原理以及實作(轉載)

,那麼對于經過下圖黑色點的直線簇,我們可以将其映射到一個以m,b位坐标的空間,b是m的線性函數。對于不同的兩個點,我們可以将其直線簇映射到mb空間的兩個直線上,而mb空間兩個直線的交點(m,b)就是這兩個點公共直線的參數。但是這樣還是存在問題的,當直線是垂直的時候,m趨向于無窮,不好表示,我們需要另外一種映射。

hough變換檢測圓周_hough變換原理以及實作(轉載)
極坐标方程

在極坐标空間中,對于過固定點的直線,過原點做垂線,記距離為

hough變換檢測圓周_hough變換原理以及實作(轉載)

,夾角為

hough變換檢測圓周_hough變換原理以及實作(轉載)

,通過圖示我們可以得到對于過一點x,y的直線簇有:

hough變換檢測圓周_hough變換原理以及實作(轉載)
hough變換檢測圓周_hough變換原理以及實作(轉載)

也就是說過固定點的直線簇

hough變換檢測圓周_hough變換原理以及實作(轉載)

hough變換檢測圓周_hough變換原理以及實作(轉載)

之間有一定的函數關系。

霍夫變換

我們将過每個點的直線簇映射到極坐标空間,基本都由一條曲線表示,比如圖示的三個點,這樣。曲線的交點對應的坐标就是過所有點的直線的極坐标參數。

hough變換檢測圓周_hough變換原理以及實作(轉載)
投票機制

當圖檔上的點非常多時,所有曲線并不期望相交于一點。我們可以将霍夫空間劃分為一個個patch,當一個patch上面的交點滿足大于某個threshold時,我們視為這些點有它們的公共直線。

hough變換檢測圓周_hough變換原理以及實作(轉載)

3. cv2實作

cv.2HoughLinesP(image, rho, theta, threshold[, lines[, minLineLength[, maxLineGap]]])

參數

image 圖像。

rho、theta:分辨率。(分别率就是指同一個角度,如果計算出兩點的rio值小于2,則認為是同一直線。)

threshold:投票門檻值。

lines:沒有查到。

minLineLength:最小線條長度。

maxLineGap:最大線條間隔。

def display_lines(image,lines):
    line_image = np.zeros_like(image)
    if lines is not None:
        for line in lines:
            x1, y1, x2, y2 = line.reshape(4)
            cv2.line(line_image, (x1,y1), (x2,y2),(255,0,0),10)
    return line_image
            
lines = cv2.HoughLinesP(cropped_image, 2, np.pi/180, 100, np.array([133,2]), minLineLength=40, maxLineGap=5)
line_image = display_lines(image,lines)
plotImg(line_image)

combo_image = cv2.addWeighted(lane_image,0.8, line_image,1,1)
plotImg(combo_image)
           

霍夫變換求直線

hough變換檢測圓周_hough變換原理以及實作(轉載)
hough變換檢測圓周_hough變換原理以及實作(轉載)