首页 > 编程知识 正文

怎么对数据进行平滑处理,均值平滑如何计算

时间:2023-05-06 11:15:32 阅读:170417 作者:1341

返回到Opencv-Python教程

在图像的生成、传输或存储过程中,外部干扰可能会产生杂色,并在视觉上表现为孤立点或像素值急剧变化的点。 图像平滑处理的目的是从图像中去除这种噪声。

在讨论平滑之前,请先了解OpenCV中用于平滑的“滑动窗口”的概念。 在下面的示例中,选择了ksize=3x3的滑动窗口(或过滤器模板,kernel ),如黄色部分所示。 使用这个ksize=3x3的窗口作用于原始图像上的每个像素。 如下图绿色部分所示,该窗口覆盖的9个像素点参与计算。 这样,就可以在该像素点上得到新的像素值。 窗口沿着图像一个像素一个像素地计算,就得到了新的图像。

上图中滤波器模板的差异构成了滤波算法的差异,例如在平均平滑算法中,滑动窗口中的每个像素点的系数都为1/(窗口高度*窗口宽度),jqdg平滑中的系数与中心点的距离为jqdg

如上图所示,当滑动窗口作用于图像的边缘时,如果滑动窗口中的某些像素与图像不重叠,则需要对边缘进行特殊处理。 常见的方法是填充0、填充1或复制边缘。

1、平均平滑blur () )。

平均值滑动窗口中的所有系数都是1/(窗口高度*窗口宽度),新生成的像素值是窗口中心点和周围所有像素值的平均值。 例如,如果选择ksize=5x5的窗口,则新图像的[x,y]点的像素值用NP.sum(I[x-2:I3,y-2:y 3] )/)5*5)和numpy表示

bur ()的接口格式:

DST=cv2.blur(src,ksize[,dst[,anchor[,borderType]]] ) )参数含义:src :源图像、通道数量不限、数据锚点:定位点。 缺省值为(-1,-1),作用于滑动窗口的中心点。 borderType :边界处理类型; 以下示例是使用不同ksize的平均平滑比较。

importmatplotlib.pyplotaspltimportcv2print (VX公众号:桔子代码/juzi代码.com) ) print ) cv2._ _ version _ 3: Lena.jpg ' ) img _ re t1=cv2.blur (3,3 ) ) ) ) ) ) ) ) 11 ) #显示图像fig,ax=PLT.subplots (2,2 ) ) 1 ).set_title(blurksize=3) ) ax (0,1 ).imshow ) cv2.cvtcolor ) img_reT1,cv2.COLOR_BGR2RGB ) ) ) ax ax [ 1,0 ].axis (off ); ax [ 1,1 ].axis (off ) )关闭坐标轴并显示plt.show )的执行结果:

从执行效果可以看出,ksize越大,图像越模糊,清晰度越低。

通过观察预处理后的图像可以直观地感受到,因此通过数值验证定量的结果。 在以下例子中,设定k size=(5,5 ),提取新图像坐标x,y=10,10的像素值,提取原始图像的以x,y=10,10为中心的gtdll为5的子图,计算子图的平均值。

importnumpyasnpimportcv2print (VX公众号:桔子code/juzicode.com) (print ) cv2.__version__: )、cv2._ _ _ com LENA.jpg'(img_reT1=cv2.blur ) img,(5,5 ) ) x,y=10,10b,g,r=cv2.split ) img[x-23360x3,y-3

p.sum(r)/25)#分别计算每个通道的平均值print('img_ret1[x,y]',img_ret1[x,y])

 运行结果:

cv2.__version__: 4.5.2img b: [[124 113 113 113 114] [117 111 111 110 108] [112 110 111 108 106] [114 112 111 110 106] [112 108 106 109 105]]img g: [[142 131 133 133 136] [135 129 131 130 133] [132 130 133 130 131] [134 132 133 132 131] [134 130 131 134 130]]img r: [[235 224 228 228 231] [228 222 226 225 227] [227 225 228 225 225] [229 227 228 227 225] [229 225 225 228 224]]img average(b,g,r): 110.96 132.4 226.84img_ret1[x,y] [111 132 227]

 从运行结果可以看到新图像img_ret1像素点x,y=10,10的像素值为[111,132,227]等于原始图像的平均值:110.96,132.4,226.84取整后的结果。

2、中值平滑medianBlur()

中值平滑和均值平滑一样也采用滑动窗口的方式,但是它并不是计算滑动窗口中的某种加权和,而是使用原图像滑动窗口中所有像素值排序后的中值。

medianBlur的接口形式如下:

dst=cv2.medianBlur(src, ksize[, dst]) 参数含义:src:源图像,通道数可以是1,3或4,当ksize为3或者5时,数据类型可以是CV_8U, CV_16U, CV_32F,当使用更大的ksize时,数据类型只能是CV_8U;ksize:kernel尺寸、窗口大小,整数型,大于1的奇数值;

下面这个例子是使用不同ksize进行中值平滑的对比:

import matplotlib.pyplot as plt import cv2print('VX公众号: 桔子code / juzicode.com')print('cv2.__version__:',cv2.__version__)plt.rc('font',family='Youyuan',size='9')img = cv2.imread('..\lena.jpg')img_ret1 = cv2.medianBlur(img,3)img_ret2 = cv2.medianBlur(img,5)img_ret3 = cv2.medianBlur(img,11)#显示图像fig,ax = plt.subplots(2,2)ax[0,0].set_title('VX:桔子code 原图')ax[0,0].imshow(cv2.cvtColor(img,cv2.COLOR_BGR2RGB)) #matplotlib显示图像为rgb格式ax[0,1].set_title('medianBlur ksize=3')ax[0,1].imshow(cv2.cvtColor(img_ret1,cv2.COLOR_BGR2RGB))ax[1,0].set_title('medianBlur ksize=5')ax[1,0].imshow(cv2.cvtColor(img_ret2,cv2.COLOR_BGR2RGB))ax[1,1].set_title('medianBlur ksize=11') ax[1,1].imshow(cv2.cvtColor(img_ret3,cv2.COLOR_BGR2RGB))ax[0,0].axis('off');ax[0,1].axis('off');ax[1,0].axis('off');ax[1,1].axis('off')#关闭坐标轴显示plt.show()

运行结果:

下面仍然从数值角度看下中值平滑的处理,ksize=(5,5),提取新图像坐标x,y = 10,10处的像素值,并提取原图像的x,y=10,10为中心gtdll为5的子图,再计算子图像素值展开成list后的中值:

import numpy as npimport cv2print('VX公众号: 桔子code / juzicode.com')print('cv2.__version__:',cv2.__version__) img = cv2.imread('..\lena.jpg')img_ret1 = cv2.medianBlur(img,5)x,y = 10,10b,g,r = cv2.split(img[x-2:x+3,y-2:y+3])#分离出原图在x,y点的bgr通道print('img b:n',b )print('img g:n',g )print('img r:n',r )list_b = list(b.flatten()) #展开得到一个listlist_b.sort() #list排序list_g = list(g.flatten())list_g.sort()list_r = list(r.flatten())list_r.sort()print('list_b:',list_b )print('list_g:',list_g )print('list_r:',list_r )print('list_b[12]:',list_b[12])#提取中值print('list_g[12]:',list_g[12])print('list_r[12]:',list_r[12])print('img_ret1[x,y]',img_ret1[x,y])#新图像像素值

运行结果:

list_b: [105, 106, 106, 106, 108, 108, 108, 109, 110, 110, 110, 111, 111, 111, 111, 112, 112, 112, 113, 113, 113, 114, 114, 117, 124]list_g: [129, 130, 130, 130, 130, 130, 131, 131, 131, 131, 131, 132, 132, 132, 133, 133, 133, 133, 133, 134, 134, 134, 135, 136, 142]list_r: [222, 224, 224, 225, 225, 225, 225, 225, 225, 225, 226, 227, 227, 227, 227, 228, 228, 228, 228, 228, 228, 229, 229, 231, 235]list_b[12]: 111 #中值list_g[12]: 132list_r[12]: 227img_ret1[x,y] [111 132 227]

从上面的运行结果可以看到新图像在坐标x,y = 10,10处的像素值为[111 132 227],等于该处滑动窗口内像素值的中值。

3、像素值对比

通过前面的介绍我们可以看到平滑处理后图像会变得更“模糊”,这是因为不管均值也好,中值也罢,都会降低图像变化的程度,下面我们从另外一个角度来验证下变化效果。

因为图像在水平和垂直方向都发生了“平滑”,为了方便观察下面我们仅以水平方向为例,以图像的水平方向坐标作为绘图的X轴,在上面这个lena图片中,X轴的取值范围就是0~511(图像宽度为512个像素),提取第10行的像素值作为绘图的Y轴,因为是uint8(CV_8U)类型的数据,Y轴分布在0~255。分别绘制原图、均值滤波和中值滤波后的像素值的曲线:

import numpy as npimport matplotlib.pyplot as plt import cv2print('VX公众号: 桔子code / juzicode.com')print('cv2.__version__:',cv2.__version__)plt.rc('font',family='Youyuan',size='9')img = cv2.imread('..\lena.jpg')img_ret1 = cv2.blur(img,(15,15)) img_ret2 = cv2.medianBlur(img,15) X = np.arange(img.shape[1]) Y = img[:,:,0][10,:] #仅提取b通道第10行Y1 = img_ret1[:,:,0][10,:] #提取变化后图像的第10行Y2 = img_ret2[:,:,0][10,:]plt.plot(X,Y,'-g',label='raw' ) #绘图plt.plot(X,Y1,'-r',label='blur')plt.plot(X,Y2,'-b',label='medianBlur')plt.legend(title='img type(juzicode.com)',fontsize='xx-large',loc='upper center')plt.show()

运行结果:

从上面的对比可以看到绿色的原始图像,其像素值变化的非常“剧烈”,有很多ssddm或波谷,但是经过平滑处理后的像素值则显得平滑的多。

小结:平滑处理是图像滤波的一种,可以看做是低通滤波,它会消除图像的高频“信号”,让图像看起来更模糊、平滑,通过将变化前后的图像像素值绘制曲线可以更形象地观察到这种平滑效果。

 原文链接:OpenCV-Python教程:均值平滑、中值平滑(blur,medianBlur) – 桔子code

扩展阅读: OpenCV-Python教程

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。