天天看點

opencv+python Hough變換的基本原理

Hough變換思想(參數空間變換):

在原始圖像坐标系下的一個點對應了參數坐标系中的一條直線,同樣參數坐标系的一條直線對應了原始坐标系下的一個點,然後,原始坐标系下呈現直線的所有點,它們的斜率和截距是相同的,是以它們在參數坐标系下對應于同一個點。這樣在将原始坐标系下的各個點投影到參數坐标系下之後,看參數坐标系下有沒有聚集點,這樣的聚集點就對應了原始坐标系下的直線。

opencv+python 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)值對應于直角坐标中所求直線。

opencv+python Hough變換的基本原理

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

檢測效果:

opencv+python Hough變換的基本原理