SHARPENING (HIGHPASS) SPATIAL FILTERS


上一部分介绍的blur能够将图片模糊化, 这部分介绍的是突出图片的边缘的细节.

什么是边缘呢? 往往是像素点跳跃特别大的点, 这部分和梯度的概念是类似的, 可以如下定义图片的一阶导数而二阶导数:
∂ f ∂ x = f ( x + 1 ) − f ( x ) , ∂ 2 f ∂ x 2 = f ( x + 1 ) + f ( x − 1 ) − 2 f ( x ) . \frac{\partial f}{\partial x} = f(x+1) - f(x), \\ \frac{\partial^2 f}{\partial x^2} = f(x+1) + f(x-1) - 2f(x). xf=f(x+1)f(x),x22f=f(x+1)+f(x1)2f(x).
注: 或许用差分来表述更为贴切.

如上图实例所示, 描述了密度值沿着 x x x的变化, 一阶导数似乎能划分区域, 而二阶导数能够更好的“识别"边缘.

Laplacian

著名的laplacian算子:
Δ f = ∂ 2 f ∂ x 2 + ∂ 2 f ∂ y 2 , \Delta f = \frac{\partial^2 f}{\partial x^2} + \frac{\partial^2 f}{\partial y^2}, Δf=x22f+y22f,
在digital image这里:
Δ f = f ( x + 1 , y ) + f ( x − 1 , y ) + f ( x , y + 1 ) + f ( x , y − 1 ) − 4 f ( x , y ) . \Delta f = f(x+1, y) + f(x-1, y) + f(x, y+1) + f(x, y-1) - 4 f(x, y). Δf=f(x+1y)+f(x1,y)+f(x,y+1)+f(x,y1)4f(x,y).

这个算子用kernel表示是下面的(a), 但是在实际中也有(b, c, d)的用法, (b, d)额外用到了对角的信息, 注意到这些kernels都满足
∑ i j w i j = 0. \sum_{ij}w_{ij} = 0. ijwij=0.

最后
g ( x , y ) = f ( x , y ) + c [ ∇ 2 f ( x , y ) ] , g(x, y) = f(x, y) + c[\nabla^2 f(x, y)], g(x,y)=f(x,y)+c[2f(x,y)],
c = − 1 c=-1 c=1, 如果a, b, c = 1 c=1 c=1如果c, d.

kernel = -np.ones((3, 3))
kernel[1, 1] = 8
laps = cv2.filter2D(img, -1, kernel)
laps = (laps - laps.min()) / (laps.max() - laps.min()) * 255
img_pos = img + laps
img_neg = img - laps
fig, axes = plt.subplots(1, 4)
axes[0].imshow(img, cmap='gray')
axes[1].imshow(laps, cmap='gray')
axes[2].imshow(img_pos, cmap='gray')
axes[3].imshow(img_neg, cmap='gray')
plt.tight_layout()
plt.show()

kernel = np.ones((3, 3))
kernel[0, 0] = 0
kernel[0, 2] = 0
kernel[1, 1] = -4
kernel[2, 0] = 0
kernel[2, 2] = 0
laps = cv2.filter2D(img, -1, kernel)
laps = (laps - laps.min()) / (laps.max() - laps.min()) * 255
img_pos = img + laps
img_neg = img - laps
fig, axes = plt.subplots(1, 4)
axes[0].imshow(img, cmap='gray')
axes[1].imshow(laps, cmap='gray')
axes[2].imshow(img_pos, cmap='gray')
axes[3].imshow(img_neg, cmap='gray')
plt.tight_layout()
plt.show()

有点奇怪… 注意到我上面对laps进行标准化处理了, 如果没这个处理其实感觉是差不多的 c = 1 , − 1 c=1,-1 c=1,1.

UNSHARP MASKING AND HIGHBOOST FILTERING

注意到, 之前的box kernel,
w b o x ( s , t ) = 1 m n , w_{box}(s, t) = \frac{1}{mn}, wbox(s,t)=mn1,
考虑 3 × 3 3 \times 3 3×3的kernel size下:
w l a p = 9 ( E − ⋅ w b o x ) , w_{lap} = 9(E - \cdot w_{box}), wlap=9(Ewbox),
这里
E ( s , t ) = 0 , ∀ s ≠ 2 , t ≠ 2. E(s, t) =0, \forall s\not=2, t\not=2. E(s,t)=0,s=2,t=2.
故假设
g m a s k ( x , y ) = f ( x , y ) − f ˉ ( x , y ) , g_{mask} (x, y) = f(x, y) - \bar{f} (x, y), gmask(x,y)=f(x,y)fˉ(x,y),
其中 f ˉ \bar{f} fˉ是通过box filter 模糊的图像, 则
Δ f = 9 ⋅ g m a s k . \Delta f = 9 \cdot g_{mask}. Δf=9gmask.
g m a s k g_{mask} gmask也反应了细节边缘信息.

进一步定义
g ( x , y ) = f ( x , y ) + k g m a s k ( x , y ) . g(x, y) = f(x, y) + k g_{mask}(x, y). g(x,y)=f(x,y)+kgmask(x,y).

kernel = np.ones((3, 3)) / 9
img_mask = (img - cv2.filter2D(img, -1, kernel)) * 9
img_mask = (img_mask - img_mask.mean()) / (img_mask.max() - img_mask.min())
fig, ax = plt.subplots(1, 1)
ax.imshow(img_mask, cmap='gray')
plt.show()

First-Order Derivatives

最后再说说如何用一阶导数提取细节.

定义
M ( x , y ) = ∥ ∇ f ∥ = ( ∂ f ∂ x ) 2 + ( ∂ f ∂ y ) 2 . M(x, y) = \|\nabla f\| = \sqrt{(\frac{\partial f}{\partial x})^2 + (\frac{\partial f}{\partial y})^2}. M(x,y)=f=(xf)2+(yf)2 .
注: 也常常用 M ( x , y ) = ∣ ∂ f ∂ x ∣ + ∣ ∂ f ∂ y ∣ M(x, y) = |\frac{\partial f}{\partial x}| + |\frac{\partial f}{\partial y}| M(x,y)=xf+yf代替.

Roberts cross-gradient

把目标区域按照图(a)区分, Roberts cross-gradient采用如下方式定义:
∂ f ∂ x = z 9 − z 5 ,   ∂ f ∂ y = z 8 − z 6 , \frac{\partial f}{\partial x} = z_9 - z_5, \: \frac{\partial f}{\partial y} = z_8 - z_6, xf=z9z5,yf=z8z6,
即右下角的对角之差. 所以相应的kernel变如图(b, c)所示(其余部分为0, 3 × 3 3 \times 3 3×3).

注: 计算 M M M需要两个kernel做两次卷积.

Sobel operators

Sobel operators 则是
∂ f ∂ x = ( z 7 + 2 z 8 + z 9 ) − ( z 1 + 2 z 2 + z 3 ) ∂ f ∂ y = ( z 3 + 2 z 6 + z 9 ) − ( z 1 + 2 z 4 + z 7 ) , \frac{\partial f}{\partial x} = (z_7 + 2z_8 + z_9) - (z_1 + 2z_2 + z_3) \\ \frac{\partial f}{\partial y} = (z_3 + 2z_6 + z_9) - (z_1 + 2z_4 + z_7), xf=(z7+2z8+z9)(z1+2z2+z3)yf=(z3+2z6+z9)(z1+2z4+z7),
即如图(d, e)所示.

kernel = np.zeros((3, 3))
kernel[1, 1] = -1
kernel[2, 2] = 1
part1 = cv2.filter2D(img, -1, kernel)
kernel = np.zeros((3, 3))
kernel[1, 2] = -1
kernel[2, 1] = 1
part2 = cv2.filter2D(img, -1, kernel)
img_roberts = np.sqrt(part1 ** 2 + part2 ** 2)
part1 = cv2.Sobel(img, -1, dx=1, dy=0, ksize=3)
part2 = cv2.Sobel(img, -1, dx=0, dy=1, ksize=3)
img_sobel = np.sqrt(part1 ** 2 + part2 ** 2)
fig, axes = plt.subplots(1, 2)
axes[0].imshow(img_roberts, cmap='gray')
axes[1].imshow(img_sobel, cmap='gray')

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值