虽然现在基本都是直接调用OpenCv,但为了某些要求(我可没说应付老师嗷)还需要自己实现。
本文:
1. 只完成了灰度图
2.没有做边缘检测
3. 效果肯定不用OpenCv好
原理:
自行百度
简述一下,以图像中一个点为核心圈出一个k阶矩阵,边界不考虑。然后对这个k阶矩阵求平均值,并将这个平均值赋给这个点。中值的字面意思,让每个点中值一次
不多bb上代码
首先导入需要的库
import cv2 import numpy as np from PIL import Image
这里opencv只负责读存图片
函数全部:
src要处理图像的路径, dst新图像存的路径, k 近邻中值滤波器
def MedianFilter(src, dst, k, padding=None): img = cv2.imread(src,cv2.IMREAD_GRAYSCALE) height, width = img.shape[:2] if not padding: kk = int((k - 1) / 2) if height - 1 - kk <= kk or width - 1 - kk <= kk: print("K大的离谱了!") return None new_arr = np.zeros((height, width), dtype="uint8") for i in range(height): for j in range(width): # 判断是否为边界 if i <= kk - 1 or i >= height - 1 - kk or j <= kk - 1 or j >= height - kk - 1: new_arr[i, j] = img[i, j] else: # 中值滤波 new_arr[i, j] = np.median(imarray[i - kk:i + kk + 1, j - kk:j + kk + 1]) new_img = Image.fromarray(new_arr) new_img.save(dst)
导入图像,求出宽高,简单的判断一下k是不是太大了
img = cv2.imread(src,cv2.IMREAD_GRAYSCALE)
height, width = img.shape[:2]
if not padding:
kk = int((k - 1) / 2)
if height - 1 - kk <= kk or width - 1 - kk <= kk:
print("K大的离谱了!")
return None
创建一个跟原图大小一样的空矩阵
new_arr = np.zeros((height, width), dtype="uint8")
开始循环,先判断一下是不是边界。如果是则照抄原图像,不是则进行中值滤波
np.median()求一个矩阵的平均值,最后 new_img = Image.fromarray(new_arr)把矩阵换为图像并保存
np.median(imarray[i - kk:i + kk + 1, j - kk:j + kk + 1])
for i in range(height):
for j in range(width):
# 判断是否为边界
if i <= kk - 1 or i >= height - 1 - kk or j <= kk - 1 or j >= height - kk - 1:
new_arr[i, j] = img[i, j]
else: # 中值滤波
new_arr[i, j] = np.median(imarray[i - kk:i + kk + 1, j - kk:j + kk + 1])
new_img = Image.fromarray(new_arr)
new_img.save(dst)
调用:
src = "dilireba.png"
dst = "dilireba2.png"
k = 3
MedianFilter(src, dst, k)
通俗易懂!