0%

几种常见的图像模糊处理

由于成像系统散焦、设备与物体的相对运动等因素易造成对成像系统影响,同时设备本身的缺陷或部分图像存在异物遮挡,也常常会导致图像质量无法达到理想化水平。

图像复原基本原理

图像退化是指图像受采集设备、光线等影响,在生成、传输过程中出现质量下降、信息丢失的现象。理论上,图像退化是图像主动或被动融入噪声。因此,图像x在噪声n的作用下,形成模糊图像y的数学表达如下:

其中, k称为点扩散函数,反应了光源成像系统对点源的解析能力。

通过图像复原技术,能够得到表达效果好、清晰度高的新图像。由上式可知,要想得到一个清晰的图像 ,通常需要对公式求解逆过程。因此,可视作对积分方程的逆变换。由于模糊核 k和噪声 n 未知,得到的 x不唯一。

图像退化和复原的基本流程如下图所示。受到各种因素的影响,清晰图像形成降质退化或模糊图像,分别研究退化模型和去模糊算法,进而对图像进行复原,生成清晰图像。常见的模糊图像类型包括高斯模糊、椒盐模糊、运动模糊等。

image-20210407193015944

高斯模糊图像

高斯模糊图像是依据高斯曲线对图像周围像素进行加权平均处理去掉图像细节使图像变得模糊。高斯模糊的数学公式如下:

其中,$h(x,y)$ 为高斯模糊函数, $\sigma$ 为标准差, x、y 为模糊点d 相对坐标。如图所示,中心点(0,0)附近坐标如下。

image-20210407193501743

椒盐模糊图像

椒盐噪声也称为脉冲噪声,表现为在图像中随机出现白/黑点。其中,未受到污染的像素仍会保留原始信息,不会影响原有图像的所有像素以及结构等信息。定义如下:

其中,a,b均为常数,表示像素值的取值范围。当 $p_a=0$或 $p_b=0$时,表示单极脉冲,当 $p_a\neq 0、p_b \neq 0$且 $p_a \approx p_b$时,称之为椒盐噪声。

运动模糊图像

运动模糊通常是物体与相机的相对运动引起的,其中最简单的就是匀速直线运动。用公式表示如下:

其中,d表示运动的距离, $\theta$表示运动方向。但是在实际生活中除速度、角度等变化外,运动模糊产生的原因往往比较复杂。

模糊图像仿真

原Lena图像下载,对于高斯模糊采取的模糊策略是模糊半径为2px;对于椒盐噪声采取的模糊策略是添加10%噪声;对于运动模糊,采取的模糊策略是模糊距离为10px;对于异物遮挡图像采取的模糊策略是用黑色遮挡30*30px的图像区域。

仿真结果

lena_dim

仿真代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
import os
import cv2
import pylab
import random
import numpy as np
from skimage import io
from matplotlib import pyplot as plt
from PIL import Image, ImageFilter, ImageDraw



def gauss_noise(image, mean=0, var=0.001):
'''
添加高斯噪声
mean : 均值
var : 方差
'''
image = np.array(image/255, dtype=float)
noise = np.random.normal(mean, var ** 0.5, image.shape)
out = image + noise
if out.min() < 0:
low_clip = -1.
else:
low_clip = 0.
out = np.clip(out, low_clip, 1.0)
out = np.uint8(out*255)
return out

#默认10%的椒盐噪声
def salt_and_pepper_noise(noise_img, proportion=0.1):
height, width, _ = noise_img.shape
num = int(height * width * proportion) # 多少个像素点添加椒盐噪声
for i in range(num):
w = random.randint(0, width - 1)
h = random.randint(0, height - 1)
if random.randint(0, 1) == 0:
noise_img[h, w] = 0
else:
noise_img[h, w] = 255
return noise_img


'''
生成运动模糊图像 模糊距离10px
'''

def motion_blur(image, degree=10, angle=45):
image = np.array(image)

# 这里生成任意角度的运动模糊kernel的矩阵, degree越大,模糊程度越高
M = cv2.getRotationMatrix2D((degree / 2, degree / 2), angle, 1)
motion_blur_kernel = np.diag(np.ones(degree))
motion_blur_kernel = cv2.warpAffine(motion_blur_kernel, M, (degree, degree))

motion_blur_kernel = motion_blur_kernel / degree
blurred = cv2.filter2D(image, -1, motion_blur_kernel)

# convert to uint8
cv2.normalize(blurred, blurred, 0, 255, cv2.NORM_MINMAX)
blurred = np.array(blurred, dtype=np.uint8)
return blurred

'''
生成马赛克图像
:param rgb_img
:param int x : 马赛克左顶点
:param int y: 马赛克左顶点
:param int w: 马赛克宽
:param int h: 马赛克高
:param int neighbor: 马赛克每一块的宽
'''

def do_mosaic(img, x, y, w, h, neighbor=9):
for i in range(0, h , neighbor):
for j in range(0, w , neighbor):
rect = [j + x, i + y]
color = img[i + y][j + x].tolist() # 关键点1 tolist
left_up = (rect[0], rect[1])
x2=rect[0] + neighbor - 1 # 关键点2 减去一个像素
y2=rect[1] + neighbor - 1
if x2>x+w:
x2=x+w
if y2>y+h:
y2=y+h
right_down = (x2,y2)
cv2.rectangle(img, left_up, right_down, color, -1) #替换为为一个颜值值
return img


def main():

#对before文件夹下的所有图片加入噪声,保存到after_salt文件夹中
# for root, dirs, files in os.walk(r"../dataset/before/"):
# for file in files:
# img = io.imread(os.path.join(root, file))
# noise_img = salt_and_pepper_noise(img)
# io.imsave(os.path.join('../dataset/after_salt/', file),noise_img)

#原lena图像路径
path='./lena512color.tiff'

#高斯模糊仿真
#im = Image.open(path)
#im = im.filter(ImageFilter.GaussianBlur(radius=2))
#im.save('./lena_gaussian.png')

img=cv2.imread(path)
lena_gauss=gauss_noise(img, mean=0,var=0.001)
cv2.imwrite('./lena_gauss.png',lena_gauss)


#椒盐噪声模糊仿真
img = io.imread(path)
lean_noise=salt_and_pepper_noise(img)
io.imsave('./lena_noise.png',lean_noise)

#运动模糊仿真
img = cv2.imread(path)
motion_img = motion_blur(img)
cv2.imwrite('./lena_motion.png',motion_img)

#遮挡图像仿真(图像裁剪)
im = Image.open(path)
draw = ImageDraw.Draw(im)
#裁剪矩形,左上角和右下角的坐标,像素用0填充
draw.rectangle((70, 100, 100, 130), fill=(0))
im.save('./lena_crop.png')

#马赛克图像仿真
img=cv2.imread(path)
lena_mosaic=do_mosaic(img, 200, 200, 200, 200, neighbor=10)
cv2.imwrite('./lena_mosaic.png',lena_mosaic)


if __name__ == '__main__':
main()
------------- THE END! THANKS! -------------