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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > python >内容正文

python

python实现sobel_OpenCV-Python系列之Sobel和Scharr算子

發布時間:2025/3/21 python 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 python实现sobel_OpenCV-Python系列之Sobel和Scharr算子 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

我們再上個教程中留了一個小彩蛋——形態學的梯度問題,通常情況下,它被用于提取圖像的輪廓,今天我們來了解圖像邊緣的另一種方法,它將比形態學梯度更有效,適用范圍也更廣。

Sobel算子

前面的例子,已經接觸到了圖像卷積運算。最終要的卷積運算之一是用于計算圖像的導數(或近似導數)。為什么圖像中導數的計算很重要,看下面邊緣檢測的例子:

很容易觀察到上面圖像中像素灰度值變化沒有規律。一種比較好的描述這種變化的方法是采用導數。其中梯度劇烈變化的地方代表圖像灰度值變化強烈的地方,也就是邊緣。

為了更好的說明,以1維圖像(也就是圖像的1行)為例。邊緣出現在灰度值跳變的地方,如下圖所示:

如果對上面的1維圖像求導數,得到下圖,可以很明顯的看到邊緣所在的位置。

從上面的解釋,我們可以設置一個閾值,根據局部像素變化強烈程度獲取圖像邊緣。

sobel算子是一個離散微分算子,計算得到的是圖像梯度的近似值。sobel算子結合了高斯平滑和微分。

假設輸入圖像是I,,核大小為3,通過下面運算分別計算水平方向和垂直方向的微分:

a.水平方向:

b.垂直方向:

具體運算為:

結合上面結果可以計算出圖像中一個點的近似梯度:

或者表示為:

需要注意的是,當核的大小為3時,也就是上面所示的Sobel核可能會產生明顯的誤差(畢竟Sobel只是微分的近似值)。

在OpenCV-Python中,使用Sobel的算子的函數原型如下:

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

前四個是必須的參數:

第一個參數是需要處理的圖像;

第二個參數是圖像的深度,-1表示采用的是與原圖像相同的深度。目標圖像的深度必須大于等于原圖像的深度;

dx和dy表示的是求導的階數,0表示這個方向上沒有求導,一般為0、1、2。

其后是可選的參數:

dst不用解釋了;

ksize是Sobel算子的大小,必須為1、3、5、7。

scale是縮放導數的比例常數,默認情況下沒有伸縮系數;

delta是一個可選的增量,將會加到最終的dst中,同樣,默認情況下沒有額外的值加到dst中;

borderType是判斷圖像邊界的模式。這個參數默認值為cv2.BORDER_DEFAULT。

現在我們來看實驗圖像:

實戰代碼:import?cv2

import?numpy?as?np

img?=?cv2.imread("pie.png",0)

x?=?cv2.Sobel(img,cv2.CV_16S,1,0)

cv2.imshow("x",x)

cv2.waitKey(0)

cv2.destroyAllWindows()

我們發現沒有輸出,原因在于圖像格式的問題,在Sobel函數的第二個參數這里使用了cv2.CV_16S。因為OpenCV文檔中對Sobel算子的介紹中有這么一句:“in the case of 8-bit input images it will result in truncated derivatives”。即Sobel函數求完導數后會有負值,還有會大于255的值。而原圖像是uint8,即8位無符號數,所以Sobel建立的圖像位數不夠,會有截斷。因此要使用16位有符號的數據類型,即cv2.CV_16S。

在經過處理后,別忘了用convertScaleAbs()函數將其轉回原來的uint8形式。否則將無法顯示圖像,而只是一副灰色的窗口。convertScaleAbs()的原型為:

dst = cv2.convertScaleAbs(src[, dst[, alpha[, beta]]])

其中可選參數alpha是伸縮系數,beta是加到結果上的一個值。結果返回uint8類型的圖片。

由于Sobel算子是在兩個方向計算的,最后還需要用cv2.addWeighted(...)函數將其組合起來。其函數原型為:

dst = cv2.addWeighted(src1, alpha, src2, beta, gamma[, dst[, dtype]])

當然,這個函數我們在前面已經講述過在這里就不多講述了。

我們再來看代碼:import?cv2

import?numpy?as?np

img?=?cv2.imread("pie.png",0)

x?=?cv2.Sobel(img,cv2.CV_16S,1,0)

y?=?cv2.Sobel(img,cv2.CV_16S,0,1)

absX?=?cv2.convertScaleAbs(x)

absY?=?cv2.convertScaleAbs(y)

dst?=?cv2.addWeighted(absX,0.5,absY,0.5,0)

cv2.imshow("x",absX)

cv2.imshow("y",absY)

cv2.imshow("res",dst)

cv2.waitKey(0)

cv2.destroyAllWindows()

先分別來看下,x,y兩個方向上的:

再看看最終相加在一起的:

由于Sobel算子是濾波算子的形式,用于提取邊緣,可以利用快速卷積函數,?簡單有效,因此應用廣泛。美中不足的是,Sobel算子并沒有將圖像的主體與背景嚴格地區分開來,即Sobel算子沒有嚴格地模擬人的視覺生理特征,所以提取的圖像輪廓有時并不能令人滿意。

Scharr算子

Scharr()?函數提供了比標準Sobel函數更精確的計算結果。它使用了下面的核:

除了卷積核與Sobel不同,在其余方面它與Sobel基本一致,我們來看它的函數原型:

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

參數就不再介紹了,與Sobel是完全一致的,我們來看看代碼演示:import?cv2

import?numpy?as?np

img?=?cv2.imread("pie.png",0)

x?=?cv2.Scharr(img,cv2.CV_16S,1,0)

y?=?cv2.Scharr(img,cv2.CV_16S,0,1)

absX?=?cv2.convertScaleAbs(x)

absY?=?cv2.convertScaleAbs(y)

dst?=?cv2.addWeighted(absX,0.5,absY,0.5,0)

cv2.imshow("res",dst)

cv2.waitKey(0)

cv2.destroyAllWindows()

本次教程所講述的Sobel算子與Scharr算子在圖形的邊緣檢測方面有些缺陷,想必大家也看到了,不過在下次教程我們將會講述這個問題。

總結

以上是生活随笔為你收集整理的python实现sobel_OpenCV-Python系列之Sobel和Scharr算子的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。