图像处理(一):高斯滤波
概念介绍
首先, 我们知道, 给定某个二维点坐标 𝐩=(
p
x
p_x
px,
p
y
p_y
py) , 一个center在点 𝐩 , 方差为
σ
2
\sigma^2
σ2的高斯分布, 离该点距离为 𝑑 的任意一点 𝐪 的概率分布为
N
(
q
)
=
exp
(
−
d
2
2
σ
2
)
\mathcal{N}(\mathbf q) =\exp({- \frac{d^{2}}{2\sigma^{2}} })
N(q)=exp(−2σ2d2)
对于一个图像
I
I
I,我们可以定义高斯滤波操作为
G
(
p
)
=
1
∑
q
∈
S
N
(
q
)
∑
q
∈
S
N
(
q
)
I
q
G(\mathbf p) = \frac{1}{\sum\limits_{q\in S}\mathcal{N}(\mathbf q)} \sum\limits_{q\in S} \mathcal{N} (\mathbf q)I_q
G(p)=q∈S∑N(q)1q∈S∑N(q)Iq
我们定义像素周围的像素集合
S
S
S为以像素点
p
\mathbf{p}
p为中心,边长为
2
n
+
1
2n+1
2n+1的正方形区域,其中
n
=
⌊
3
σ
⌋
n = \lfloor{3\sigma}\rfloor
n=⌊3σ⌋
应用
主要是图像后期去噪点,比如磨皮。
代码实现
图片
我们选取梵高的作品
一些工具函数
这个系列之后也可能用到,还是比较重要的
导入模块
from __future__ import print_function
import numpy as np
import matplotlib.pyplot as plt
from time import time
from skimage import io
from scipy import ndimage
%load_ext autoreload
%autoreload 2
%reload_ext autoreload
显示单张图片
def show_image(img, zoom=1.5):
dpi = 77
plt.figure(figsize=(img.shape[0]*zoom/dpi,img.shape[0]*zoom/dpi))
if len(img.shape) == 2:
img = np.repeat(img[:,:,np.newaxis],3,2)
plt.imshow(img, interpolation='nearest')
显示多张图片
def show_images(imglist, zoom=1, needs_encoding=False):
if type(imglist) is not list:
imglist = [imglist]
n = len(imglist)
first_img = imglist[0]
dpi = 77
plt.figure(figsize=(first_img.shape[0]*zoom*n/dpi,first_img.shape[0]*zoom*n/dpi))
for i in range(0,n):
img = imglist[i]
plt.subplot(1,n,i + 1)
plt.tight_layout()
plt.axis('off')
if len(img.shape) == 2:
img = np.repeat(img[:,:,np.newaxis],3,2)
plt.imshow(img, interpolation='nearest')
高斯滤波
# Parameters:
# im: rgb三通道图像
# sigma: 高斯分布的方差 (sigma^2)
def gaussian(im, sigma):
height, width,_ = im.shape
img_filtered = np.zeros([height, width, 3 ])
### generate the mask
### return img_filtered
gaussian_mask = np.zeros((7, 7))
for i in range(7):
for j in range(7):
gaussian_mask[i][j] = 1/(2*np.pi*sigma*sigma)*np.exp(-((i-3)*(i-3)+(j-3)*(j-3))/(2*sigma*sigma))
### 归一化
sum = 0
for i in range(7):
for j in range(7):
sum = sum + gaussian_mask[i][j]
for i in range(7):
for j in range(7):
gaussian_mask[i][j] = gaussian_mask[i][j] / sum
### filter
for i in range(height):
for j in range(width):
for h in range(7):
for w in range(7):
if i-3+h >= 0 and i-3+h < height and j-3+w >= 0 and j-3+w < width:
for channel in range(3):
img_filtered[i][j][channel] = img_filtered[i][j][channel] + im[i-3+h][j-3+w][channel]*gaussian_mask[h][w]
return img_filtered
import numpy as np
from PIL import Image
img = np.array(Image.open('data/poster.jpg'), dtype=np.float32)
img_filtered = np.asarray(gaussian(img, 3))
show_image(img_filtered.astype(np.uint8))