四种图像平滑⽅法python代码
1.图像平滑概述
图像平滑也称为图像去噪,是为了抑制图像噪声改善图像质量进⾏的处理。这种噪声可能是在图像获取和传输等过程中造成的,噪声会使图像恶化,质量下降,图像模糊,特征淹没,对图像分析很不利。
本⽂主要介绍四种空间域的图像平滑⽅法:邻域平均法(均值滤波法),超限像素平滑法,有选择保边缘平滑法和中值滤波法。并且给出案例以及python代码。
2.邻域平均法(均值滤波法)
这种⽅法直接在空间域上进⾏平滑处理
思想:
假设图像由许多灰度恒定的⼩块组成,相邻的像素之间存在很⾼的空间相关性,⽽噪声则是统计独⽴的。所以可以⽤邻域内各像素的灰度平均值代替像素原来的灰度值,实现图像的平滑。
假设有⼀副N×N的图像f(x,y),若平滑图像为g(x,y),那么我们有:
公式中:
x,y=0,1,…,N-1
s是(x,y)像素邻域内像素的集合
M表⽰集合s内像素的个数
邻域平均法是把当前像素邻域内各像素的灰度平均值作为像素的输出值,⽤这种⽅法对图像进⾏去噪。
⽅法特点:
算法简单,但这种⽅法有⼀个缺点,就是在降低噪声的同时会使图像产⽣模糊,特别是在边缘和细节处,⽽且邻域越⼤,去噪能⼒增强的同时模糊程度越严重。
3.超限像素平滑法
这种⽅法对邻域平均法稍加改进。⽅法把f(x,y)和邻域平均得到的g(x,y)值做⼀个差的绝对值运算,再与⼀个选定的阈值进⾏⽐较,⽤⽐较结果决定像素(x,y)的灰度值g’(x,y)。表达式如下:
⽅法特点:
这种⽅法对抑制椒盐噪声⽐较有效,对保护仅有微⼩灰度差的细节和纹理也有效。
4.有选择保边缘平滑法
⽅法对图像上任⼀像素(x,y)的5×5邻域,采⽤9个掩膜,其中包括⼀个3×3正⽅形、4个五边形和4个六边形。计算各个掩膜的均值和⽅差,对⽅差进⾏排序,最⼩⽅差所对应的掩膜区的灰度均值就是像素(x,y)的输出值。
这种⽅法⽤⽅差来测度区域的灰度均匀性。如果区域含有尖锐的边缘,它的灰度⽅差就会很⼤,如果不含边缘或者灰度均匀的区域,⽅差就很⼩,所以最⼩⽅差所对应的区域就是灰度最均匀区域。这种平滑⽅法既能消除噪声,⼜不会破坏区域边界的细节。
另外,五边形和六边形在(x,y)处都有锐⾓,这样,即使像素(x,y)位于⼀个复杂形状区域的锐⾓处,也能到均匀的区域。从⽽在平滑时既不会使尖锐边缘模糊,也不会破坏边缘形状。
5.中值滤波法
中值滤波法⽤⼀个滑动窗⼝,对窗⼝内的像素灰度排序,⽤中值代替窗⼝中⼼像素的灰度值,是⼀种⾮线性的图像平滑法。
中值滤波器的窗⼝形状可以有多种,如线状、⽅形、⼗字形、圆形、菱形等。不同形状的窗⼝会产⽣不同的滤波效果,在使⽤的时候需要根据图像的内容和不同的要求进⾏选择。经验表明⽅形或圆形的窗⼝适宜于外轮廓线较长的物体图像,⽽⼗字形窗⼝对有尖顶⾓状的图像效果好。
6.案例展⽰
⾸先将原始图⽚进⾏灰度化,得到灰度图⽚,并且添加椒盐噪声
对添加了椒盐噪声的图像运⽤邻域平均法进⾏处理,下图分别为3×3邻域平滑和5×5邻域平滑。可以看出5×5的邻域⽐3×3的邻域的图像模糊更严重。
对图像运⽤超限像素平滑法进⾏处理,取阈值T=50,下图分别为3×3超限像素平滑和5×5超限像素平滑。同邻域平滑法相⽐,超限像素平滑法去椒盐噪声的效果更好,⽽且⼀定程度上可以保护细节,减少图像模糊。
对图像运⽤有选择保边缘平滑法进⾏去噪处理,结果如下图所⽰,可以有效去椒盐噪声。
对图像运⽤中值滤波法进⾏处理,下图分别为3×3模板和5×5模板进⾏中值滤波的结果,可见中值滤波法能有效削弱椒盐噪声,⽽且⽐邻域、超限像素平滑法更为有效,可以保留更多的图像细节,减少图像模糊。
7.代码
灰度化与添加椒盐噪声
import cv2 as cv
import numpy as np
img = cv.imread("image.jpg")
h = img.shape[0]
w = img.shape[1]
# 将彩⾊图⽚转换为灰度图⽚
grayimage = np.zeros((h, w), np.uint8)
for i in range(h):
for j in range(w):
grayimage[i, j]=0.11* img[i, j,0]+0.59* img[i, j,1]+0.3* img[i, j,2]# python中以B G R存储图像
# 添加椒盐噪声
noiseimage = py()
SNR =0.95# 信噪⽐
pixels = h * w # 计算图像像素点个数
noise_num =int(pixels *(1- SNR))# 计算图像椒盐噪声点个数
for i in range(noise_num):
randx = np.random.randint(1, h-1)# ⽣成⼀个 1 ⾄ h-1 之间的随机整数
randy = np.random.randint(1, w-1)# ⽣成⼀个 1 ⾄ w-1 之间的随机整数
if np.random.random()<=0.5:# np.random.random()⽣成⼀个 0 ⾄ 1 之间的浮点数
noiseimage[randx, randy]=0
else:
noiseimage[randx, randy]=255
cv.imshow("image",img)
cv.imshow("grayimage", grayimage)
cv.imshow("noiseimage", noiseimage)
cv.imwrite("grayimage.jpg", grayimage)
cv.imwrite("noiseimage.jpg", noiseimage)
cv.waitKey(0)
cv.destroyAllWindows()
图像平滑
import cv2 as cv
import numpy as np
img = cv.imread("noiseimage.jpg",0)
h = img.shape[0]
w = img.shape[1]
# 均值滤波
img_Blur_3 = cv.blur(img,(3,3))# 3*3均值滤波
img_Blur_5 = cv.blur(img,(5,5))# 5*5均值滤波
# 中值滤波
img_MedianBlur_3 = cv.medianBlur(img,3)# 3*3中值滤波
img_MedianBlur_5 = cv.medianBlur(img,5)# 5*5中值滤波
# 超限像素平滑法
def overrun_pixel_smoothing(kernel, image):
img_overrun = py()
filter= np.zeros((kernel, kernel), np.uint8)
average = np.zeros((h - kernel +1, w - kernel +1), np.uint8)# 平均值矩阵
for i in range(h - kernel +1):
for j in range(w - kernel +1):
for m in range(kernel):
for n in range(kernel):
filter[m, n]= img_overrun[i + m, j + n]
average[i, j]=1/(kernel * kernel)*filter.sum()# 求平均
T =50# 设定阈值
for i in range(h - kernel +1):
for j in range(w - kernel +1):
if abs(img[i + kernel -2, j + kernel -2]- average[i, j])> T:
img_overrun[i + kernel -2, j + kernel -2]= average[i, j]
return img_overrun
img_overrun_3 = overrun_pixel_smoothing(3, img)# 核⼤⼩为3*3
img_overrun_5 = overrun_pixel_smoothing(5, img)# 核⼤⼩为5*5
# 有选择保边缘平滑法
img_EdgeKeeping = py()
filter= np.zeros((5,5), np.uint8)
for i in range(h -4):
for j in range(w -4):
for m in range(5):
for n in range(5):
filter[m, n]= img_EdgeKeeping[i + m, j + n]
mask =[]
# 3*3掩膜
mask.append([filter[1,1],filter[1,2],filter[1,3],filter[2,1],filter[2,2],filter[2,3],filter[3,1],filter[3,2],filter[3,3]]) # 5*5掩膜
mask.append([filter[2,2],filter[1,1],filter[1,2],filter[1,3],filter[0,1],filter[0,2],filter[0,3]])
mask.append([filter[2,2],filter[1,1],filter[2,1],filter[3,1],filter[1,0],filter[2,0],filter[3,0]])
mask.append([filter[2,2],filter[1,1],filter[2,1],filter[3,1],filter[1,0],filter[2,0],filter[3,0]]) mask.append([filter[2,2],filter[3,1],filter[3,2],filter[3,3],filter[4,1],filter[4,2],filter[4,3]]) mask.append([filter[2,2],filter[1,3],filter[2,3],filter[3,3],filter[1,4],filter[2,4],filter[3,4]])
# 6*6掩膜
mask.append([filter[2,2],filter[3,2],filter[2,3],filter[3,3],filter[4,3],filter[3,4],filter[4,4]]) mask.append([
filter[2,2],filter[2,3],filter[1,2],filter[1,3],filter[1,4],filter[0,3],filter[0,4]]) mask.append([filter[2,2],filter[1,2],filter[2,1],filter[1,1],filter[0,1],filter[1,0],filter[0,0]]) mask.append([filter[2,2],filter[2,1],filter[3,2],filter[3,1],filter[3,0],filter[4,1],filter[4,0]])
# 求各掩膜的⽅差
var =[]
for k in range(9):
var.append(np.var(mask[k]))
index = var.index(min(var))# ⽅差最⼩的掩膜对应的索引号
img_EdgeKeeping[i +2, j +2]= np.mean(mask[index])
cv.imshow("image", img)
cv.imshow("img_Blur_3", img_Blur_3)
cv.imshow("img_Blur_5", img_Blur_5)
python代码转换
cv.imshow("img_MedianBlur_3", img_MedianBlur_3)
cv.imshow("img_MedianBlur_5", img_MedianBlur_5)
cv.imshow("img_overrun_3", img_overrun_3)
cv.imshow("img_overrun_5", img_overrun_5)
cv.imshow("img_EdgeKeeping", img_EdgeKeeping)
cv.waitKey(0)
cv.destroyAllWindows()
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论