python+opencv 中值滤波器、最大值滤波器和最小值滤波器

2,463 阅读3分钟

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

中值滤波器

中值滤波器好说,opencv自带和函数就能直接用。在OpenCV中,实现中值滤波的函数是cv2.medianBlur(src, ksize)

  • src:图片位置
  • kszie:卷积核大小
import cv2 as cv

img = cv.imread('d:/Desktop/1.jpg')  # 我的桌面上有个1.jpg
res = cv.medianBlur(img, 5)
cv.imshow("original", img)
cv.imshow("result", res)
cv.waitKey(0)

image.png

中值滤波会取当前像素点及其周围临近像素点(一共有奇数个像素点)的像素值,将这些像素值排序,然后将位于中间位置的像素值作为当前像素点的像素值。

image.png

将其邻域设置为3×3大小,对其3×3邻域内像素点的像素值进行排序(升序降序均可),按升序排序后得到序列值为:[66,78,90,91,93,94,95,97,101]。在该序列中,处于中心位置(也叫中心点或中值点)的值是“93”,因此用该值替换原来的像素值78,作为当前点的新像素值,处理结果如下。

image.png

最大最小值滤波器

中值滤波器的原理上边讲到了,最大最小值滤波器就是把中值换成最大或者最小值。

opencv没有自带的最大最小值滤波器,所以需要自己写,定义函数的代码如下:

def original(i, j, k, ksize, img):
    # 找到矩阵坐标
    x1 = y1 = -ksize // 2
    x2 = y2 = ksize + x1
    temp = np.zeros(ksize * ksize)
    count = 0
    # 处理图像
    for m in range(x1, x2):
        for n in range(y1, y2):
            if i + m < 0 or i + m > img.shape[0] - 1 or j + n < 0 or j + n > img.shape[1] - 1:
                temp[count] = img[i, j, k]
            else:
                temp[count] = img[i + m, j + n, k]
            count += 1
    return temp

# 自定义最大值滤波器最小值滤波器
def max_min_functin(ksize, img, flag):
    img0 = copy.copy(img)
    for i in range(0, img.shape[0]):
        for j in range(2, img.shape[1]):
            for k in range(img.shape[2]):
                temp = original(i, j, k, ksize, img0)
                if flag == 0:   # 设置flag参数,如果是0就检测最大值,如果是1就检测最小值。
                    img[i, j, k] = np.max(temp)
                elif flag == 1:
                    img[i, j, k] = np.min(temp)
    return img

注意,上边这段代码写的比较简单,只能接受卷积核是方阵的情况。

实际操作一下:

import cv2 as cv
import numpy as np
import copy

def original(i, j, k, ksize, img):
    # 找到矩阵坐标
    x1 = y1 = -ksize // 2
    x2 = y2 = ksize + x1
    temp = np.zeros(ksize * ksize)
    count = 0
    # 处理图像
    for m in range(x1, x2):
        for n in range(y1, y2):
            if i + m < 0 or i + m > img.shape[0] - 1 or j + n < 0 or j + n > img.shape[1] - 1:
                temp[count] = img[i, j, k]
            else:
                temp[count] = img[i + m, j + n, k]
            count += 1
    return temp

# 自定义最大值滤波器最小值滤波器
def max_min_functin(ksize, img, flag):
    img0 = copy.copy(img)
    for i in range(0, img.shape[0]):
        for j in range(2, img.shape[1]):
            for k in range(img.shape[2]):
                temp = original(i, j, k, ksize, img0)
                if flag == 0:
                    img[i, j, k] = np.max(temp)
                elif flag == 1:
                    img[i, j, k] = np.min(temp)
    return img

img = cv.imread('d:/Desktop/1.png')
min_img = max_min_functin(3, copy.copy(img),1)
max_img = max_min_functin(3, copy.copy(img),0)
cv.imshow("original", img)
cv.imshow("min_img", min_img)
cv.imshow("max_img", max_img)
cv.waitKey(0)

image.png

可以看出最大值滤波可以去除图像中的暗斑,同时也会使亮斑增大(膨胀);最小值滤波可以去除图像中的亮斑,同时也会增大暗斑(腐蚀)。