实验思路代码有很多不完善之处,仅供学习参考
如果同是NKU2021人工智能导论的同学,可以跳过这篇博客,因为会等到实验截止之后笔者才会将实验的具体代码补全。
实验中待处理的图片(sample):
生成的噪声图片:
局部均值滤波器恢复后的图片:
主要是补写两部分代码:
主要噪声及去噪方法的介绍
生成噪声图像:noise_mask_image
根据实验给出的noise_ratio
描述,noise_ratio[i]
分别表示任意一行的像素点的第i
个通道受损的数量在该行所有像素点的数量的比例。
根据实验描述,可知此方式生成的噪声是属于均匀噪声,在接下来的restore_image
中要设计一种算法尽可能来恢复图片
恢复噪声图像:restore_image
笔者对于均匀噪声恢复的想法主要还是对于像素点周围区域中有效像素点求均值的方式来进行恢复。
此方法比较简陋,会损失一部分图像的细节。对于这种方法,还想了一种改进的措施,即根据区域内有效像素点到中心待恢复点的欧氏距离作为权重,求加权平均值作为待恢复像素点的对应通道的值,但是这种方法好像想过并不明显?对于好几张图片,笔者均值用了两种算法,发现直接求均值的方式反而恢复效果更好。
noise_mask_image
#在实验截止后笔者在将代码补全
def noise_mask_image(img, noise_ratio=[0.8, 0.4, 0.6]):
"""
根据题目要求生成受损图片
:param img: cv2 读取图片,而且通道数顺序为 RGB
:param noise_ratio: 噪声比率,类型是 List,,内容:[r 上的噪声比率,g 上的噪声比率,b 上的噪声比率]
默认值分别是 [0.8,0.4,0.6]
:return: noise_img 受损图片, 图像矩阵值 0-1 之间,数据类型为 np.array,
数据类型对象 (dtype): np.double, 图像形状:(height,width,channel),通道(channel) 顺序为RGB
"""
# 受损图片初始化
noise_img = None
# -------------实现受损图像答题区域-----------------
if noise_ratio[0] <= 1 and noise_ratio[1] <= 1 and noise_ratio[2] <= 1:
noise_img = np.copy(img)
rows = img.shape[0]
cols = img.shape[1]
for row in range(rows):
#分别随机生成三个通道需要损坏的像素点
list_R = random.sample(range(cols), int(cols * noise_ratio[0]))
list_G = random.sample(range(cols), int(cols * noise_ratio[1]))
list_B = random.sample(range(cols), int(cols * noise_ratio[2]))
#分别损坏三个通道的像素点
for i in range(int(cols * noise_ratio[0])):
noise_img[row][list_R[i]][0] = 0.0
for j in range(int(cols * noise_ratio[1])):
noise_img[row][list_G[j]][1] = 0.0
for k in range(int(cols * noise_ratio[2])):
noise_img[row][list_B[k]][2] = 0.0
# -----------------------------------------------
return noise_img
restore_image
#在实验截止之后笔者再将代码补全
def restore_image(noise_img, size=4):
"""
使用 你最擅长的算法模型 进行图像恢复。
:param noise_img: 一个受损的图像
:param size: 输入区域半径,长宽是以 size*size 方形区域获取区域, 默认是 4
:return: res_img 恢复后的图片,图像矩阵值 0-1 之间,数据类型为 np.array,
数据类型对象 (dtype): np.double, 图像形状:(height,width,channel), 通道(channel) 顺序为RGB
"""
# 恢复图片初始化,首先 copy 受损图片,然后预测噪声点的坐标后作为返回值。
res_img = np.copy(noise_img)
# 获取噪声图像
noise_mask = get_noise_mask(noise_img)
# -------------实现图像恢复代码答题区域----------------------------
rows = res_img.shape[0]
cols= res_img.shape[1]
for chan in range(0,3):
for row in range(0, rows):
for col in range(0, cols):
#该像素点的chan通道受损
if noise_mask[row][col][chan] == 0:
sum = 0.0 #计算有效点通道值之和
num = 0 #该区域内有效点的个数
for x in range(max(row - size, 0), min(row + size + 1, rows)):
for y in range(max(col - size, 0), min(col + size + 1, cols)):
if noise_mask[x][y][chan] != 0:
sum += noise_img[x][y][chan]
num = num + 1
#如果没有无受损节点,
while num == 0:
size_large = copy.deepcopy(size)
size_large = size_large + 1 #扩大搜索范围
for x in range(max(row - size_large, 0), min(row + size_large + 1, rows)):
for y in range(max(col - size_large, 0), min(col + size_large + 1, cols)):
if noise_mask[x][y][chan] != 0:
sum += noise_img[x][y][chan]
num += 1
res_img[row][col][chan] = sum / num #计算范围内有效点通道值的平均值
#目前res_img变成了经过预处理的图片了
#此时再使用多元线性回归方法
for chan in range(0, 3):
for row in range(rows):
for col in range(cols):
#处理R通道
if noise_mask[row, col, chan] != 0:
continue
row_min = max(row - size, 0)
row_max = min(row + size + 1, rows)
col_min = max(row - size, 0)
col_max = min(col + size + 1, cols)
x_train = []
y_train = []
for x in range(row_min, row_max):
for y in range(col_min, col_max):
if x == row and y == col:
continue
x_train.append([x, y])
y_train.append([res_img[x, y, chan]])
if x_train == []:
continue
print(row, col, chan)
Reg = LinearRegression()
Reg.fit(x_train, y_train)
res_img[row, col, chan] = Reg.predict([[row, col]])
# ---------------------------------------------------------------
return res_img