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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

OpenCV与图像处理学习八——图像边缘提取(Canny检测代码)

發(fā)布時(shí)間:2024/7/23 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 OpenCV与图像处理学习八——图像边缘提取(Canny检测代码) 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

OpenCV與圖像處理學(xué)習(xí)八——圖像邊緣提取(Canny檢測代碼)

  • 一、圖像梯度
    • 1.1 梯度
    • 1.2 圖像梯度
  • 二、梯度圖與梯度算子
    • 2.1模板卷積
    • 2.2 梯度圖
    • 2.3 梯度算子
      • 2.3.1 Roberts交叉算子
      • 2.3.2 Prewitt算子
      • 2.3.3 Sobel算子
  • 三、Canny邊緣檢測算法(代碼實(shí)現(xiàn))

這次筆記簡單介紹圖像梯度、梯度圖以及梯度算子的概念,并詳細(xì)介紹三種基本的梯度算子,然后簡單的介紹Canny檢測的原理與代碼實(shí)現(xiàn)(因?yàn)镃anny檢測中有很重要的一步用到了Sobel算子計(jì)算梯度,所以先介紹前面的內(nèi)容)。

一、圖像梯度

1.1 梯度

先來看梯度的概念:

梯度是一個(gè)向量梯度方向指向函數(shù)變化最快的方向,大小就是它的模,也是最大的變化率,對于二元函數(shù)z=f(x,y),它在點(diǎn)(x,y)的梯度記為:

或:

梯度的計(jì)算公式為:
梯度向量的幅值和方向角為:

有了梯度是最大變化率這么一個(gè)認(rèn)識(shí),下面我們拓展到圖像梯度的概念上來。

1.2 圖像梯度

圖像梯度即圖像中灰度變化的度量,求圖像梯度的過程是二維離散函數(shù)求導(dǎo)過程。

因?yàn)閳D像邊緣上的像素值變化非常劇烈,所以圖像的邊緣其實(shí)就是圖像上灰度級變化很快的點(diǎn)的集合。

下圖展示了一個(gè)灰度圖的數(shù)學(xué)化表達(dá),像素點(diǎn)(x,y)的灰度值是f(x,y),它有八個(gè)鄰域(有時(shí)使用四鄰域):

圖像在點(diǎn)(x,y)的梯度為:

分別對應(yīng)圖像的水平方向和豎直方向,可見圖像梯度的求法只是像素值之間的差,而無需求導(dǎo)(因?yàn)閿?shù)字圖像是離散的)。

二、梯度圖與梯度算子

2.1模板卷積

要理解梯度圖的生成,就要先了解模板卷積的過程,模板卷積是模板運(yùn)算的一種方式,其步驟如下:

  • 將模板在輸入圖像中漫游,并將模板中心與圖像中某個(gè)像素位置重合;
  • 將模板上各個(gè)系數(shù)與模板下各對應(yīng)像素的灰度相乘;
  • 將所有乘積相加(為保持灰度范圍,常將結(jié)果再除以模板系數(shù)之和,后面梯度算子模板和為0的話就不需要除了);
  • 將上述運(yùn)算結(jié)果(模板的響應(yīng)輸出)賦給輸出圖像中對應(yīng)模板中心位置的像素。

  • 其實(shí)就是現(xiàn)在的卷積運(yùn)算干的事。

    2.2 梯度圖

    梯度圖的生成和模板卷積相同,不同的是要生成梯度圖,還需要在模板卷積完成后計(jì)算在點(diǎn)(x,y)梯度的幅值,將幅值作為像素值,這樣才算完。

    注意: 梯度圖上每個(gè)像素點(diǎn)的灰度值就是梯度向量的幅度,生成梯度圖需要兩個(gè)模板(求圖像梯度需要兩個(gè)方向),右圖為水平和豎直方向最簡單的模板:



    所以水平方向和豎直方向上的梯度為:

    2.3 梯度算子

    梯度算子是一階導(dǎo)數(shù)算子,是水平G(x)和豎直G(y)方向?qū)?yīng)模板的組合也有對角線方向,即是上述卷積模板的組合。

    常見的一階算子:Roberts交叉算子, Prewitt算子, Sobel算子,下面將分別介紹。

    2.3.1 Roberts交叉算子


    Roberts交叉算子其本質(zhì)是一個(gè)對角線方向的梯度算子,對應(yīng)的水平方向和豎直方向的梯度分別為:

    優(yōu)點(diǎn):邊緣定位較準(zhǔn)適用于邊緣明顯且噪聲較少的圖像
    缺點(diǎn):

  • 沒有描述水平和豎直方向的灰度變化,只關(guān)注了對角線方向,容易造成遺漏。
  • 魯棒性差。由于點(diǎn)本身參加了梯度計(jì)算,不能有效的抑制噪聲的干擾
  • 2.3.2 Prewitt算子


    Prewitt算子是典型的3*3模板,其模板中心對應(yīng)要求梯度的原圖像坐標(biāo)(x,y), (x,y)對應(yīng)的8-鄰域的像素灰度值如下表所示:

    通過Prewitt算子的水平模板M(x)卷積后,對應(yīng)的水平方向梯度為:

    通過Prewitt算子的豎直模板M(y)卷積后,對應(yīng)的豎直方向梯度為:

    輸出梯度圖在(x,y)的灰度值為:

    優(yōu)點(diǎn):Prewitt算子引入了類似局部平均的運(yùn)算,對噪聲具有平滑作用,較Roberts算子更能抑制噪聲。

    2.3.3 Sobel算子


    Sobel算子其實(shí)就是是增加了權(quán)重系數(shù)的Prewitt算子,其模板中心對應(yīng)要求梯度的原圖像坐標(biāo),對應(yīng)的8-鄰域的像素灰度值如下表所示:

    通過Sobel算子的水平模板M(x)卷積后,對應(yīng)的水平方向梯度為:

    通過Sobel算子的豎直模板M(y)卷積后,對應(yīng)的豎直方向梯度為:


    輸出梯度圖在(x,y)的灰度值為:

    優(yōu)點(diǎn):Sobel算子引入了類似局部加權(quán)平均的運(yùn)算,對邊緣的定位比要比Prewitt算子好。

    因?yàn)镾obel算子的效果較好,實(shí)際使用中相比于另外兩種更多,所以我們只看一下Sobel算子的例子。

    函數(shù):

    dst = cv2.Sobel( src, ddepth, dx, dy[, dst[, ksize[, scale[, delta[, borderType]]]]] )

    參數(shù):

  • src:輸入圖像。

  • ddepth:輸出圖像位深度,-1表示采用的是與原圖像相同的深度。目標(biāo)圖像的深度必須大于等于原圖像的深度;

  • dx:x導(dǎo)數(shù)的階數(shù),0表示這個(gè)方向上沒有求導(dǎo),一般為0、 1、 2;

  • dy:y導(dǎo)數(shù)的階數(shù),0表示這個(gè)方向上沒有求導(dǎo),一般為0、 1、 2;

  • ksize:Sobel算子的尺寸,必須是1,3,5或7。還可以是一個(gè)特殊值,ksize = FILTER_SCHARR (-1),那么將會(huì)使用scharr算子,在x方向的算子為:
    在y方向上是這個(gè)算子的轉(zhuǎn)置。

  • scale:(可選)計(jì)算的導(dǎo)數(shù)值的比例因子;默認(rèn)情況下,不應(yīng)用縮放。

  • delta:(可選)在將結(jié)果存儲(chǔ)到dst中之前添加到結(jié)果中的增量值。

  • 看個(gè)例子:

    import numpy as np import cv2 from matplotlib import pyplot as plt img = cv2.imread('./image/girl2.png', 0) sobelx = cv2.Sobel(img, cv2.CV_64F, 1, 0, ksize=5) sobely = cv2.Sobel(img, cv2.CV_64F, 0, 1, ksize=5)plt.subplot(1, 3, 1), plt.imshow(img, cmap = 'gray') plt.title('Original'), plt.xticks([]), plt.yticks([]) plt.subplot(1, 3, 2), plt.imshow(sobelx, cmap = 'gray') plt.title('Sobel X'), plt.xticks([]), plt.yticks([]) plt.subplot(1, 3, 3),plt.imshow(sobely, cmap = 'gray') plt.title('Sobel Y'), plt.xticks([]), plt.yticks([]) plt.show()

    得到的就是該圖像在x方向上和y方向上的梯度圖:

    從這個(gè)效果中我們也可以看出,梯度圖能夠突出圖像中的邊緣或明暗變化劇烈的地方

    三、Canny邊緣檢測算法(代碼實(shí)現(xiàn))

    Canny算法是先平滑后求導(dǎo)數(shù)的方法。 John Canny研究了最優(yōu)邊緣檢測方法所需的特性,給出了評價(jià)邊緣檢測性能優(yōu)劣的三個(gè)指標(biāo):

  • 好的信噪比,即將非邊緣點(diǎn)判定為邊緣點(diǎn)的概率要低,將邊緣點(diǎn)判為非邊緣點(diǎn)的概率要低;
  • 高的定位性能,即檢測出的邊緣點(diǎn)要盡可能在實(shí)際邊緣的中心;
  • 對單一邊緣僅有唯一響應(yīng),即單個(gè)邊緣產(chǎn)生多個(gè)響應(yīng)的概率要低,并且虛假響應(yīng)邊緣應(yīng)該得到最大抑制。
  • 步驟:

  • 彩色圖像轉(zhuǎn)換為灰度圖像(以灰度圖單通道圖讀入)
  • 對圖像進(jìn)行高斯模糊(去噪)
  • 計(jì)算圖像梯度(這里用到了Sobel算子來計(jì)算圖像梯度),根據(jù)梯度計(jì)算圖像邊緣幅值與角度
  • 沿梯度方向進(jìn)行非極大值抑制(邊緣細(xì)化)
  • 雙閾值邊緣連接處理
  • 二值化圖像輸出結(jié)果
  • 在OpenCV中的函數(shù)為:

    edges = cv2.Canny( image, threshold1, threshold2[, edges[, apertureSize[, L2gradient]]] )

    參數(shù):

  • image:輸入圖像,灰度圖。
  • threshold1:雙閾值邊緣連接處理的第一個(gè)閾值。
  • threshold2:雙閾值邊緣連接處理的第二個(gè)閾值。
  • apertureSize:Sobel算子的尺寸。
  • L2gradient:是否使用L2正則化更精確地計(jì)算梯度,還是使用L1。
  • 看個(gè)例子:

    # 加載 opencv 和 numpy import cv2 import numpy as np # 以灰度圖形式讀入圖像 img = cv2.imread('./image/canny.png', 0) v1 = cv2.Canny(img, 80, 150, (3, 3)) v2 = cv2.Canny(img, 50, 100, (5, 5))# np.vstack():在豎直方向上堆疊 # np.hstack():在水平方向上平鋪堆疊 ret = np.hstack((v1, v2)) cv2.imshow('img', ret) cv2.waitKey(0) cv2.destroyAllWindows()

    原圖如下所示:

    通過canny檢測得到該圖的邊緣信息,設(shè)置了兩組參數(shù),得到的結(jié)果分別為:

    不同的參數(shù)設(shè)置可能得到不同的結(jié)果,很明顯第一種參數(shù)使得檢測得到的邊緣信息更少更干凈,而第二種得到的更多更全面,實(shí)際使用中可以自己調(diào)節(jié)。

    Canny檢測作為傳統(tǒng)的圖像邊緣提取算法,雖然效果上不如現(xiàn)在大火的深度學(xué)習(xí)的各種網(wǎng)絡(luò),但是對于一些邊緣信息較為明顯單一的圖像來說任然有使用價(jià)值,我們將輸入圖像換一下:

    再用Canny檢測(上述代碼,換一下輸入圖像即可),得到的結(jié)果為:

    可以看到檢測效果已經(jīng)非常不錯(cuò)了,更重要的是,它不需要訓(xùn)練,所以速度非常的快,這是它很大的一個(gè)優(yōu)點(diǎn),所以現(xiàn)在還是會(huì)使用到Canny檢測。

    總結(jié)

    以上是生活随笔為你收集整理的OpenCV与图像处理学习八——图像边缘提取(Canny检测代码)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

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