先直接来一个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]如何判断一副图片的通道数