亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

OpenCV-Python學(xué)習(xí)筆記(十六):Hough直線變換、Hough圓

系統(tǒng) 2507 0

一、Hough 直線變換(Hough Line Transform

目標(biāo)
? 理解霍夫變換的概念
? 學(xué)習(xí)如何在一張圖片中檢測直線
? 學(xué)習(xí)函數(shù): cv2.HoughLines(), cv2.HoughLinesP()

原理
霍夫變換在檢測各種形狀的的技術(shù)中非常流行, 如果你要檢測的形狀可以用數(shù)學(xué)表達(dá)式寫出,你就可以是使用霍夫變換檢測它,即使檢測的形狀存在一點破壞或者扭曲也可以使用 。我們下面就看看如何使用霍夫變換檢測直線。?

一條直線可以用數(shù)學(xué)表達(dá)式? y = mx+c 或者? \rho = x \cos \theta + y \sin \theta 表示。ρ 是從原點到直線的垂直距離, θ 是直線的垂線與橫軸順時針方向的夾角(如果你使用的坐標(biāo)系不同方向也可能不同,這里是按 OpenCV 使用的坐標(biāo)系描述的)。如下圖所示:?

OpenCV-Python學(xué)習(xí)筆記(十六):Hough直線變換、Hough圓變換_第1張圖片

所以如果一條線在原點下方經(jīng)過, ρ 的值就應(yīng)該大于 0,角度小于 180。但是如果從原點上方經(jīng)過的話,角度不是大于 180,而是小于 180,但 ρ 的值小于 0。垂直線的角度為 0 度,水平線的角度為 90 度。

讓我們來看看霍夫變換是如何工作的。每一條直線都可以用 (ρ,?θ) 表示。所以首先創(chuàng)建一個 2D 數(shù)組(累加器),初始化累加器,所有的值都為 0。行表示 ρ,列表示 θ。這個數(shù)組的大小決定了最后結(jié)果的準(zhǔn)確性。如果你希望角度精確到 1 度,你就需要 180 列。對于 ρ,最大值為圖片對角線的距離。所以如果精確度要達(dá)到一個像素的級別,行數(shù)就應(yīng)該與圖像對角線的距離相等。?

想象一下我們有一個大小為 100x100 的直線位于圖像的中央。取直線上的第一個點,我們知道此處的(x, y)值。把 x 和 y 帶入上邊的方程組,然后遍歷 θ 的取值: 0, 1, 2, 3, ..., 180。分別求出與其對應(yīng)的 ρ 的值,這樣我們就得到一系列(ρ,θ)的數(shù)值對,如果這個數(shù)值對在累加器中也存在相應(yīng)的位置,就在這個位置上加 1。所以現(xiàn)在累加器中的(50, 90)=1。(一個點可能存在于多條直線中,所以對于直線上的每一個點可能是累加器中的多個值同時加 1)

現(xiàn)在取直線上的第二個點。重復(fù)上邊的過程。更新累加器中的值。現(xiàn)在累加器中(50,90)的值為 2。你每次做的就是更新累加器中的值。對直線上的每個點都執(zhí)行上邊的操作,每次操作完成之后,累加器中的值就加 1,但其他地方有時會加 1, 有時不會。按照這種方式下去,到最后累加器中(50,90)的值肯定是最大的。如果你搜索累加器中的最大值,并找到其位置(50,90),這就說明圖像中有一條直線,這條直線到原點的距離為 50,它的垂線與橫軸的夾角為 90 度。下面的動畫很好的演示了這個過程(Image Courtesy: Amos Storkey )。

OpenCV-Python學(xué)習(xí)筆記(十六):Hough直線變換、Hough圓變換_第2張圖片

這就是霍夫直線變換工作的方式。很簡單,也許你自己就可以使用 Numpy搞定它。下圖顯示了一個累加器。其中最亮的兩個點代表了圖像中兩條直線的參數(shù)。(Image courtesy: Wikipedia)。

OpenCV-Python學(xué)習(xí)筆記(十六):Hough直線變換、Hough圓變換_第3張圖片

1.1?OpenCV 中的霍夫變換

上面介紹的整個過程在 OpenCV 中都被封裝進(jìn)了一個函數(shù): cv2.HoughLines() 。返回值就是一個數(shù)組(ρ,?θ)。 ρ 的單位是像素, θ 的單位是弧度。這個 函數(shù)的第一個參數(shù)是一個二值化圖像,所以在進(jìn)行霍夫變換之前要首先進(jìn)行二值化,或者進(jìn)行Canny 邊緣檢測 。第二和第三個值分別代表 ρ 和 θ 的精確度。第四個參數(shù)是閾值,只有累加其中的值高于閾值時才被認(rèn)為是一條直線,也可以把它看成能檢測到的直線的最短長度(以像素點為單位)。示例如下:

            
              import cv2 as cv
import numpy as np

img = cv.imread(cv.samples.findFile('sudoku.png'))
gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
edges = cv.Canny(gray, 50, 150, apertureSize=3)
lines = cv.HoughLines(edges, 1, np.pi / 180, 200)
for line in lines:
    rho, theta = line[0]
    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))
    cv.line(img, (x1, y1), (x2, y2), (0, 0, 255), 2)
cv.imwrite('houghlines3.jpg', img)
            
          

結(jié)果:

OpenCV-Python學(xué)習(xí)筆記(十六):Hough直線變換、Hough圓變換_第4張圖片

1.2 Probabilistic Hough Transform

從上邊的過程我們可以發(fā)現(xiàn):僅僅是一條直線都需要兩個參數(shù),這需要大量的計算。 Probabilistic_Hough_Transform 是對霍夫變換的一種優(yōu)化 。它不會對每一個點都進(jìn)行計算,而是從一幅圖像中隨機選取一個點集進(jìn)行計算,對于直線檢測來說這已經(jīng)足夠了。但是使用這種變換我們必須要降低閾值(總的點數(shù)都少了,閾值肯定也要小呀!)。下圖是對兩種方法的對比。(Image Courtesy : Franck Bettinger’s homepage)

OpenCV-Python學(xué)習(xí)筆記(十六):Hough直線變換、Hough圓變換_第5張圖片

OpenCV 中使用由?Matas, J. , Galambos, C. 和 Kittler, J.V. 提出的Progressive Probabilistic Hough Transform。這個函數(shù)是 cv2.HoughLinesP() ,它有兩個參數(shù):?

? minLineLength - 線的最短長度。比這個短的線都會被忽略。
? MaxLineGap - 兩條線段之間的最大間隔,如果小于此值,這兩條直線就被看成是一條直線。?

更加給力的是,這個函數(shù)的返回值就是直線的起點和終點。而在前面的例子中,我們只得到了直線的參數(shù),并且你必須要找到所有的點。而在這里一切都很直接很簡單。

            
              import cv2 as cv
import numpy as np

img = cv.imread(cv.samples.findFile('sudoku.png'))
gray = cv.cvtColor(img,cv.COLOR_BGR2GRAY)
edges = cv.Canny(gray,50,150,apertureSize = 3)
lines = cv.HoughLinesP(edges,1,np.pi/180,100,minLineLength=100,maxLineGap=10)
for line in lines:
    x1,y1,x2,y2 = line[0]
    cv.line(img,(x1,y1),(x2,y2),(0,255,0),2)
cv.imwrite('houghlines5.jpg',img)
            
          

?

OpenCV-Python學(xué)習(xí)筆記(十六):Hough直線變換、Hough圓變換_第6張圖片

?

二、Hough圓形變換(Hough Circle Transform)

目標(biāo)
? 學(xué)習(xí)使用霍夫變換在圖像中找圓形(環(huán))。
? 學(xué)習(xí)函數(shù): cv2.HoughCircles()


原理
圓形的數(shù)學(xué)表達(dá)式為 (x-x_{center})^2 + (y - y_{center})^2 = r^2 ,其中 (x_{center},y_{center}) ?為圓心的坐標(biāo), r 為圓的半徑。從這個方程中我們可以看出:一個圓環(huán)需要 3個參數(shù)來確定。所以進(jìn)行圓形霍夫變換的累加器必須是 3 維的,這樣的話效率就會很低。OpenCV 用了一個比較巧妙的辦法, 霍夫梯度法 ,它可以使用邊界的梯度信息。我們要使用的函數(shù)為 cv2.HoughCircles() 。文檔中對它的參數(shù)有詳細(xì)的解釋。這里我們就直接看代碼吧。?

            
              import numpy as np
import cv2 as cv
img = cv.imread('opencv-logo-white.png',0)
img = cv.medianBlur(img,5)
cimg = cv.cvtColor(img,cv.COLOR_GRAY2BGR)
circles = cv.HoughCircles(img,cv.HOUGH_GRADIENT,1,20,
                            param1=50,param2=30,minRadius=0,maxRadius=0)
circles = np.uint16(np.around(circles))
for i in circles[0,:]:
    # draw the outer circle
    cv.circle(cimg,(i[0],i[1]),i[2],(0,255,0),2)
    # draw the center of the circle
    cv.circle(cimg,(i[0],i[1]),2,(0,0,255),3)
cv.imshow('detected circles',cimg)
cv.waitKey(0)
cv.destroyAllWindows()
            
          

?結(jié)果:

OpenCV-Python學(xué)習(xí)筆記(十六):Hough直線變換、Hough圓變換_第7張圖片

?

參考資料:

1.?OpenCV-Python官方文檔-Hough Line Transform

2.?OpenCV-Python官方文檔-Hough Circle Transform

3.《OpenCV-Python 中文教程》(段力輝 譯)

?

?


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯(lián)系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發(fā)表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 国产成人高清精品免费观看 | 久久99国产亚洲高清观看韩国 | 成人短视频在线观看免费 | 99久久99久久精品免费看蜜桃 | 国产精品一区二区在线播放 | 三级不卡 | 欧美一级毛片图 | 成人亚欧网站在线观看 | 米奇影视7777 | 888午夜不卡理论久久 | 好吊妞视频在线观看 | 69做爰视频在线观看 | 99久久精品费精品国产一区二 | 性做爰片视频毛片 | 欧美亚洲动漫 | 久久国产一区二区 | 日韩另类视频 | 狠狠操福利视频 | 欧美视频一区二区三区在线观看 | 视频毛片 | 色网址在线观看 | 性成人动作片在线看 | 色综合天天综合网站中国 | 正在播放国产乱子伦视频 | 亚洲免费高清 | 欧美日韩激情在线一区二区 | 国产精品欧美亚洲韩国日本99 | 四虎国产永久在线观看 | 国产精品久久久久影院免费 | 91色桃 | 一级特级aaaa毛片免费观看 | 五月天婷婷在线免费观看 | 四虎影院在线免费播放 | 久久不卡免费视频 | 天天干天天曰天天操 | 天天做夜夜做 | 91拍拍在线观看 | 久久加久久 | 国产欧美日韩看片片在线人成 | 日日碰夜夜爽 | 久久久国产99久久国产久 |