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

歡迎訪問 生活随笔!

生活随笔

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

python

python计算机视觉2:图像边缘检测

發(fā)布時間:2023/12/19 python 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 python计算机视觉2:图像边缘检测 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.


我是一名初學者,如果你發(fā)現(xiàn)文中有錯誤,請留言告訴我,謝謝


?

如果需要檢測到圖像里面的邊緣,首先我們需要知道邊緣處具有什么特征。

對于一幅灰度圖像來說,邊緣兩邊的灰度值肯定不相同,這樣我們才能分辨出哪里是邊緣,哪里不是。

因此,如果我們需要檢測一個灰度圖像的邊緣,我們需要找出哪里的灰度變化最大。顯然,灰度變化越大,對比度越強,邊緣就越明顯。

那么問題來了,我們怎么知道哪里灰度變化大,哪里灰度變化小呢?


?導(dǎo)數(shù),梯度,邊緣信息?

在數(shù)學中,與變化率有關(guān)的就是導(dǎo)數(shù)

如果灰度圖像的像素是連續(xù)的(實際不是),那么我們可以分別原圖像G對x方向和y方向求導(dǎo)數(shù)

獲得x方向的導(dǎo)數(shù)圖像Gx和y方向的導(dǎo)數(shù)圖像Gy。Gx和Gy分別隱含了x和y方向的灰度變化信息,也就隱含了邊緣信息。

如果要在同一圖像上包含兩個方向的邊緣信息,我們可以用到梯度。(梯度是一個向量)

原圖像的梯度向量Gxy為(Gx,Gy),梯度向量的大小和方向可以用下面兩個式子計算

角度值好像需要根據(jù)向量所在象限不同適當+pi或者-pi。

梯度向量大小就包含了x方向和y方向的邊緣信息。


?

?圖像導(dǎo)數(shù)?

實際上,圖像矩陣是離散的。

連續(xù)函數(shù)求變化率用的是導(dǎo)數(shù),而離散函數(shù)求變化率用的是差分。

差分的概念很容易理解,就是用相鄰兩個數(shù)的差來表示變化率。

下面公式是向后差分

x方向的差分:Gx(n,y) = G(n,y)-G(n-1,y)

y方向的差分:Gy(x,n) = G(x,n)-G(x,n-1)

?實際計算圖像導(dǎo)數(shù)時,我們是通過原圖像和一個算子進行卷積來完成的(這種方法是求圖像的近似導(dǎo)數(shù))。

最簡單的求圖像導(dǎo)數(shù)的算子是 Prewitt算子

x方向的Prewitt算子為

y方向的Prewitt算子為

---------------------------------------------

原圖像和一個算子進行卷積的大概過程如下

如果圖像矩陣中一塊區(qū)域為

那么x5處的x方向的導(dǎo)數(shù)是,將x方向算子的中心和x5重合,然后對應(yīng)元素相乘再求和,即

x5處的x方向?qū)?shù)為x3+x6+x9-x1-x4-x7

對矩陣中所有元素進行上述計算,就是卷積的過程。

--------------------------------------------

因此,利用原圖像和x方向Prewitt算子進行卷積就可以得到圖像的x方向?qū)?shù)矩陣Gx,

利用原圖像和y方向Prewitt算子進行卷積就可以得到圖像的y方向?qū)?shù)矩陣Gy。

利用公式

就可以得到圖像的梯度矩陣Gxy,這個矩陣包含圖像x方向和y方向的邊緣信息。


?

?Python實現(xiàn)卷積及Prewitt算子的邊緣檢測?

?首先我們把圖像卷積函數(shù)封裝在一個名為imconv的函數(shù)中 ?( 實際上,scipy庫中的signal模塊含有一個二維卷積的方法convolve2d() ?)

import numpy as np from PIL import Imagedef imconv(image_array,suanzi):'''計算卷積參數(shù)image_array 原灰度圖像矩陣suanzi 算子返回原圖像與算子卷積后的結(jié)果矩陣'''image = image_array.copy() # 原圖像矩陣的深拷貝 dim1,dim2 = image.shape# 對每個元素與算子進行乘積再求和(忽略最外圈邊框像素)for i in range(1,dim1-1):for j in range(1,dim2-1):image[i,j] = (image_array[(i-1):(i+2),(j-1):(j+2)]*suanzi).sum()# 由于卷積后灰度值不一定在0-255之間,統(tǒng)一化成0-255image = image*(255.0/image.max())# 返回結(jié)果矩陣return image

?

然后我們利用Prewitt算子計算x方向?qū)?shù)矩陣Gx,y方向?qū)?shù)矩陣Gy,和梯度矩陣Gxy。

import numpy as np import matplotlib.pyplot as plt# x方向的Prewitt算子 suanzi_x = np.array([[-1, 0, 1],[ -1, 0, 1],[ -1, 0, 1]])# y方向的Prewitt算子 suanzi_y = np.array([[-1,-1,-1],[ 0, 0, 0],[ 1, 1, 1]])# 打開圖像并轉(zhuǎn)化成灰度圖像 image = Image.open("pika.jpg").convert("L")# 轉(zhuǎn)化成圖像矩陣 image_array = np.array(image)# 得到x方向矩陣 image_x = imconv(image_array,suanzi_x)# 得到y(tǒng)方向矩陣 image_y = imconv(image_array,suanzi_y)# 得到梯度矩陣 image_xy = np.sqrt(image_x**2+image_y**2) # 梯度矩陣統(tǒng)一到0-255 image_xy = (255.0/image_xy.max())*image_xy# 繪出圖像 plt.subplot(2,2,1) plt.imshow(image_array,cmap=cm.gray) plt.axis("off") plt.subplot(2,2,2) plt.imshow(image_x,cmap=cm.gray) plt.axis("off") plt.subplot(2,2,3) plt.imshow(image_y,cmap=cm.gray) plt.axis("off") plt.subplot(2,2,4) plt.imshow(image_xy,cmap=cm.gray) plt.axis("off") plt.show()

?

?Prewitt算子 的結(jié)果如下圖所示

上方:左圖為原圖像,右圖為x方向?qū)?shù)圖像

下方:左圖為y方向?qū)?shù)圖像,右圖為梯度圖像

從圖中可以看出,Prewitt算子雖然能檢測出圖像邊緣,但是檢測結(jié)果較為粗糙,還帶有大量的噪聲。


?

?近似導(dǎo)數(shù)的Sobel算子?

Sobel算子與Prewitt比較類似,但是它比Prewitt算子要好一些。

x方向的Sobel算子為

y方向的Sobel算子為

python代碼只需要將上面代碼中的Prewitt算子改成Sobel算子即可。

# x方向的Sobel算子 suanzi_x = np.array([[-1, 0, 1],[ -2, 0, 2],[ -1, 0, 1]])# y方向的Sobel算子 suanzi_y = np.array([[-1,-2,-1],[ 0, 0, 0],[ 1, 2, 1]])

?Sobel算子?的結(jié)果如下圖所示

上方:左圖為原圖像,右圖為x方向?qū)?shù)圖像

下方:左圖為y方向?qū)?shù)圖像,右圖為梯度圖像

從圖中看出,比較Prewitt算子和Sobel算子,Sobel算子稍微減少了一點噪聲,但噪聲還是比較多的。


?近似二階導(dǎo)數(shù)的Laplace算子?

Laplace算子是一個二階導(dǎo)數(shù)的算子,它實際上是一個x方向二階導(dǎo)數(shù)和y方向二階導(dǎo)數(shù)的和的近似求導(dǎo)算子。

實際上,Laplace算子是通過Sobel算子推導(dǎo)出來的。

Laplace算子為

Laplace還有一種擴展算子為

為了不再重復(fù)造輪子,這次我們運用scipy庫中signal模塊的convolve()方法來計算圖像卷積。

convolve()的第一個參數(shù)是原圖像矩陣,第二個參數(shù)為卷積算子,然后指定關(guān)鍵字參數(shù)mode="same"(輸出矩陣大小和原圖像矩陣相同)。

import numpy as np from PIL import Image import matplotlib.pyplot as plt import matplotlib.cm as cm import scipy.signal as signal # 導(dǎo)入sicpy的signal模塊# Laplace算子 suanzi1 = np.array([[0, 1, 0], [1,-4, 1],[0, 1, 0]])# Laplace擴展算子 suanzi2 = np.array([[1, 1, 1],[1,-8, 1],[1, 1, 1]])# 打開圖像并轉(zhuǎn)化成灰度圖像 image = Image.open("pika.jpg").convert("L") image_array = np.array(image)# 利用signal的convolve計算卷積 image_suanzi1 = signal.convolve2d(image_array,suanzi1,mode="same") image_suanzi2 = signal.convolve2d(image_array,suanzi2,mode="same")# 將卷積結(jié)果轉(zhuǎn)化成0~255 image_suanzi1 = (image_suanzi1/float(image_suanzi1.max()))*255 image_suanzi2 = (image_suanzi2/float(image_suanzi2.max()))*255# 為了使看清邊緣檢測結(jié)果,將大于灰度平均值的灰度變成255(白色) image_suanzi1[image_suanzi1>image_suanzi1.mean()] = 255 image_suanzi2[image_suanzi2>image_suanzi2.mean()] = 255# 顯示圖像 plt.subplot(2,1,1) plt.imshow(image_array,cmap=cm.gray) plt.axis("off") plt.subplot(2,2,3) plt.imshow(image_suanzi1,cmap=cm.gray) plt.axis("off") plt.subplot(2,2,4) plt.imshow(image_suanzi2,cmap=cm.gray) plt.axis("off") plt.show()

?

結(jié)果如下圖

其中上方為原圖像

下方:左邊為Laplace算子結(jié)果,右邊為Laplace擴展算子結(jié)果

從結(jié)果可以看出,laplace算子似乎比前面兩個算子(prewitt算子和Sobel算子)要好一些,噪聲減少了,但還是比較多。

而Laplace擴展算子的結(jié)果看上去比Laplace的結(jié)果少一些噪聲。


?降噪后進行邊緣檢測?

?為了獲得更好的邊緣檢測效果,可以先對圖像進行模糊平滑處理,目的是去除圖像中的高頻噪聲。

python程序如下

首先用標準差為5的5*5高斯算子對圖像進行平滑處理,然后利用Laplace的擴展算子對圖像進行邊緣檢測。

import numpy as np from PIL import Image import matplotlib.pyplot as plt import matplotlib.cm as cm import scipy.signal as signal# 生成高斯算子的函數(shù) def func(x,y,sigma=1):return 100*(1/(2*np.pi*sigma))*np.exp(-((x-2)**2+(y-2)**2)/(2.0*sigma**2))# 生成標準差為5的5*5高斯算子 suanzi1 = np.fromfunction(func,(5,5),sigma=5)# Laplace擴展算子 suanzi2 = np.array([[1, 1, 1],[1,-8, 1],[1, 1, 1]])# 打開圖像并轉(zhuǎn)化成灰度圖像 image = Image.open("pika.jpg").convert("L") image_array = np.array(image)# 利用生成的高斯算子與原圖像進行卷積對圖像進行平滑處理 image_blur = signal.convolve2d(image_array, suanzi1, mode="same")# 對平滑后的圖像進行邊緣檢測 image2 = signal.convolve2d(image_blur, suanzi2, mode="same")# 結(jié)果轉(zhuǎn)化到0-255 image2 = (image2/float(image2.max()))*255# 將大于灰度平均值的灰度值變成255(白色),便于觀察邊緣 image2[image2>image2.mean()] = 255# 顯示圖像 plt.subplot(2,1,1) plt.imshow(image_array,cmap=cm.gray) plt.axis("off") plt.subplot(2,1,2) plt.imshow(image2,cmap=cm.gray) plt.axis("off") plt.show()

?

結(jié)果如下圖

從圖中可以看出,經(jīng)過降噪處理后,邊緣效果較為明顯。


?

參考列表

1. 《python計算機視覺編程》?

2. 網(wǎng)絡(luò)(感謝百度,感覺網(wǎng)絡(luò)上分享知識的網(wǎng)友)


實際上,一些現(xiàn)成的Python庫已經(jīng)對邊緣檢測過程進行了封裝,效果和效率更為出色。

文中以自己的python代碼進行邊緣檢測,實際上是想對實際過程有更好的認識和了解

?

轉(zhuǎn)載于:https://www.cnblogs.com/smallpi/p/4555854.html

總結(jié)

以上是生活随笔為你收集整理的python计算机视觉2:图像边缘检测的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

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