图像处理20210606

292次阅读
没有评论

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

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

新的去噪方法

选取 3X3 噪声点

中心点为 C,周围八个点分别是 A1~A8

处理中心点 C

对九个点进行不考虑位置的区域划分,再去掉中心点 C,对其余八个点进行不考虑位置的划分,若两次划分有明显的变化,那么说明中心点为噪声点。

如果中心点 C 为噪声,那么就在八邻域中找到与中心点最为接近的点的值,赋给中心点 C

处理八邻域

将九个点全排列,分成两个区域,然后搜索每个点,如果该点没有与所在区域的其他点相邻,那么就将它的噪声指数加一

效果

图像处理 20210606

下面尝试用 opencv 中的 canny 算子检测噪声图和处理图(去噪后)的效果:

图像处理 20210606

图像处理 20210606

代码示例

python# python3.8
# utf-8
"""
1. 找出噪声点:新划分方法
    标记次数
2. 修改
    找最接近的未标记过的点
"""
import cv2 as cv
import numpy as np

threshold = 1

class PixelChannel:
    def __init__(self, channel, noise, row, col):
        self.noise = noise
        self.channel = channel
        self.row = row
        self.col = col

class Part:
    def __init__(self, x, y, area):
        self.x = x
        self.y = y
        self.area = area

# 建立像素通道类
def create_pixel_channel(img_channel):
    (row, col) = img_channel.shape
    result = PixelChannel(img_channel, noise_check(img_channel), row, col)
    return result

# 一维数组映射到二维
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
    elif x == 8:
        return 1, 1

# 二维数组映射到一维
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 division1(_3x3):
    result = [0] * 9
    p1 = [_3x3[0][0], _3x3[0][1], _3x3[0][2], _3x3[1][2], _3x3[2][2], _3x3[2][1], _3x3[2][0],
          _3x3[1][0], _3x3[1][1]]
    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])), abs(int(p[7]) - int(p[8]))]
    # 判断区分度
    if max(q) < 10:
        return result, False
    max_index = q.index(max(q))
    for i in range(0, max_index + 1):
        result[p1.index(p[i])] = 1
    for i in range(9):
        if result[i] != 1:
            result[i] = 2
    return result, True

# 去除 del_num 号元素,del_num:0~8
def division2(_3x3, del_num):
    p1 = [_3x3[0][0], _3x3[0][1], _3x3[0][2], _3x3[1][2], _3x3[2][2], _3x3[2][1], _3x3[2][0],
          _3x3[1][0], _3x3[1][1]]
    p2 = []
    for i in range(9):
        if i == del_num:
            continue
        p2.append(p1[i])
    result = [0] * 9

    p = sorted(p2)
    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]) - p[7])]
    # 判断区分度
    if max(q) < 10:
        return result, False
    max_index = q.index(max(q))
    for i in range(0, max_index + 1):
        result[p1.index(p[i])] = 1
    for i in range(8):
        if result[i] != 1:
            result[i] = 2
    result[del_num] = 0
    return result, True

# 搜索八邻域像素点是否合理 num:0~7
def check_8area(_8area, part, num):
    x, y = _1d_2_2d(num)
    if 0 <= x-1 <= 2 and 0 <= y-1 <= 2 and part[_2d_2_1d(x-1, y-1)] == part[num]:
        pass
    elif 0 <= x-1 <= 2 and 0 <= y <= 2 and part[_2d_2_1d(x-1, y)] == part[num]:
        pass
    elif 0 <= x-1 <= 2 and 0 <= y+1 <= 2 and part[_2d_2_1d(x-1, y+1)] == part[num]:
        pass
    elif 0 <= x <= 2 and 0 <= y+1 <= 2 and part[_2d_2_1d(x, y+1)] == part[num]:
        pass
    elif 0 <= x+1 <= 2 and 0 <= y+1 <= 2 and part[_2d_2_1d(x+1, y+1)] == part[num]:
        pass
    elif 0 <= x+1 <= 2 and 0 <= y <= 2 and part[_2d_2_1d(x+1, y)] == part[num]:
        pass
    elif 0 <= x+1 <= 2 and 0 <= y-1 <= 2 and part[_2d_2_1d(x+1, y-1)] == part[num]:
        pass
    elif 0 <= x <= 2 and 0 <= y-1 <= 2 and part[_2d_2_1d(x, y-1)] == part[num]:
        pass
    else:
        return False
    return True

def noise_check(img_channel):
    (row, col) = img_channel.shape
    result = [[0] * col for i in range(row)]
    for i in range(1, row - 1):
        for j in range(1, col - 1):
            _3X3 = [[0] * 3 for i in range(3)]
            _3X3[0][0] = img_channel[i - 1][j - 1]
            _3X3[0][1] = img_channel[i - 1][j]
            _3X3[0][2] = img_channel[i - 1][j + 1]
            _3X3[1][2] = img_channel[i][j + 1]
            _3X3[2][2] = img_channel[i + 1][j + 1]
            _3X3[2][1] = img_channel[i + 1][j]
            _3X3[2][0] = img_channel[i + 1][j - 1]
            _3X3[1][0] = img_channel[i][j - 1]
            _3X3[1][1] = img_channel[i][j]
            # 不考虑位置
            part1, flag1 = division1(_3X3)
            # 如果在不去除点的情况下,不需要划分,那么就跳过
            if not flag1:
                continue
            # 判断中心点是否合群
            part_del_c, flag_del_c = division2(_3X3, 8)
            # 如果去掉中心点后可划分,那么比较两种划分
            if flag_del_c:
                cnt = 0
                for m in range(9):
                    if part_del_c[m] != 0 and part1[m] != part_del_c[m]:
                        cnt += 1
                if cnt >= 1:
                    x, y = _1d_2_2d(9-1)
                    result[i - 1 + x][j - 1 + y] += 1
            # 如果不可划分,那么中心点为可能的噪声
            else:
                x, y = _1d_2_2d(9 - 1)
                result[i - 1 + x][j - 1 + y] += 1
            # 搜索其余八邻域像素点是否合理
            for k in range(8):
                if not check_8area(_3X3, part1, k):
                    x, y = _1d_2_2d(k)
                    result[i - 1 + x][j - 1 + y] += 1
    return result

# 不考虑缩小二分之一图像
def mark(pixel_channel):
    for i in range(pixel_channel.row):
        for j in range(pixel_channel.col):
            if pixel_channel.noise[i][j] >= threshold:
                pixel_channel.channel[i][j] = find_best(pixel_channel, i, j)
    return pixel_channel

# 找到最合适的值
def find_best(pixel_channel, x, y):
    p = pixel_channel.channel[x][y]
    # 建立领域列表
    neighborhood = []
    if pixel_channel.row > x - 1 >= 0 and pixel_channel.col > y - 1 >= 0 and pixel_channel.noise[x - 1][y - 1] < threshold:
        neighborhood.append(pixel_channel.channel[x - 1][y - 1])
    if pixel_channel.row > x - 1 >= 0 and pixel_channel.col > y >= 0 and pixel_channel.noise[x - 1][y] < threshold:
        neighborhood.append(pixel_channel.channel[x - 1][y])
    if pixel_channel.row > x - 1 >= 0 and pixel_channel.col > y + 1 >= 0 and pixel_channel.noise[x - 1][y + 1] < threshold:
        neighborhood.append(pixel_channel.channel[x - 1][y + 1])
    if pixel_channel.row > x >= 0 and pixel_channel.col > y + 1 >= 0 and pixel_channel.noise[x][y + 1] < threshold:
        neighborhood.append(pixel_channel.channel[x][y + 1])
    if pixel_channel.row > x + 1 >= 0 and pixel_channel.col > y + 1 >= 0 and pixel_channel.noise[x + 1][y + 1] < threshold:
        neighborhood.append(pixel_channel.channel[x + 1][y + 1])
    if pixel_channel.row > x + 1 >= 0 and pixel_channel.col > y >= 0 and pixel_channel.noise[x + 1][y] < threshold:
        neighborhood.append(pixel_channel.channel[x + 1][y])
    if pixel_channel.row > x + 1 >= 0 and pixel_channel.col > y - 1 >= 0 and pixel_channel.noise[x + 1][y - 1] < threshold:
        neighborhood.append(pixel_channel.channel[x + 1][y - 1])
    if pixel_channel.row > x >= 0 and pixel_channel.col > y - 1 >= 0 and pixel_channel.noise[x][y - 1] < threshold:
        neighborhood.append(pixel_channel.channel[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 repair(pixel_channel, half_channel):
    # 左上角
    for i in range(half_channel[0].row):
        for j in range(half_channel[0].col):
            if half_channel[0].noise[i][j] >= threshold:
                pixel_channel.noise[i * 2][j * 2] += half_channel[0].noise[i][j]

    # 右上角
    for i in range(half_channel[1].row):
        for j in range(half_channel[1].col):
            if half_channel[1].noise[i][j] >= threshold:
                pixel_channel.noise[i * 2][j * 2 + 1] += half_channel[1].noise[i][j]

    # 左下角
    for i in range(half_channel[2].row):
        for j in range(half_channel[2].col):
            if half_channel[2].noise[i][j] >= threshold:
                pixel_channel.noise[i * 2 + 1][j * 2] += half_channel[2].noise[i][j]

    # 右下角
    for i in range(half_channel[3].row):
        for j in range(half_channel[3].col):
            if half_channel[3].noise[i][j] >= threshold:
                pixel_channel.noise[i * 2 + 1][j * 2 + 1] += half_channel[3].noise[i][j]

    for i in range(pixel_channel.row):
        for j in range(pixel_channel.col):
            if pixel_channel.noise[i][j] >= threshold:
                pixel_channel.channel[i][j] = find_best(pixel_channel, i, j)

    return pixel_channel

def main():
    # 图像地址
    img_address = "img_noise.png"
    # 以 BGR 方式读入图像
    img = cv.imread(img_address, 1)
    cv.imshow("img_noise.png", img)
    # 通道分离
    channel_b, channel_g, channel_r = cv.split(img)
    # 建立像素通道类
    b = create_pixel_channel(channel_b)
    g = create_pixel_channel(channel_g)
    r = create_pixel_channel(channel_r)
    # 缩小二分之一
    # half_b = [half_1(b), half_2(b), half_3(b), half_4(b)]
    # half_g = [half_1(g), half_2(g), half_3(g), half_4(g)]
    # half_r = [half_1(r), half_2(r), half_3(r), half_4(r)]

    fp = open('b.noise.csv', 'w')
    for i in range(b.row):
        for j in range(b.col):
            print(b.noise[i][j], file=fp, end='')
            print(",", file=fp, end='')
        print("", file=fp)

    fp = open('b.pixel.csv', 'w')
    for i in range(b.row):
        for j in range(b.col):
            print(b.channel[i][j], file=fp, end='')
            print(",", file=fp, end='')
        print("", file=fp)

    # 不考虑二分之一图像
    new_img = cv.merge((mark(b).channel, mark(g).channel, mark(r).channel))

    # 考虑二分之一图像
    # new_img = cv.merge((repair(b, half_b).channel, repair(g, half_g).channel, repair(r, half_r).channel))

    cv.imwrite("denoised_img.png", new_img)
    cv.imshow("denoised_img.png", new_img)
    cv.waitKey()
    cv.destroyAllWindows()

if __name__ == '__main__':
    main()
正文完
 0
icvuln
版权声明:本站原创文章,由 icvuln 于2021-06-06发表,共计7320字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
评论(没有评论)