先直接来一个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 = 0for 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 = 1elif src_img.ndim == 3:channels = 3else: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 = 0for 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 emptyif __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]如何判断一副图片的通道数