数字图像处理的作业,虽然很快写完了但还是在不该费时间的地方踩了一些弱智的坑,在这里记录一下
思路如下:
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++,可能有一些语法上的问题,这个问题先存着,说不定过段时间回来看会发现很简单。