基于python+openCV的中值滤波

先直接来一个3×3的吧

def median(src_img, filter_size, channels):
    # 首先,定义一个大小为9的0数组
    # list = [[0, 0, 0, 0, 0, 0, 0, 0, 0],
    #         [0, 0, 0, 0, 0, 0, 0, 0, 0],
    #         [0, 0, 0, 0, 0, 0, 0, 0, 0]]
    list = np.zeros([3, 9])
    # print(list[1][4])
    
    rows = src_img.shape[0]
    cols = src_img.shape[1]

    # list = [[1, 2, 3], [3, 1, 2]]
    # list[1].sort()
    # print(list[1])

    # 新建一张相同大小的空白黑色图像
    empty = np.zeros([rows, cols, channels], np.uint8)

    # 然后开始遍历
    # 首先遍历所有图像像素(边框除外)
    for i in range(1, rows - 1):
        for j in range(1, cols - 1):
            # 分通道取中值
            for c in range(0, channels):
                # 用于计数:计当前计到了九宫格的第几个像素
                count = 0
                for k in range(i - 1, i + 2):
                    for m in range(j - 1, j + 2):
                        list[c][count] = src_img[k, m, c]
                        count += 1
            # 所有的赋值都结束后,再分通道取中值,并将其赋给空白图像中的对应位置
            for r in range(0, channels):
                # print(list[r])
                list[r].sort()
                empty[i, j, r] = list[r][4]

    # print(empty)
    return empty

下面是具有一定普适性的改进版:

def median(src_img, filter_size):
    # 首先获取图像通道数
    # 注意,关于ndim的最为直接的理解方式是:要表示一个元素最少需要几个下标,ndim就是几
    if src_img.ndim == 2:
        channels = 1
    elif src_img.ndim == 3:
        channels = 3
    else:
        raise ValueError("the parameter must be a picture! It cannot be a picture!")

    pixel_list = np.zeros([channels, filter_size * filter_size])

    rows = src_img.shape[0]
    cols = src_img.shape[1]

    # 新建一张相同大小的空白黑色图像
    empty = np.zeros([rows, cols, channels], np.uint8)

    # 然后开始遍历
    # 首先遍历所有图像像素(边框除外)
    for i in range(int((filter_size - 1) / 2), rows - int((filter_size - 1) / 2)):
        for j in range(1, cols - int((filter_size - 1) / 2)):
            # 分通道取中值
            for c in range(0, channels):
                # 用于计数:计当前计到了九宫格的第几个像素
                count = 0
                for k in range(i - int((filter_size - 1) / 2), i + int((filter_size - 1) / 2 + 1)):
                    for m in range(j - int((filter_size - 1) / 2), j + int((filter_size - 1) / 2 + 1)):
                        pixel_list[c][count] = src_img[k, m, c]
                        count += 1
            # 所有的赋值都结束后,再分通道取中值,并将其赋给空白图像中的对应位置
            # 多通道
            if channels != 1:
                for r in range(0, channels):
                    # 按行排序
                    # 注意
                    pixel_list = np.sort(pixel_list, axis=1)
                    empty[i, j, r] = pixel_list[r][int((filter_size * filter_size - 1) / 2)]
            else:
                # 单通道
                empty[i, j] = pixel_list[int((filter_size * filter_size - 1) / 2)]
    # print(empty)
    return empty

if __name__ == "__main__":
    cv.namedWindow("src", cv.WINDOW_NORMAL)
    cv.namedWindow("see", cv.WINDOW_NORMAL)
    cv.namedWindow("see1", cv.WINDOW_NORMAL)
    pathname = "E://Computer_Version//resource//4.png"
    src_img = cv.imread(pathname)
    cv.imshow("src", src_img)
    cv.imshow("see", median(src_img, 5,3))
    # 与openCV自带函数进行对比
    cv.imshow("see1", cv.medianBlur(src_img, 3))
    cv.waitKey(0)
    cv.destroyAllWindows()

虽然效果不错,但是运行速度依旧堪忧,需要再多多改进

感谢大佬:[python,opencv]如何判断一副图片的通道数

你可能感兴趣的:(opencv,python,计算机视觉)