拉普拉斯銳化
[原理及Python實現(xiàn)](含拉氏標定、拉普拉斯標定)
原創(chuàng)文章;轉載請注明出處:?? Sylvan Ding
銳化處理的主要目的是突出灰度的過度部分。圖像銳化的用途多種多樣,應用范圍從電子印刷和醫(yī)學成像到工業(yè)檢測和軍事系統(tǒng)的制導等。利用圖像微分可以增強邊緣和其他突變(如噪聲),而削弱灰度變化緩慢的區(qū)域。
定義
對于一維函數(shù),其一階微分的定義如下(差值):(為了與二維函數(shù)圖像的微分保持一致,這里使用了偏導符號)
? f ? x = f ( x + 1 ) ? f ( x ) \frac{\partial f}{\partial x} = f(x+1)-f(x) ?x?f?=f(x+1)?f(x)
由此,不難推出其二階微分(差分):
? 2 f ? x 2 = f ( x + 1 ) ? f ( x ? 1 ) + 2 f ( x ) \frac{\partial ^2f}{\partial x^2} = f(x+1)-f(x-1)+2f(x) ?x2?2f?=f(x+1)?f(x?1)+2f(x)
由上式可知,一階微分需要"前瞻"一個值,而二階微分不僅需要"前瞻"、還需要"后瞻"才能算出。所以在分析二階微分的問題時,通常只考慮從第二個點到倒數(shù)第二個點的微分計算,以避免前一個點和下一個點不存在的情況。
對于二維函數(shù)圖像 f ( x , y ) f(x,y) f(x,y),其拉普拉斯算子定義為:
? 2 f = ? 2 f ? x 2 + ? 2 f ? y 2 \nabla^{2} f=\frac{\partial^{2} f}{\partial x^{2}}+\frac{\partial^{2} f}{\partial y^{2}} ?2f=?x2?2f?+?y2?2f?
在 x x x 方向和 y y y 方向上有:
? 2 f ? x 2 = f ( x + 1 , y ) + f ( x ? 1 , y ) ? 2 f ( x , y ) \frac{\partial^{2} f}{\partial x^{2}}=f(x+1, y)+f(x-1, y)-2 f(x, y) ?x2?2f?=f(x+1,y)+f(x?1,y)?2f(x,y)
? 2 f ? y 2 = f ( x , y + 1 ) + f ( x , y ? 1 ) ? 2 f ( x , y ) \frac{\partial^{2} f}{\partial y^{2}}=f(x, y+1)+f(x, y-1)-2 f(x, y) ?y2?2f?=f(x,y+1)+f(x,y?1)?2f(x,y)
故
? 2 f ( x , y ) = f ( x + 1 , y ) + f ( x ? 1 , y ) + f ( x , y + 1 ) + f ( x , y ? 1 ) ? 4 f ( x , y ) \nabla^{2} f(x, y)=f(x+1, y)+f(x-1, y)+f(x, y+1)+f(x, y-1)-4 f(x, y) ?2f(x,y)=f(x+1,y)+f(x?1,y)+f(x,y+1)+f(x,y?1)?4f(x,y)
核心思想
一階微分表征了在某個方向上灰度的變化率,而二階微分表征的是一階微分的變化情況。對于灰度值的緩慢變化(斜坡過渡),一階微分只能產(chǎn)生粗糙的邊緣,但二階微分可以形成"零交叉"(前后連個像素點間二階微分差值很大,切連線與坐標軸相交,產(chǎn)生零點),比一階微分更能反應出邊界,在邊緣檢測中發(fā)揮著更加重要的作用。
由上述分析知,二階微分在增強細節(jié)方面比一階微分好得多,是適合銳化圖像的立項特征,這就是拉普拉斯二階微分算子銳化圖像的核心思想。
構造拉普拉斯模版
拉普拉斯濾波通過濾波器模板(核)來實現(xiàn)。根據(jù)定義中對拉普拉斯算子的描述,不難得到:(模版1)
[ 0 1 0 1 ? 4 1 0 1 0 ] \begin{bmatrix}0 & 1 & 0 \\ 1& -4 &1 \\ 0& 1 &0 \end{bmatrix} ???010?1?41?010????
模版1
中四個角均為
0
0
0,沒有納入拉普拉斯算子的線性計算中,因為這樣構造出的模版只是在 x、y 坐標軸方向上求了二階微分,那么可以考慮向定義中拉普拉斯算子里加入
4
5
°
45^\circ
45°、
13
5
°
135^\circ
135° 的對角線方向的二階微分。
? 2 f ( x , y ) = f ( x ? 1 , y + 1 ) + f ( x + 1 , y + 1 ) + f ( x + 1 , y ? 1 ) + f ( x ? 1 , y ? 1 ) + f ( x + 1 , y ) + f ( x ? 1 , y ) + f ( x , y + 1 ) + f ( x , y ? 1 ) ? 8 f ( x , y ) \nabla^{2} f(x, y)=f(x-1, y+1)+f(x+1, y+1)+f(x+1, y-1)+f(x-1, y-1)+f(x+1, y)+f(x-1, y)+f(x, y+1)+f(x, y-1)-8 f(x, y) ?2f(x,y)=f(x?1,y+1)+f(x+1,y+1)+f(x+1,y?1)+f(x?1,y?1)+f(x+1,y)+f(x?1,y)+f(x,y+1)+f(x,y?1)?8f(x,y)
那么,將對角方向灰度變化納入銳化中的拉普拉斯擴展模版2
:
[ 1 1 1 1 ? 8 1 1 1 1 ] \begin{bmatrix} 1& 1 &1 \\ 1& -8 &1 \\ 1& 1 &1 \end{bmatrix} ???111?1?81?111????
銳化過程
拉普拉斯算子強調的是圖像中灰度的突變,并不強調灰度級緩慢變化的區(qū)域,將原圖像和拉普拉斯圖像疊加,可以增強邊界的灰度值,以實現(xiàn)銳化。
g ( x , y ) = f ( x , y ) ? [ ? 2 f ( x , y ) ] g(x, y)=f(x, y)-\left[\nabla^{2} f(x, y)\right] g(x,y)=f(x,y)?[?2f(x,y)]
其中, f ( x , y ) f(x,y) f(x,y) 為原圖, g ( x , y ) g(x,y) g(x,y)為銳化后所得到的圖像函數(shù)。
由于 ? 2 f ( x , y ) \nabla^{2} f(x, y) ?2f(x,y) 拉普拉斯圖像中既有負值也有正值,故在展示拉普拉斯圖像時,負值會截斷成灰度值 0,超過 255 的灰度值也會截斷成 255,所以需要標定,本質上是歸一化。
"卷積"過程中,為了避免產(chǎn)生黑邊,所以邊緣填充為鏡像,對應openCV中BORDER_REFLECT_101
.
二維卷積函數(shù) filter2D
cv.filter2D(src, ddepth, kernel[, dst[, anchor[, delta[, borderType]]]]) -> dst
Convolves an image with the kernel.
The function applies an arbitrary linear filter to an image. In-place operation is supported. When the aperture is partially outside the image, the function interpolates outlier pixel values according to the specified border mode.
The function does actually compute correlation, not the convolution:
dst ? ( x , y ) = ∑ 0 ≤ x ′ < ?kernel.cols? 0 ≤ y ′ < ?kernel.rows? kernel ? ( x ′ , y ′ ) ? src ? ( x + x ′ ? ?anchor.? x , y + y ′ ? ?anchor.y? ) \operatorname{dst}(x, y)=\sum_{\begin{array}{l} 0 \leq x^{\prime}<\text { kernel.cols } \\ 0 \leq y^{\prime}<\text { kernel.rows }\end{array} } \operatorname{kernel}\left(x^{\prime}, y^{\prime}\right) * \operatorname{src}\left(x+x^{\prime}-\text { anchor. } x, y+y^{\prime}-\text { anchor.y }\right) dst(x,y)=0≤x′<?kernel.cols?0≤y′<?kernel.rows??∑?kernel(x′,y′)?src(x+x′??anchor.?x,y+y′??anchor.y?)
That is, the kernel is not mirrored around the anchor point. If you need a real convolution, flip the kernel using flip and set the new anchor to (kernel.cols - anchor.x - 1, kernel.rows - anchor.y - 1)
.
Parameters:
- src: input image.
- dst: output image of the same size and the same number of channels as src.
- ddepth: desired depth of the destination image, if set to -1, it will keep the same as the input
- kernel: convolution kernel.
- anchor: default value (-1,-1) means that the anchor is at the kernel center.
- delta: optional value added to the filtered pixels before storing them in dst.
- borderType: pixel extrapolation method.
ddepth:
CV_8U (0…255)
CV_8S (-128…127)
CV_16U (0…65535)
CV_16S (-32768…32767)
…
C
is channel number, CV_8UC1 means 8 unsigned with a channel.
borderType:
cv2.BORDER_CONSTANT: It adds a constant colored border. The value should be given as a keyword argument
cv2.BORDER_REFLECT: The border will be mirror reflection of the border elements. Suppose, if image contains letters “abcdefg” then output will be “gfedcba|abcdefg|gfedcba“.
cv2.BORDER_REFLECT_101 or cv2.BORDER_DEFAULT: It does the same works as cv2.BORDER_REFLECT but with slight change. Suppose, if image contains letters “abcdefgh” then output will be “gfedcb|abcdefgh|gfedcba“.
cv2.BORDER_REPLICATE: It replicates the last element. Suppose, if image contains letters “abcdefgh” then output will be “aaaaa|abcdefgh|hhhhh“.
實驗
使用模版1
進行銳化的結果如下,從上到下依次為圖片編號1、2、3、4:
- 原圖
- 未標定的拉普拉斯圖像
- 標定的拉普拉斯圖像
- 拉普拉斯濾波后的圖像
使用模版2
進行銳化的結果如下:
不難發(fā)現(xiàn),模版2 比 模版1 效果更好。
代碼
import cv2
import numpy as np
import matplotlib.pyplot as plt
def Laplace(img, kernel):
des_8U = cv2.filter2D(img, -1, kernel=kernel, borderType=cv2.BORDER_DEFAULT)
des_16S = cv2.filter2D(img, ddepth=cv2.CV_16SC1, kernel=kernel, borderType=cv2.BORDER_DEFAULT)
g = img - des_16S
g[g<0] = 0
g[g>255] = 255
plt.figure(figsize=(10,14))
# origin, des_8U, des_16S, filtered
plt.subplot(221)
plt.imshow(img, cmap='gray')
plt.title('origin')
plt.subplot(222)
plt.imshow(des_8U, cmap='gray')
plt.title('des-8U')
plt.subplot(223)
plt.imshow(des_16S, cmap='gray')
plt.title('des-16S')
plt.subplot(224)
plt.imshow(g, cmap='gray')
plt.title('g')
plt.show()
img0 = 'moon.tif'
f = cv2.imread(img0, cv2.IMREAD_GRAYSCALE)
kernel1 = np.asarray([[0, 1, 0],
[1, -4, 1],
[0, 1, 0]])
Laplace(f, kernel1)
kernel2 = np.asarray([[1, 1, 1],
[1, -8, 1],
[1, 1, 1]])
Laplace(f, kernel2)
預備知識
文章來源:http://www.zghlxwxcb.cn/news/detail-409341.html
文章來源地址http://www.zghlxwxcb.cn/news/detail-409341.html
參考文獻
- 數(shù)字圖像處理:第3版,北京:電子工業(yè)出版社
- 圖像分割——線檢測——拉普拉斯標定(Matlab)
- 數(shù)據(jù)集下載地址
到了這里,關于拉普拉斯銳化[原理及Python實現(xiàn)](含拉氏標定、拉普拉斯標定)的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!