opencv+python Hough變換的基本原理

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).

檢測效果:

輸入圖片說明

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