赞
踩
记录自己用python加opencv实现的图像处理的入门操作,各种平滑去噪滤波器的实现。
包括有:产生的椒盐噪声、高斯噪声等等,以及使用的中值滤波、平均滤波、高斯滤波等等。
分成了两部分来实现:一是自编写函数来实现,二是调用opencv中的相应函数,对比效果。
噪声的产生:分别是椒盐噪声和高斯噪声,原理的话可以参考别人的博客或我之后再补充,噪声就是在原来的图像上以一定的特殊规律给图像增添一些像素,使图像变得模糊等等。
椒盐噪声:
输入图像和自定义的噪声阈值,输出处理后的图像
# 向图片中添加椒盐噪声
def salt_pepper_noise(image, prob): # prob:盐噪声阈值,由用户自己决定
output = np.zeros(image.shape, np.uint8)
thres = 1 - prob # 胡椒噪声阈值
for i in range(image.shape[0]): # 遍历整个图片的灰度级
for j in range(image.shape[1]):
randomnum = random.random() # 生成一个随机0-1之间的随机数
if randomnum < prob: # 如果随机数大于盐噪声阈值0.1,则将此位置灰度级的值设为0,即添加盐噪声
output[i][j] = 0
elif randomnum > thres: # 如果随机数大于胡椒噪声阈值1-0.1,则将此位置灰度级的输出设为255,即添加胡椒噪声
output[i][j] = 255
else: # 如果随机数处于两者之间,则此位置的灰度级的值等于原图的灰度级值
output[i][j] = image[i][j]
return output
高斯噪声:
输入图像,自定义的参数:均值、方差,输出的是处理后的图像
# 向图片中添加高斯噪声 def gasuss_noise(image, mean=0, var=0.001): # mean : 均值,var : 方差 image = np.array(image/255, dtype=float) noise = np.random.normal(mean, var ** 0.5, image.shape) # 使用numpy库中的函数生成正态分布矩阵,对应数据分别为概率均值,概率标准差,图像的大小 output = image + noise # 输出结果为原图灰度级概率与噪声概率相加 output_handle = np.array([[[0]*3 for i in range(output.shape[1])] for i in range(output.shape[0])], dtype=float) # 处理后最终输出矩阵将齐大小设置为与原图一样 if output.min() < 0: # 确定一个比较中间值 low_clip = -1. else: low_clip = 0. for i in range (output.shape[0]): # 遍历整个三位矩阵 for j in range (output.shape[1]): for k in range (output.shape[2]): if output[i][j][k] < low_clip: # 将输出的概率矩阵内的值限定在(-1,1)范围内 output_handle[i][j][k] = low_clip # 使其之后*255变为灰度级时不会超出[0-255]的范围 elif output[i][j][k] > 1.0: output_handle[i][j][k] = 1.0 else: output_handle[i][j][k] = output[i][j][k] # 在最大值和最小值之间的不变 output = np.uint8(output_handle*255) # 将处理后的灰度级转化为[0-255]的整数级 return output
加性噪声:
# 向图片中添加加性噪声 def addrandom_noise(image,prob=0.1): output = image # 将原始图像数据拷贝至输出矩阵 n = random.randint(1, 1000) + int(prob*20000) for k in range(n-500): a = random.randint(0, 50) b = random.randint(0, 50) c = random.randint(0, 50) i = random.randint(0, image.shape[0]-1) j = random.randint(0, image.shape[1]-1) output[i][j][0] = 255-a output[i][j][1] = 255-b output[i][j][2] = 255-c for k in range(n): a = random.randint(0, 50) b = random.randint(0, 50) c = random.randint(0, 50) i = random.randint(0, image.shape[0]-1) j = random.randint(0, image.shape[1]-1) output[i][j][0] = a output[i][j][1] = b output[i][j][2] = c return output
设计了均值滤波、中值滤波、高斯滤波,可分别对应处理以上的三种噪声,效果较好。
具体的对应情况可自己比较一下哦。
中值滤波:
# 中值滤波 a为要处理的图像 windowsize为采用的模版大小 def medianfliter(a, windowsize): output = a if windowsize == 3 : output1 = np.zeros(a.shape, np.uint8) for i in range(1, output.shape[0]-1): # 求齐周围9个方格与模版进行冒泡排序 for j in range(1, output.shape[1]-1): value1 = [output[i-1][j-1], output[i-1][j], output[i-1][j+1], output[i][j-1], output[i][j], output[i][j+1], output[i+1][j-1], output[i+1][j], +output[i+1][j+1]] np.sort(value1) # 对这九个数进行排序 value = value1[4] # 中值为排序后中间这个数的正中间 output1[i-1][j-1] = value elif windowsize == 5: output1 = np.zeros(a.shape, np.uint8) for i in range(2, output.shape[0]-2): # 求齐周围25个方格与模版进行卷积 for j in range(2, output.shape[1]-2): value1 = [output[i-2][j-2],output[i-2][j-1],output[i-2][j],output[i-2][j+1],output[i-2][j+2],output[i-1][j-2],output[i-1][j-1],output[i-1][j],output[i-1][j+1],\ output[i-1][j+2],output[i][j-2],output[i][j-1],output[i][j],output[i][j+1],output[i][j+2],output[i+1][j-2],output[i+1][j-1],output[i+1][j],output[i+1][j+1],\ output[i+1][j+2],output[i+2][j-2],output[i+2][j-1],output[i+2][j],output[i+2][j+1],output[i+2][j+2]] value1.sort() # 对这九个数进行排序 value = value1[12] # 中值为排序后中间这个数的正中间 output1[i-2][j-2] = value # 将计算结果填入原本位置 else : print('模版大小输入错误,请输入3或5,分别代表3*3或5*5模版!') return output1
均值滤波:
# 均值滤波 a为要处理的图像 windowsize为采用的模版大小 def meanflite(a, windowsize): output = a if windowsize == 3: window = np.ones((3, 3)) / 3 ** 2 # 生成3*3模版 output1 = np.zeros(a.shape, np.uint8) for i in range(1, output.shape[0] - 1): # 求齐周围9个方格与模版进行卷积 for j in range(1, output.shape[1] - 1): value = (output[i - 1][j - 1] * window[0][0] + output[i - 1][j] * window[0][1] + output[i - 1][j + 1] * window[0][2] + \ output[i][j - 1] * window[1][0] + output[i][j] * window[1][1] + output[i][j + 1] * window[1][ 2] +\ output[i + 1][j - 1] * window[2][0] + output[i + 1][j] * window[2][1] + output[i + 1][j + 1] * window[2][2]) output1[i - 1][j - 1] = value # 将计算结果填入原本位置 elif windowsize == 5: window = np.ones((5, 5)) / 5 ** 2 # 生成5*5模版 output1 = np.zeros(a.shape, np.uint8) for i in range(2, output.shape[0] - 2): # 求齐周围25个方格与模版进行卷积 for j in range(2, output.shape[1] - 2): value = (output[i - 2][j - 2] * window[0][0] + output[i - 2][j - 1] * window[0][1] + output[i - 2][j] * window[0][2] + output[i - 2][j + 1] * window[0][3] + output[i - 2][j + 2] * window[0][4] + \ output[i - 1][j - 2] * window[1][0] + output[i - 1][j - 1] * window[1][1] + output[i - 1][j] * window[1][2] + output[i - 1][j + 1] * window[1][3] + output[i - 1][j + 2] * window[1][4] + \ output[i][j - 2] * window[2][0] + output[i][j - 1] * window[2][1] + output[i][j] * window[2][ 2] + output[i][j + 1] * window[2][3] + output[i][j + 2] * window[2][4] + \ output[i + 1][j - 2] * window[3][0] + output[i + 1][j - 1] * window[3][1] + output[i + 1][j] * window[3][2] + output[i + 1][j + 1] * window[3][3] + output[i + 1][j + 2] * window[3][4] + \ output[i + 2][j - 2] * window[4][0] + output[i + 2][j - 1] * window[4][1] + output[i + 2][j] * window[4][2] + output[i + 2][j + 1] * window[4][3] + output[i + 2][j + 2] * window[4][4]) output1[i - 2][j - 2] = value # 将计算结果填入原本位置 else: print('模版大小输入错误,请输入3或5,分别代表3*3或5*5模版!') return output1
高斯滤波:
ef gaussian(im):
im = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY)
b = np.array([[2, 4, 5, 2, 2],
[4, 9, 12, 9, 4],
[5, 12, 15, 12, 5],
[4, 9, 12, 9, 4],
[2, 4, 5, 4, 2]]) / 156
kernel = np.zeros(im.shape)
kernel[:b.shape[0], :b.shape[1]] = b
fim = np.fft.fft2(im)
fkernel = np.fft.fft2(kernel)
fil_im = np.fft.ifft2(fim * fkernel)
return abs(fil_im).astype(int)
我用到的包有:numpy、matplotlib.pyplot、cv2、random
主程序很好理解,读入原图,再对原图调用各种函数进行处理,再以子图的形式展示出来。
if __name__ == "__main__": image = cv2.imread('whl.jpg') plt.subplot(4, 2, 1) plt.imshow(image) plt.axis('off') plt.title('Original') salt = salt_pepper_noise(image, 0.05) plt.subplot(4, 2, 2) plt.imshow(salt) plt.axis('off') plt.title('salt') gauss = gasuss_noise(image) plt.subplot(4, 2, 3) plt.imshow(gauss) plt.axis('off') plt.title('gauss') random = addrandom_noise(image) plt.subplot(4, 2, 4) plt.imshow(random) plt.axis('off') plt.title('random') median = medianfliter(salt, 3) plt.subplot(4, 2, 5) plt.imshow(median) plt.axis('off') plt.title('median') mean = meanflite(random, 3) plt.subplot(4, 2, 6) plt.imshow(mean) plt.axis('off') plt.title('mean') gaussout = gaussian(gauss) plt.subplot(4, 2, 7) plt.imshow(gaussout) plt.axis('off') plt.title('gaussout') plt.show()
效果展示为:
以opencv中的函数实现各种噪声的产生和滤波器的编写更为简单,基本一行代码就可以实现调用,以下是我的整个程序:
# 图像去噪平滑滤波 # 使用opencv的自带函数实现,与自编写作比较 # 产生椒盐噪声,高斯噪声等 # 使用中值滤波,平均滤波,高斯滤波,方框滤波 import numpy as np import cv2 import matplotlib.pyplot as plt # 加噪声 def noise(img): out = img rows, cols, chn = img.shape for i in range(5000): x = np.random.randint(0, rows) y = np.random.randint(0, cols) out[x, y, :] = 255 return out if __name__ == "__main__": image = cv2.imread('whl.jpg') plt.subplot(3, 2, 1) plt.imshow(image) plt.axis('off') plt.title('Original') noise_img = noise(image) plt.subplot(3, 2, 2) plt.imshow(noise_img) plt.axis('off') plt.title('noise') # 均值滤波 result1 = cv2.blur(noise_img, (5, 5)) plt.subplot(3, 2, 3) plt.imshow(result1) plt.axis('off') plt.title('mean') # 方框滤波 result2 = cv2.boxFilter(noise_img, -1, (5, 5), normalize=1) plt.subplot(3, 2, 4) plt.imshow(result2) plt.axis('off') plt.title('box') # 高斯滤波 result3 = cv2.GaussianBlur(noise_img, (3, 3), 0) plt.subplot(3, 2, 5) plt.imshow(result3) plt.axis('off') plt.title('gaussian') # 中值滤波 result4 = cv2.medianBlur(noise_img, 3) plt.subplot(3, 2, 6) plt.imshow(result4) plt.axis('off') plt.title('median') plt.show()
效果展示为:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。