【PYTHON+OPENCV】实现中值滤波

数字图像处理的作业,虽然很快写完了但还是在不该费时间的地方踩了一些弱智的坑,在这里记录一下

思路如下:
1.读入图片

image=cv.imread("test.jpg",cv.IMREAD_GRAYSCALE)

2.编写AddNoise函数增加噪点

def AddNoise(img,SNR):  #加噪音

添加噪声参考了别人的思路:
(1)计算出总共的像素个数,以及根据信噪比求出总共要布置多少个噪点


    NoiseImg=img.copy()

    h=img.shape[0]
    w=img.shape[1]
    sqare=h*w           #sqare为总共的像素个数
    num=int(sqare*(1-SNR))  #Num为噪点个数

(2)随机生成一些像素点,将其值改为0或255

for i in range(num):
        randx=random.randint(1,h-1)
        randy=random.randint(1,w-1)# 随机生成一个像素点,令它的灰度为0或225
        if random.random()<=0.5:
            NoiseImg[randx,randy]=0
        else:
            NoiseImg[randx,randy]=255

完整函数代码如下:

def AddNoise(img,SNR):  #加噪音

    NoiseImg=img.copy()

    h=img.shape[0]
    w=img.shape[1]
    sqare=h*w           #sqare为总共的像素个数
    num=int(sqare*(1-SNR))  #Num为噪点个数
    for i in range(num):
        randx=random.randint(1,h-1)
        randy=random.randint(1,w-1)# 随机生成一个像素点,令它的灰度为0或225
        if random.random()<=0.5:
            NoiseImg[randx,randy]=0
        else:
            NoiseImg[randx,randy]=255

    return NoiseImg

3.编写中值滤波函数
中值滤波的原理具体可以看这篇博文:图像处理:中值滤波&均值滤波
在这里简单讲解一下:
假设一个滤波器fliter为二维的九宫格,找出这九个数字中的中值,将这个中值赋给中间的数据
在这里插入图片描述
(1)首先创建一个一维fliter(在这里也可以创建2维的,之后的滤波循环会方便写一点,一维比较方便查找中值)。
(2)这里我用了一个快排来给这个滤波器查找中值,快排的代码是直接复制的。如果创建的是二维fliter可以使用被我注释掉的flatten()函数

def quick_sort(alist, start, end):
    if start >= end:
        return
    mid = alist[start]
    left = start
    right = end
    # left与right未重合,就向中间移动
    while left < right:
        while left < right and alist[right] >= mid:
            right -= 1
        alist[left] = alist[right]
        while left < right and alist[left] < mid:
            left += 1  # a_list = [1, 12, 22, 34, 21, 4, 6, 8, 11, 54, 36, 7, 3, 0, 60, 62, 63]
        alist[right] = alist[left]
    # 从循环退出后,left与right相遇,即left==right
    alist[left] = mid
    # 对左边部分执行快速排序
    quick_sort(alist, start, left-1)
    # 对右边部分执行快速排序
    quick_sort(alist, left+1, end)


def FindMedNum(numpy):
    #new_numpy=numpy.flatten()  #将二维数组转化为一维数组
    quick_sort(numpy,0,8)  #排序
    return numpy[4]

(3)进行滤波处理

    for i in range(h - 2):  # 滤波器在矩阵上进行遍历
        for j in range(w - 2):
            # 将每个九宫格里的数据赋值给滤波器
            a = 0
            for fi in range(i, i + 3):
                for fj in range(j, j + 3):
                    filter[a] = Noise[fi, fj]
                    a += 1
            # filter为滤波器
            MedNum = FindMedNum(filter)  # 查找中值
            NoiseImg[i + 1, j + 1] = MedNum
            # 将中值付给噪声矩阵的中间的点

完整代码如下:

import cv2 as cv
import numpy as np
import random


def quick_sort(alist, start, end):
    if start >= end:
        return
    mid = alist[start]
    left = start
    right = end
    # left与right未重合,就向中间移动
    while left < right:
        while left < right and alist[right] >= mid:
            right -= 1
        alist[left] = alist[right]
        while left < right and alist[left] < mid:
            left += 1  # a_list = [1, 12, 22, 34, 21, 4, 6, 8, 11, 54, 36, 7, 3, 0, 60, 62, 63]
        alist[right] = alist[left]
    # 从循环退出后,left与right相遇,即left==right
    alist[left] = mid
    # 对左边部分执行快速排序
    quick_sort(alist, start, left-1)
    # 对右边部分执行快速排序
    quick_sort(alist, left+1, end)


def FindMedNum(numpy):
    #new_numpy=numpy.flatten()  #将二维数组转化为一维数组
    quick_sort(numpy,0,8)  #排序
    return numpy[4]

# def rgbTogray(img):
#     h=img.shape[0]
#     w=img.shape[1]
#     img1=np.zeros((h,w),np.uint8)
#     for i in range(h):
#         for j in range(w):
#             img1[i,j]=0.144*img[i,j,0]+0.587*img[i,j,1]+0.299*img[i,j,2]
            #将彩色图像转换成灰度图像公式,注意:opencv存储图像通道顺序为BGR
    # return img1

def AddNoise(img,SNR):  #加噪音

    NoiseImg=img.copy()

    h=img.shape[0]
    w=img.shape[1]
    sqare=h*w           #sqare为总共的像素个数
    num=int(sqare*(1-SNR))  #Num为噪点个数
    for i in range(num):
        randx=random.randint(1,h-1)
        randy=random.randint(1,w-1)# 随机生成一个像素点,令它的灰度为0或225
        if random.random()<=0.5:
            NoiseImg[randx,randy]=0
        else:
            NoiseImg[randx,randy]=255

    return NoiseImg

def medflit(Noise):
    filter=np.zeros(9)#创立有9个元素的一维数组
                      #这样就不用将二维数组转化成为一维
    h=Noise.shape[0]
    w=Noise.shape[1]

    for i in range(h - 2):  # 滤波器在矩阵上进行遍历
        for j in range(w - 2):
            # 将每个九宫格里的数据赋值给滤波器
            a = 0
            for fi in range(i, i + 3):
                for fj in range(j, j + 3):
                    filter[a] = Noise[fi, fj]
                    a += 1
            # filter为滤波器
            MedNum = FindMedNum(filter)  # 查找中值
            NoiseImg[i + 1, j + 1] = MedNum
            # 将中值付给噪声矩阵的中间的点


    return Noise


image=cv.imread("test.jpg",cv.IMREAD_GRAYSCALE)
cv.imshow('img',image)

SNR=0.8
NoiseImg=AddNoise(image,SNR)
cv.imshow('NoiseImg',NoiseImg)

MedianImg=medflit(NoiseImg)
cv.imshow('MedianImg',MedianImg)


cv.waitKey(0)
cv.destroyAllWindows()


最后得到的结果是这样的
在这里插入图片描述

遇到的问题:

(1)刚开始不知道imread()函数默认读出来的应该是包含了长、宽、色彩通道的一个三维矩阵,直接当成二维的矩阵来处理,一直在报错,后来查了一些手册才知道,于是写了rbgTogray这个函数,再后来发现直接使用cv.IMREAD_GRAYSCALE参数可以直接读取到灰度图像,就注释掉了rbgTogray,如果直接读入彩色图像的话,结果是这样的:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
(2)要注意一下在赋值给滤波器的时候下标,当时犯了很愚蠢的错误一直在把中值付给滤波器,原图一点都没变……

(3)最后一个问题一直都没有解决,就是在我将最后主函数几个代码顺序变换为

NoiseImg=AddNoise(image,SNR)
MedianImg=medflit(NoiseImg)

cv.imshow('NoiseImg',NoiseImg)
cv.imshow('MedianImg',MedianImg)

的时候,NoiseImg显示的一直都是滤波完成之后的图片,我刚上手python几个月,之前主要用的都是c++,可能有一些语法上的问题,这个问题先存着,说不定过段时间回来看会发现很简单。

  • 1
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值