共计 4190 个字符,预计需要花费 11 分钟才能阅读完成。
提醒:本文最后更新于 2024-08-29 14:59,文中所关联的信息可能已发生改变,请知悉!
上周问题
可以看出还有很多单个噪声点残留,那么需要修改噪声定位的部分。经过调试发现,问题出在寻找 1:7 情况的部分。
改进代码
下面是修改后的代码:
# python 3.8
# utf-8
# follow 20211124 report
import cv2 as cv
import numpy as np
# 二维数组映射到一维
def _2d_2_1d(x, y):
if x == 0 and y == 0:
return int(0)
elif x == 0 and y == 1:
return int(1)
elif x == 0 and y == 2:
return int(2)
elif x == 1 and y == 2:
return int(3)
elif x == 2 and y == 2:
return int(4)
elif x == 2 and y == 1:
return int(5)
elif x == 2 and y == 0:
return int(6)
elif x == 1 and y == 0:
return int(7)
elif x == 1 and y == 1:
return int(8)
def _1d_2_2d(x):
if x == 0:
return 0, 0
elif x == 1:
return 0, 1
elif x == 2:
return 0, 2
elif x == 3:
return 1, 2
elif x == 4:
return 2, 2
elif x == 5:
return 2, 1
elif x == 6:
return 2, 0
elif x == 7:
return 1, 0
def division(_8):
result = [0] * 8
p1 = [_8[0][0], _8[0][1], _8[0][2], _8[1][2], _8[2][2], _8[2][1], _8[2][0],
_8[1][0]]
p = sorted(p1)
q = [abs(int(p[0]) - int(p[1])), abs(int(p[1]) - int(p[2])), abs(int(p[2]) - int(p[3])), abs(int(p[3]) - int(p[4])),
abs(int(p[4]) - int(p[5])), abs(int(p[5]) - int(p[6])), abs(int(p[6]) - int(p[7]))]
# 判断区分度
if max(q) < 10:
return result, False
max_index = q.index(max(q))
for i in range(0, max_index + 1):
for j in range(len(q)):
if p1[j] == p[i]:
result[j] = 1
for i in range(8):
if result[i] != 1:
result[i] = 2
return result, True
def find_best(a, x, y):
result = []
for i in range(3):
for j in range(3):
if (i, j) != (1, 1) and (i, j) != (x, y):
result.append(a[i][j])
d = [0] * 7
for i in range(7):
d[i] = abs(int(result[i]) - int(a[x][y]))
return result[d.index(min(d))]
def denoise_1_7(channel, flag, k):
"""
:param channel: 待检测通道
:param flag: 噪声标记
:param k: 多尺度指数
:return: 被找到的噪声个数
"""
x, y = channel.shape
sub_flag = 0
for i in range(1, x - 1):
for j in range(1, y - 1):
# 取出九宫格
a = [[0] * 3 for ix in range(3)]
for i0 in range(3):
for j0 in range(3):
a[i0][j0] = channel[i - 1 + i0][j - 1 + j0]
# 划分区域
div, div_flag = division(a)
if not div_flag:
continue
cnt = 0
for i0 in range(8):
if div[i0] == 1:
cnt += 1
if cnt == 1:
for i0 in range(8):
if div[i0] == 1:
x0, y0 = _1d_2_2d(i0)
if flag[i - 1 + x0][j - 1 + y0] == 1:
sub_flag += 1
channel[i - 1 + x0][j - 1 + y0] = find_best(a, x0, y0)
elif cnt == 7:
for i0 in range(8):
if div[i0] == 2:
x0, y0 = _1d_2_2d(i0)
if flag[i - 1 + x0][j - 1 + y0] == 1:
sub_flag += 1
channel[i - 1 + x0][j - 1 + y0] = find_best(a, x0, y0)
return channel, sub_flag
def denoise(noise, noise_flag, k):
"""
:param noise: 噪声图像
:param noise_flag: 噪声标记
:param k: 多尺度指数
:return: 修改后的噪声图像,被找到的噪声
"""
b_noise, g_noise, r_noise = cv.split(noise)
sub_flag = 0
b_noise, f = denoise_1_7(b_noise, noise_flag[0], k)
sub_flag += f
g_noise, f = denoise_1_7(g_noise, noise_flag[1], k)
sub_flag += f
r_noise, f = denoise_1_7(r_noise, noise_flag[2], k)
sub_flag += f
new_noise = cv.merge((b_noise, g_noise, r_noise))
return new_noise, sub_flag
def get_noise_flag(origin, noise):
"""
:param origin: Mat 原图
:param noise: Mat 噪声图
:return: flag 矩阵
"""
b_origin, g_origin, r_origin = cv.split(origin)
b_noise, g_noise, r_noise = cv.split(noise)
row, col = b_origin.shape
flag = np.zeros((3, row, col))
cnt_flag = 0
for i in range(row):
for j in range(col):
if b_origin[i][j] != b_noise[i][j]:
flag[0][i][j] = 1
cnt_flag += 1
if g_origin[i][j] != g_noise[i][j]:
flag[1][i][j] = 1
cnt_flag += 1
if r_origin[i][j] != r_noise[i][j]:
flag[2][i][j] = 1
cnt_flag += 1
return flag, cnt_flag
def main(origin, noise, k):
"""
:param origin: 原始标准图片路径
:param noise: 噪声图路径
:param k: 多尺度指数
:return:
"""
img_origin = cv.imread(origin, 1)
img_noise = cv.imread(noise, 1)
noise_flag, cnt_flag = get_noise_flag(img_origin, img_noise)
print(' 原噪声个数:', cnt_flag)
# new_noise, sub_flag = denoise(img_noise, noise_flag, 1)
# cv.imwrite('new.png', new_noise)
# print(sub_flag / cnt_flag)
noises = []
noises.append(img_noise)
for i in range(10):
new, sub_flag = denoise(noises[i], noise_flag, 1)
noises.append(new)
print('[' + str(i + 1) + ']', sub_flag / cnt_flag)
cv.imwrite('new.png', noises[9])
if __name__ == '__main__':
origin_addr = 'img.png'
noise_addr = 'img_1.png'
main(origin_addr, noise_addr, 1)
测试效果
原噪声个数:23363
[1] 0.7008517741728374
[2] 0.08813080511920558
[3] 0.029833497410435304
[4] 0.008988571673158413
[5] 0.006634421949235972
[6] 0.005906775670932671
[7] 0.004579891281085477
[8] 0.004494285836579207
[9] 0.004323074947566665
[10] 0.004066258614047853
原图:
噪声图:
处理图:
每个 3 * 3 区域内的单个噪声点几乎完全消除,但是在像素修改上存在不合理的情况,比如在图像的明显分界线上,像素互相侵蚀。
出现这样情况的原因如下图,在不考虑中心点(黄色)的情况下,设红色像素点是噪声,那么这个 3 * 3 矩阵,满足 1:7 的划分状态,我们肯定能定位出红色的噪声点,但是在修改噪声的时候,会取蓝色区域内最接近于红色值的像素值来赋给红色像素点。
由于降噪算法的核心就是根据原有的合理像素值猜测出噪声值本来的样子,那么在不考虑四个边界的像素点情况下,每个像素点都有与它联系最紧密的 8 邻域像素,我称它们为最佳关联点。
当猜测噪声点的原值的时候,最佳关联点对它的影响越大,则猜的越准,那么刚才的修改方法就不太合适:
- 如图所示,该修改方法使用的红色像素点的最佳关联点只有四个,还有三个非最佳关联点,如果这个红色点在四个角上的话,那么,会使用到的最佳关联点只有两个,非最佳关联点有五个
- 由于该噪声定位的方法与以前先定位加权,再修改的方式不同,所以我们不能保证蓝色像素点部分没有噪声,只是因为红色的噪声更突出,所以分出来 1:7 的状态,那么在修改的时候,不可避免的会使用到比非最佳关联点还要不合理的噪声点
正文完