Hough變換思想(參數空間變換):
在原始圖像座標系下的一個點對應了參數座標系中的一條直線,同樣參數座標系的一條直線對應了原始座標系下的一個點,然後,原始座標系下呈現直線的所有點,它們的斜率和截距是相同的,所以它們在參數座標系下對應於同一個點。這樣在將原始座標系下的各個點投影到參數座標系下之後,看參數座標系下有沒有聚集點,這樣的聚集點就對應了原始座標系下的直線。
在實際應用中,y=kx+b形式的直線方程沒有辦法表示x=c形式的直線(這時候,直線的斜率爲無窮大)。所以實際應用中,是採用參數方程p=xcos(theta)+y*sin(theta)。這樣,圖像平面上的一個點就對應到參數p—theta平面上的一條曲線上,其它的還是一樣。
Hough變換思想(參數空間劃分網格統計):
爲了檢測出直角座標X-Y中由點所構成的直線,可以將極座標a-p量化成許多小格。根據直角座標中每個點的座標(x,y),在a = 0-180°內以小格的步長計算各個p值,所得值落在某個小格內,便使該小格的累加記數器加1。當直角座標中全部的點都變換後,對小格進行檢驗,計數值最大的小格,其(a,p)值對應於直角座標中所求直線。
Hough變換的程序實現:
import cv2
import numpy as np
#hough變換的程序實現
img = cv2.imread("building.jpg")#讀取圖片
img2 = img.copy()
gray =cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)#將圖片轉換爲灰度圖
edges = cv2.Canny(gray,50,150,apertureSize = 3)#canny算法提取輪廓
#基於概率的hough變換......................................................
lines_Probabilitys = cv2.HoughLinesP(edges,1,np.pi/180,30,minLineLength=100,maxLineGap=10)#概率hough變換
lines_Probability = lines_Probabilitys[:,0,:]#提取爲二維
for x1,y1,x2,y2 in lines_Probability[:]:
cv2.line(img,(x1,y1),(x2,y2),(255,0,0),1)
cv2.namedWindow("HoughLines_Probabilitys", 2) #創建一個窗口
cv2.imshow('HoughLines_Probabilitys', img) #顯示原始圖片
#標準的hough變換......................................................
lines_standards = cv2.HoughLines(edges,1,np.pi/180,200) #標準hough變換查找直線
#繪製hough變換後找到的所有直線,返回數據是一個二位數組
for lines_standard in lines_standards:
for rho,theta in lines_standard:
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))
cv2.line(img2,(x1,y1),(x2,y2),(0,0,255),2)
print(lines_standards)#打印出找到的直線的極座標系座標、
cv2.namedWindow("HoughLines_standards", 2) #創建一個窗口
cv2.imshow('HoughLines_standards', img2) #顯示原始圖片
cv2.waitKey()
函數參數解釋:
HoughLinesP(image, rho, theta, threshold, lines=None, minLineLength=None, maxLineGap=None)
- image: 必須是二值圖像,推薦使用canny邊緣檢測的結果圖像;
- rho: 線段以像素爲單位的距離精度,double類型的,推薦用1.0
- theta: 線段以弧度爲單位的角度精度,推薦用numpy.pi/180
- threshod: 累加平面的閾值參數,int類型,超過設定閾值才被檢測出線段,值越大,基本上意味着檢出的線段越長,檢出的線段個數越少。根據情況推薦先用100試試
- lines:這個參數的意義未知,發現不同的lines對結果沒影響,但是不要忽略了它的存在
- minLineLength:線段以像素爲單位的最小長度,根據應用場景設置
- maxLineGap:同一方向上兩條線段判定爲一條線段的最大允許間隔(斷裂),超過了設定值,則把兩條線段當成一條線段,值越大,允許線段上的斷裂越大,越有可能檢出潛在的直線段
cvHoughLines2( CvArr* image, void* line_storage, int method,double rho, double theta, int threshold,double param1=0, double param2=0 );
- image輸入 8-比特、單通道 (二值) 圖像,其內容可能被函數所改變
- line_storage檢測到的線段存儲.
- method
CV_HOUGH_STANDARD - 傳統或標準 Hough 變換. 每一個線段由兩個浮點數 (ρ, θ)表示,其中 ρ 是點與原點 (0,0) 之間的距離, θ 線段與 x-軸之間的夾角。因此,矩陣類型必須是 CV_32FC2 type.
CV_HOUGH_PROBABILISTIC - 概率 Hough 變換(如果圖像包含一些長的線性分割,則效率更高). 它返回線段分割而不是整個線段。每個分割用起點和終點來表示,所以矩陣(或創建的序列)類型是 CV_32SC4.
CV_HOUGH_MULTI_SCALE - 傳統 Hough 變換的多尺度變種。線段的編碼方式與CV_HOUGH_STANDARD 的一致。 - rho與象素相關單位的距離精度
- theta弧度測量的角度精度
- threshold閾值參數。如果相應的累計值大於 threshold, 則函數返回的這個線段.
- param1第一個方法相關的參數:
對傳統 Hough 變換,不使用(0).
對概率 Hough 變換,它是最小線段長度.
對多尺度 Hough 變換,它是距離精度 rho 的分母 (大致的距離精度是 rho 而精確的應該是 rho / param1 ). - param2第二個方法相關參數:
對傳統 Hough 變換,不使用 (0).
對概率 Hough 變換,這個參數表示在同一條直線上進行碎線段連接的最大間隔值(gap), 即當同一條直線上的兩條碎線段之間的間隔小於 param2 時,將其合二爲一。
對多尺度 Hough 變換,它是角度精度 theta 的分母 (大致的角度精度是 theta 而精確的角度應該是 theta / param2).