工作概述

思路

扫描全能王CamScanner 2021-12-29 21.59

  • 对于每个2*2的格子计算最大差异度$d_i$
  • 对于每个$33$的区域来说,都可以分出左上,右上,左下,右下,中间五个$22$格子(四个大格子,一个小格子),并将五个最大差异度全排列
  • 找出$max|d_i - d_j|$
  • 从此处分为两组
  • 若中间格子属于个数少的一组,则存在噪声,且噪声为重合点

代码示例

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
# utf-8
# python3.8
# note20211229

import cv2 as cv
import numpy as np


# 获取差异度
def get_differ_degree(array):
return max(array) - min(array)


def check_noise(_4x4):
position = ['null', 'leftup', 'rightup', 'rightduwn', 'leftduwn']
# 中心格子
d0 = get_differ_degree([_4x4[1][1], _4x4[1][2], _4x4[2][2], _4x4[2][1]])
# 左上
d1 = get_differ_degree([_4x4[0][0], _4x4[0][2], _4x4[2][2], _4x4[2][0]])
# 右上
d2 = get_differ_degree([_4x4[0][1], _4x4[0][3], _4x4[2][3], _4x4[2][1]])
# 右下
d3 = get_differ_degree([_4x4[1][1], _4x4[1][3], _4x4[3][3], _4x4[3][1]])
# 左下
d4 = get_differ_degree([_4x4[1][0], _4x4[1][2], _4x4[3][2], _4x4[3][0]])
differ_degree = [d0, d1, d2, d3, d4]
sorted_dd = sorted(differ_degree, reverse=False) # 升序
adjacent_differ_from_sorted_dd = [sorted_dd[1] - sorted_dd[0], sorted_dd[2] - sorted_dd[1], sorted_dd[3] - sorted_dd[2], sorted_dd[4] - sorted_dd[3]]
if max(adjacent_differ_from_sorted_dd) == 0:
return position[0]
else:
max_index = adjacent_differ_from_sorted_dd.index(max(adjacent_differ_from_sorted_dd))
if max_index == 1:
if sorted_dd[0] == d0:
return position[differ_degree.index(sorted_dd[1])]
elif sorted_dd[1] == d0:
return position[differ_degree.index(sorted_dd[0])]
elif max_index == 2:
if sorted_dd[3] == d0:
return position[differ_degree.index(sorted_dd[4])]
elif sorted_dd[4] == d0:
return position[differ_degree.index(sorted_dd[3])]
else:
return position[0]


def denoise(channel):
row, col = channel.shape
flag = np.zeros((row, col))
for i in range(0, row - 3):
for j in range(0, col - 3):
# 提取4x4的单元像素格
each_4x4_in_channel = np.zeros((4, 4))
for m in range(4):
for n in range(4):
each_4x4_in_channel[m][n] = channel[i + m][j + n]
# check noise
# position = ['null', 'leftup', 'rightup', 'rightduwn', 'leftduwn']
noise_position = check_noise(each_4x4_in_channel)
if noise_position == 'leftup':
flag[i + 1][j + 1] = 1
elif noise_position == 'rightup':
flag[i + 1][j + 2] = 1
elif noise_position == 'rightduwn':
flag[i + 2][j + 2] = 1
elif noise_position == 'leftduwn':
flag[i + 2][j + 1] = 1
for i in range(row):
for j in range(col):
if flag[i][j] == 1:
channel[i][j] = 0
return channel


def main(noise, new):
"""
:param noise: 原始图片路径
:param new: 噪声图片路径
:return: null
"""
img_noise = cv.imread(noise, 1)
b, g, r = cv.split(img_noise)
"""
b_row, b_col = b.shape
fp = open('b_o.csv', 'w')
for i in range(b_row):
for j in range(b_col):
print(b[i][j], file=fp, end='')
print(",", file=fp, end='')
print("", file=fp)
"""
b = denoise(b)
g = denoise(g)
r = denoise(r)

img_new = cv.merge((b, g, r))

cv.imwrite(new, img_new)




if __name__ == '__main__':
noise_addr = 'img_noise.png'
new_addr = 'img_new.png'
main(noise_addr, new_addr)

处理效果

img_noiseimg_new

由此观察到噪声点反而会被检测到的伪噪声包围

形成原因

比如,取最上方中最左边的点:

image-20220302225329301image-20220302225441922

处理前与处理后的数据如上图所示

取一组数据按算法计算:

img

以左下角的数据为例,这样得到的噪声确实是标黄的39,标蓝色的也是同理。

这样得到的结果将贴近图像边缘,近似重合。不过与“正确答案”已经很接近了,所以下一次工作的目标可以定在修正噪声定位。