均值滤波与中值滤波的python实现

均值滤波

均值滤波是指先选按某种规律选中图像的像素点(从左到右,从上到下),对选中的像素点进行一个范围区域的选取,按选中的像素个数进行平均。
在这里插入图片描述
按上图方式,第一个点的新像素值就应该是原始像素与周围八个像素和的平均,计算完后,移入下一个像素进行计算,直到遍历完整的图像,就可以得到框为3的均值滤波图像。如果是三通道的RGB图,记得要对每一层进行滤波操作。
该操作可以呗总结为一个3x3大小,每个元素值为1/9的卷积核与图像进行卷积操作,根据该思想可以对算法进行加速处理。
从上面的操作可以看出,当框处于图像边界时,外部是没有像素的,这里我们一般处理是填0,或者是镜像填充或者是边缘复制,这两种处理会对滤波图像的边缘产生影响。
在这里插入图片描述
处理结果如下所示:
在这里插入图片描述

import cv2
import numpy as np


#   对图像边界进行0填充
def set_border_zero(image_data, ksize):
    h_, w_, c_ = image_data.shape
    border = int((ksize - 1) / 2)
    result_data = np.zeros((h_ + ksize - 1, w_ + ksize - 1, c_))
    result_data[border:border+h_, border:border+w_, :] = image_data
    return result_data.astype("uint8")


#   对图像进行边缘镜像处理
def set_border_sym(image_data, ksize):
    h_, w_, c_ = image_data.shape
    border = int((ksize - 1) / 2)
    result_data = np.zeros((h_ + ksize - 1, w_ + ksize - 1, c_))
    for c in range(c_):
        for i in range(h_ + 2 * border):
            if i < border:
                y_ori = border - i
            elif i > h_ + border - 1:
                y_ori = (h_ + border - 1) - (i - (border + h_ - 1)) - border
            else:
                y_ori = i - border
            for j in range(w_ + 2 * border):
                if j < border:
                    x_ori = border - j
                elif j > w_ + border - 1:
                    x_ori = (w_ + border - 1) - (j - (border + w_ - 1)) - border
                else:
                    x_ori = j - border
                result_data[i, j, c] = image_data[y_ori, x_ori, c]
    return result_data.astype("uint8")


def mean_filtering(image_pad_data, ksize):
    h_, w_, c_ = image_pad_data.shape
    result_data = np.zeros_like(image_pad_data)
    #   定义卷积核大小
    k_ = np.ones((ksize, ksize)) / (ksize * ksize)
    border = int((ksize - 1) / 2)
    #   对图像分图层进行处理
    for c in range(c_):
        #   输入的是填充后的图像,但索引要从原图像素处开始
        for y in range(border, h_ - border):
            for x in range(border, w_ - border):
                #   获得(x, y)处的像素参考框,然后与k逐像素相乘并求和
                reference_matrix = image_pad_data[y-border:y+border + 1, x-border:x+border+1, c]
                sum_ref = 0
                for i in range(ksize):
                    for j in range(ksize):
                        sum_ref += reference_matrix[i, j] * k_[i, j]

                result_data[y, x, c] = sum_ref

    return result_data[border:h_ - border, border:w_ - border, :].astype("uint8")


if __name__ == "__main__":
    ori_image = cv2.imread("../../data/image/lena.png")

    #   cv2自带的均值滤波  cv2.blur(原始图像,核大小)

    cv2_result = cv2.blur(ori_image, (5, 5))

    #   手写均值滤波, 这里ksize一般为奇数,便于边缘填充,当ksize = 1 时,算发不起作用
    # zero_border_image = set_border_zero(ori_image, 5)
    sym_border_image = set_border_sym(ori_image, 5)
    result_data_mean = mean_filtering(sym_border_image, 5)

    cv2.imshow("ori_image", ori_image)
    # cv2.imshow("zero_border_image", zero_border_image)
    cv2.imshow("sym_border_image", sym_border_image)
    cv2.imshow("cv2_result", cv2_result)
    cv2.imshow("result_data_mean", result_data_mean)
    cv2.waitKey(0)

中值滤波

按下图方式,第一个点的新像素值就应该是原始像素与周围八个像素排序,去中位数作为新像素点,移入下一个像素进行计算,直到遍历完整的图像,
在这里插入图片描述

import cv2
import numpy as np


#   对图像边界进行0填充
def set_border_zero(image_data, ksize):
    h_, w_, c_ = image_data.shape
    border = int((ksize - 1) / 2)
    result_data = np.zeros((h_ + ksize - 1, w_ + ksize - 1, c_))
    result_data[border:border+h_, border:border+w_, :] = image_data
    return result_data.astype("uint8")


#   对图像进行边缘镜像处理
def set_border_sym(image_data, ksize):
    h_, w_, c_ = image_data.shape
    border = int((ksize - 1) / 2)
    result_data = np.zeros((h_ + ksize - 1, w_ + ksize - 1, c_))
    for c in range(c_):
        for i in range(h_ + 2 * border):
            if i < border:
                y_ori = border - i
            elif i > h_ + border - 1:
                y_ori = (h_ + border - 1) - (i - (border + h_ - 1)) - border
            else:
                y_ori = i - border
            for j in range(w_ + 2 * border):
                if j < border:
                    x_ori = border - j
                elif j > w_ + border - 1:
                    x_ori = (w_ + border - 1) - (j - (border + w_ - 1)) - border
                else:
                    x_ori = j - border
                result_data[i, j, c] = image_data[y_ori, x_ori, c]
    return result_data.astype("uint8")


def median_filtering(image_pad_data, ksize):
    h_, w_, c_ = image_pad_data.shape
    result_data = np.zeros_like(image_pad_data)
    #   定义卷积核大小
    border = int((ksize - 1) / 2)
    #   对图像分图层进行处理
    for c in range(c_):
        #   输入的是填充后的图像,但索引要从原图像素处开始
        for y in range(border, h_ - border):
            for x in range(border, w_ - border):
                #   获得(x, y)处的像素参考框,然后排序取中值
                reference_matrix = image_pad_data[y-border:y+border + 1, x-border:x+border+1, c]
                #   转为1维矩阵
                reference_matrix = reference_matrix.reshape(-1)
                #   排序
                reference_matrix = np.sort(reference_matrix)
                result_data[y, x, c] = reference_matrix[border]

    return result_data[border:h_ - border, border:w_ - border, :].astype("uint8")


if __name__ == "__main__":
    ori_image = cv2.imread("../../data/image/lena.png")

    #   cv2自带的均值滤波  cv2.blur(原始图像,核大小)

    cv2_result = cv2.medianBlur(ori_image, 5)

    #   手写均值滤波, 这里ksize一般为奇数,便于边缘填充,当ksize = 1 时,算发不起作用
    # zero_border_image = set_border_zero(ori_image, 5)
    sym_border_image = set_border_sym(ori_image, 5)
    result_data_median = median_filtering(sym_border_image, 5)

    cv2.imshow("ori_image", ori_image)
    # cv2.imshow("zero_border_image", zero_border_image)
    cv2.imshow("sym_border_image", sym_border_image)
    cv2.imshow("cv2_result", cv2_result)
    cv2.imshow("result_data_median", result_data_median)
    cv2.waitKey(0)

此处按中值滤波原理写的结果,与cv2的结果有明显区别,后续有时间需要查看源码作详细对比。
在这里插入图片描述

  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值