图像处理20220213

71次阅读
没有评论

共计 5629 个字符,预计需要花费 15 分钟才能阅读完成。

提醒:本文最后更新于 2024-08-30 14:54,文中所关联的信息可能已发生改变,请知悉!

前一次的工作

改进 find_best

根据一段时间对于图像降噪的经验来看,总觉得上次的处理图怪怪的,虽然确实没有了所谓 1:7 的噪声区域,从结果来看似乎是正常的。但还是再调试了一下,发现确实有可改进之处

测试效果

原图:

图像处理 20220213

噪声图:

图像处理 20220213

处理图:

图像处理 20220213

结果分析

  • 这是当 k = 1 时,进行 10 次降噪之后的结果,从结果看,无明显 1:7 类型的噪声存在
  • 与上一次工作的处理图相比,降噪效果更好
  • 降噪在进行到第四次时,被处理掉的噪声比例已经明显降低
  • 第五次时,更低
  • 从第六次降噪完之后,就不再出现新减少的噪声

本次工作

对于前一次工作的成果进行进一步处理,使用 k = 2 作为多尺度指数进行降噪

代码示例

# python3.8
# utf-8

from denoise1 import main as dn1m
from denoise2 import main as dn2m

if __name__ == '__main__':
    # dn1m('img.png', 'img_1.png', 1)
    dn2m('img.png', 'img_2.png', 2)

调用 denoise2.py

# python 3.8
# utf-8

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, flag):
    p = a[x][y]
    neighborhood = []
    if flag[x - 1][y - 1] == 0:
        neighborhood.append(a[x - 1][y - 1])
    if flag[x - 1][y] == 0:
        neighborhood.append(a[x - 1][y])
    if flag[x - 1][y + 1] == 0:
        neighborhood.append(a[x - 1][y + 1])
    if flag[x][y + 1] == 0:
        neighborhood.append(a[x][y + 1])
    if flag[x + 1][y + 1] == 0:
        neighborhood.append(a[x + 1][y + 1])
    if flag[x + 1][y] == 0:
        neighborhood.append(a[x + 1][y])
    if flag[x + 1][y - 1] == 0:
        neighborhood.append(a[x + 1][y - 1])
    if flag[x][y - 1] == 0:
        neighborhood.append(a[x][y - 1])

    d = []
    for i in range(len(neighborhood)):
        d.append(abs(int(neighborhood[i]) - int(p)))
    if len(d) == 0:
        return p
    min_index = d.index(min(d))

    return neighborhood[min_index]

def find_noise(x, y, channel, flag, flag0, sub_flag):
    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 and flag0[i - 1 + x0][j - 1 + y0] == 0:
                            sub_flag += 1
                        flag0[i - 1 + x0][j - 1 + y0] = 1
            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 and flag0[i - 1 + x0][j - 1 + y0] == 0:
                            sub_flag += 1
                        flag0[i - 1 + x0][j - 1 + y0] = 1
    return flag0, sub_flag

def shrunk(channel, k):
    x, y = channel.shape
    result = np.zeros((k, k), dtype=type(channel))
    for i in range(k):
        for j in range(k):
            result0 = np.zeros((x // k, y // k))
            for m in range(0, x // k):
                for n in range(0, y // k):
                    if m * k + i < x and n * k + j < y:
                        result0[m][n] = channel[m * k + i][n * k + j]
            result[i][j] = result0
    return result

def merge_array(array, x, y, k):
    result = np.zeros((x, y))
    for i in range(k):
        for j in range(k):
            for m in range(x // k):
                for n in range(y // k):
                    result[m * k + i][n * k + j] = array[i][j][m][n]
    return result

def denoise_1_7(channel, flag, k):
    """
    :param channel: 待检测通道
    :param flag: 噪声标记
    :param k: 多尺度指数
    :return: 被找到的噪声个数
    """
    if k == 2:
        x, y = channel.shape
        flag0 = np.zeros((k, k), dtype=type(channel))
        sub_flag = 0
        shrunk_channel = shrunk(channel, k)
        for i in range(k):
            for j in range(k):
                sx, sy = shrunk_channel[0][0].shape
                flag00 = np.zeros((sx, sy))
                flag00, sub_flag = find_noise(sx, sy, shrunk_channel[i][j], flag, flag00, sub_flag)
                flag0[i][j] = flag00

                for m in range(1, sx - 1):
                    for n in range(1, sy - 1):
                        if flag[m * k + i][n * k + j] == 1:
                            shrunk_channel[i][j][m][n] = find_best(shrunk_channel[i][j], m, n, flag00)

        # flag0 = merge_array(flag0, x, y, k)
        channel = merge_array(shrunk_channel, x, y, k)
        '''
        for i in range(1, x - 1):
            for j in range(1, y - 1):
                if flag[i][j] == 1:
                    channel[i][j] = find_best(channel, i, j, flag0)
        '''
        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)

    noises = [img_noise]
    for i in range(10):
        new, sub_flag = denoise(noises[i], noise_flag, k)
        noises.append(new)
        print('[' + str(i + 1) + ']', sub_flag / cnt_flag)

    cv.imwrite('new.png', noises[9])

if __name__ == '__main__':
    origin_addr = 'img_1.png'
    noise_addr = 'img_2.png'
    main(origin_addr, noise_addr, 2)

结果

 原噪声个数:21447
[1] 0.02802256725882408
[2] 0.0180444817456987
[3] 0.017997855177880356
[4] 0.017997855177880356

图像处理 20220213

结果分析

原噪声个数

原噪声个数与预期不符。这是因为噪声检测程序是利用原图与 k = 1 时得到的图片比对得出噪声,而大部分在 k = 1 时被修改的噪声不可能准确的还原为原值(而是利用附近的非噪声值代替),所以在 k = 2 时,比对所得的噪声个数会比预期多很多,所以噪声个数失去了参考价值

降噪比

由于上述噪声个数的原因,降噪比也只能用做降噪是否彻底的参考(即,该数值稳定后,降噪完成)

降噪效果

下图为 k = 1 的降噪图,比对上图(k = 2 降噪图)发现,前一次残留的连在一起的噪声几乎都被去除;只在图像的内部残留零星的单个噪声点,这可以再次利用 k = 1 来解;而图像的边界的降噪效果仍然不好,由于 k = 2 时会丢失更多的信息,所以,效果会比 k = 1 时要差

图像处理 20220213

正文完
 0
icvuln
版权声明:本站原创文章,由 icvuln 于2022-02-13发表,共计5629字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
评论(没有评论)