日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

OpenCV——Canny直线检测

發(fā)布時(shí)間:2023/12/29 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 OpenCV——Canny直线检测 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

目錄

  • 前言
  • 正文
    • 原理
      • 高斯濾波過濾
      • 計(jì)算像素點(diǎn)的梯度方向(Sobel算子)
      • 非極大值抑制
      • 用雙閾值算法檢測和連接邊緣
      • 通過抑制孤立的弱邊緣最終完成邊緣檢測
    • 代碼
  • 參考文獻(xiàn)

前言

Canny邊緣檢測是從不同視覺對象中提取有用的結(jié)構(gòu)信息并大大減少要處理的數(shù)據(jù)量的一種技術(shù)。我們這里主要用其來進(jìn)行直線邊緣檢測。

正文

原理

Canny邊緣檢測算法主要分為以下五個(gè)步驟(參考自:Canny邊緣檢測算法)

  • 使用高斯濾波器,以平滑圖像,濾除噪聲。
  • 計(jì)算圖像中每個(gè)像素點(diǎn)的梯度強(qiáng)度和方向。
  • 應(yīng)用非極大值抑制,以消除邊緣檢測帶來的雜散響應(yīng)。
  • 應(yīng)用雙閾值檢測來確定真實(shí)的和潛在的邊緣。
  • 通過抑制孤立的弱邊緣最終完成邊緣檢測。
  • 高斯濾波過濾

    為了盡可能減少噪聲對邊緣檢測結(jié)果的影響,所以必須濾除噪聲以防止由噪聲引起的錯(cuò)誤檢測。為了平滑圖像,使用高斯濾波器與圖像進(jìn)行卷積,該步驟將平滑圖像,以減少邊緣檢測器上明顯的噪聲影響。大小為(2k+1)x(2k+1)的高斯濾波器核的生成方程式由下式給出:

    下面是一個(gè)sigma = 1.5,尺寸為3x3的高斯卷積核的例子(需要注意歸一化):

    這個(gè)卷積核是怎么來的,我們可以算一下。我就直接摘抄網(wǎng)上的一些圖了:

    假定中心點(diǎn)的坐標(biāo)是(0,0),那么距離它最近的8個(gè)點(diǎn)的坐標(biāo)如下:

    遠(yuǎn)的點(diǎn)以此類推。
    為了計(jì)算權(quán)重矩陣,需要設(shè)定σ的值。假定σ=1.5,則模糊半徑為1的權(quán)重矩陣如下:

    這個(gè)權(quán)重矩陣,就是你把上面sigma和x,y的值都帶入那個(gè)公式就可以了。

    這9個(gè)點(diǎn)的權(quán)重總和等于0.4787147,如果只計(jì)算這9個(gè)點(diǎn)的加權(quán)平均,還必須讓它們的權(quán)重之和等于1,因此上面9個(gè)值還要分別除以0.4787147,得到最終的權(quán)重矩陣。

    接下來,計(jì)算高斯模糊
    有了權(quán)重矩陣,就可以計(jì)算高斯模糊的值了。
    假設(shè)現(xiàn)有9個(gè)像素點(diǎn),灰度值(0-255)如下:

    每個(gè)點(diǎn)乘以自己的權(quán)重值:

    得到

    將這9個(gè)值加起來,就是中心點(diǎn)的高斯模糊的值。

    對所有點(diǎn)重復(fù)這個(gè)過程,就得到了高斯模糊后的圖像。如果原圖是彩色圖片,可以對RGB三個(gè)通道分別做高斯模糊。

    那么如果一個(gè)點(diǎn)處于邊界,周邊沒有足夠的點(diǎn),怎么辦?

    一個(gè)變通方法,就是把已有的點(diǎn)拷貝到另一面的對應(yīng)位置,模擬出完整的矩陣。

    就類似于這樣的一個(gè)效果:

    你看上面我圈起來的藍(lán)色的地方,就出現(xiàn)了,119-46<225-4。圖像的邊緣這樣就因此便的平滑了。這就是高斯濾波的作用了。

    計(jì)算像素點(diǎn)的梯度方向(Sobel算子)

  • 邊緣:灰度或結(jié)構(gòu)等信息的突變處,邊緣是一個(gè)區(qū)域的結(jié)束,也是另一個(gè)區(qū)域的開始,利用該特征可以分割圖像。
  • 邊緣點(diǎn):圖像中具有坐標(biāo)[x,y],且處在強(qiáng)度顯著變化的位置上的點(diǎn)。
  • 邊緣段:對應(yīng)于邊緣點(diǎn)坐標(biāo)[x,y]及其方位 ,邊緣的方位可能是梯度角。
    索貝爾算子(Sobeloperator)主要用作邊緣檢測,在技術(shù)上,它是一離散性差分算子,用來運(yùn)算圖像亮度函數(shù)的灰度之近似值。在圖像的任何一點(diǎn)使用此算子,將會(huì)產(chǎn)生對應(yīng)的灰度矢量或是其法矢量。
    這里就直接貼圖了:

    Sobel算子根據(jù)像素點(diǎn)上下、左右鄰點(diǎn)灰度加權(quán)差,在邊緣處達(dá)到極值這一現(xiàn)象檢測邊緣。對噪聲具有平滑作用,提供較為精確的邊緣方向信息,邊緣定位精度不夠高。當(dāng)對精度要求不是很高時(shí),是一種較為常用的邊緣檢測方法。
  • 類似的結(jié)果圖就是下面這樣:

    上面這個(gè)就是算出來的梯度值,但這上面那個(gè)sobel算子的符號好像反了,不用管這個(gè),直接按照最上面的那張圖算即可。

    非極大值抑制

    指尋找像素點(diǎn)局部最大值,將非極大值點(diǎn)所對應(yīng)的灰度值置為0,這樣可以剔除掉一大部分非邊緣的點(diǎn)。要進(jìn)行非極大值抑制,就首先要確定像素點(diǎn)C的灰度值在其8值鄰域內(nèi)是否為最大。圖1中藍(lán)色的線條方向?yàn)镃點(diǎn)的梯度方向,這樣就可以確定其局部的最大值肯定分布在這條線上,也即出了C點(diǎn)外,梯度方向的交點(diǎn)dTmp1和dTmp2這兩個(gè)點(diǎn)的值也可能會(huì)是局部最大值。因此,判斷C點(diǎn)灰度與這兩個(gè)點(diǎn)灰度大小即可判斷C點(diǎn)是否為其鄰域內(nèi)的局部最大灰度點(diǎn)。如果經(jīng)過判斷,C點(diǎn)灰度值小于這兩個(gè)點(diǎn)中的任一個(gè),那就說明C點(diǎn)不是局部極大值,那么則可以排除C點(diǎn)為邊緣。這就是非極大值抑制的工作原理。

    上面的這個(gè)解釋應(yīng)該還是算比較清楚的,特別還要注意的兩個(gè)點(diǎn)是:
    1)中非最大抑制是回答這樣一個(gè)問題:“當(dāng)前的梯度值在梯度方向上是一個(gè)局部最大值嗎?” 所以,要把當(dāng)前位置的梯度值與梯度方向上兩側(cè)的梯度值進(jìn)行比較;
    2)梯度方向垂直于邊緣方向。
    但實(shí)際上,我們只能得到C點(diǎn)鄰域的8個(gè)點(diǎn)的值,而dTmp1和dTmp2并不在其中,要得到這兩個(gè)值就需要對該兩個(gè)點(diǎn)兩端的已知灰度進(jìn)行線性插值,也即根據(jù)圖1中的g1和g2對dTmp1進(jìn)行插值,根據(jù)g3和g4對dTmp2進(jìn)行插值,這要用到其梯度方向,這是上文Canny算法中要求解梯度方向矩陣Thita的原因。
    完成非極大值抑制后,會(huì)得到一個(gè)二值圖像,非邊緣的點(diǎn)灰度值均為0,可能為邊緣的局部灰度極大值點(diǎn)可設(shè)置其灰度為128。根據(jù)下文的具體測試圖像可以看出,這樣一個(gè)檢測結(jié)果還是包含了很多由噪聲及其他原因造成的假邊緣。因此還需要進(jìn)一步的處理。

    用雙閾值算法檢測和連接邊緣

    Canny算法中減少假邊緣數(shù)量的方法是采用雙閾值法。選擇兩個(gè)閾值(關(guān)于閾值的選取方法在擴(kuò)展中進(jìn)行討論),根據(jù)高閾值得到一個(gè)邊緣圖像,這樣一個(gè)圖像含有很少的假邊緣,但是由于閾值較高,產(chǎn)生的圖像邊緣可能不閉合,未解決這樣一個(gè)問題采用了另外一個(gè)低閾值。
    在高閾值圖像中把邊緣鏈接成輪廓,當(dāng)?shù)竭_(dá)輪廓的端點(diǎn)時(shí),該算法會(huì)在斷點(diǎn)的8鄰域點(diǎn)中尋找滿足低閾值的點(diǎn),再根據(jù)此點(diǎn)收集新的邊緣,直到整個(gè)圖像邊緣閉合。
    雙閾值的玩法參考下面這張圖:

    通過抑制孤立的弱邊緣最終完成邊緣檢測

    到目前為止,被劃分為強(qiáng)邊緣的像素點(diǎn)已經(jīng)被確定為邊緣,因?yàn)樗鼈兪菑膱D像中的真實(shí)邊緣中提取出來的。然而,對于弱邊緣像素,將會(huì)有一些爭論,因?yàn)檫@些像素可以從真實(shí)邊緣提取也可以是因噪聲或顏色變化引起的。為了獲得準(zhǔn)確的結(jié)果,應(yīng)該抑制由后者引起的弱邊緣。通常,由真實(shí)邊緣引起的弱邊緣像素將連接到強(qiáng)邊緣像素,而噪聲響應(yīng)未連接。為了跟蹤邊緣連接,通過查看弱邊緣像素及其8個(gè)鄰域像素,只要其中一個(gè)為強(qiáng)邊緣像素,則該弱邊緣點(diǎn)就可以保留為真實(shí)的邊緣。

    代碼

    我這里就直接調(diào)用OpenCV的一些函數(shù)去實(shí)現(xiàn)這樣的一個(gè)效果。

    import cv2 as cv import numpy as np# canny運(yùn)算步驟:5步 # 1. 高斯模糊 - GaussianBlur # 2. 灰度轉(zhuǎn)換 - cvtColor # 3. 計(jì)算梯度 - Sobel/Scharr # 4. 非極大值抑制 # 5. 高低閾值輸出二值圖像# 非極大值抑制: # 算法使用一個(gè)3×3鄰域作用在幅值陣列M[i,j]的所有點(diǎn)上; # 每一個(gè)點(diǎn)上,鄰域的中心像素M[i,j]與沿著梯度線的兩個(gè)元素進(jìn)行比較, # 其中梯度線是由鄰域的中心點(diǎn)處的扇區(qū)值ζ[i,j]給出。 # 如果在鄰域中心點(diǎn)處的幅值M[i,j]不比梯度線方向上的兩個(gè)相鄰點(diǎn)幅值大,則M[i,j]賦值為零,否則維持原值; # 此過程可以把M[i,j]寬屋脊帶細(xì)化成只有一個(gè)像素點(diǎn)寬,即保留屋脊的高度值。# 高低閾值連接 # T1,T2為閾值,凡是高于T2的都保留,凡是低于T1的都丟棄 # 從高于T2的像素出發(fā),凡是大于T1而且相互連接的都保留。最終得到一個(gè)輸出二值圖像 # 推薦高低閾值比值為T2:T1 = 3:1/2:1,其中T2高閾值,T1低閾值def edge_demo(image):blurred = cv.GaussianBlur(image,(3,3),0)#高斯模糊gray = cv.cvtColor(blurred,cv.COLOR_BGR2GRAY)# 將其變成灰度圖grad_x = cv.Sobel(gray,cv.CV_16SC1,1,0)#用sobel算子求梯度。最后兩個(gè)參數(shù)就是說是求的x,還是y的梯度grad_y = cv.Sobel(gray,cv.CV_16SC1,0,1)edge_output = cv.Canny(grad_x,grad_y,30,150)# 將兩個(gè)梯度傳入,然后傳入高閾值與低閾值#edge_output = cv.Canny(gray,50,150)cv.imshow("gray",gray)cv.imshow("canny_dmeo",edge_output)src = cv.imread("../images/boss2.jpg") cv.namedWindow("input image",cv.WINDOW_AUTOSIZE) cv.imshow('input image', src) edge_demo(src) cv.waitKey(0) # 等有鍵輸入或者1000ms后自動(dòng)將窗口消除,0表示只用鍵輸入結(jié)束窗口cv.destroyAllWindows()

    效果圖

    參考文獻(xiàn)

  • 高斯模糊的算法(高斯卷積 高斯核)
  • sobel算子原理與實(shí)現(xiàn)
  • canny算子中的非極大值抑制是什么原理?
  • Canny邊緣檢測算法原理及其VC實(shí)現(xiàn)詳解(一)
  • 圖像處理中最經(jīng)典的邊沿檢測算法: Canny邊緣檢測
  • 總結(jié)

    以上是生活随笔為你收集整理的OpenCV——Canny直线检测的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。