持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第17天,点击查看活动详情
之前的博客里面已经说过了卷积的概念,很多时候,图像里面涉及的操作原理都与卷积类似,比如现在市面上有许多美颜的软件,其中有一项功能被称为磨皮,其中最基本的原理就是平滑,本博客主要是在原理层和代码实现层,细细的剖析一下平滑。
对于一幅灰度图像,其平滑本质上可以视为一种空间滤波的操作,在这种操作下,滤波器的系数对于每一个经过的像素价值相同。当滤波器划过图像时,像素会在滤波器中被平均,这种原理的背后,数学公式可以表示如下。
在灰度图中,图像被视为标量图像,这些标量图像可以通过传统的灰度级邻域处理,对于彩色图像的平滑与灰度图的平滑类似,不同的是灰度图是单通道图像,平滑时仅需要在一个面上进行即可,而彩色图,是三通道图像,也就是相当于三张灰度图的叠加,在算法计算时原理相同。
本博客的示例代码以灰度图为例,实现图像的平滑效果,其实现过程类似于pytorch中的conv2d的实现操作,代码如下。
import numpy as np
import imageio.v3 as imageio
import PIL.Image as Image
def smoothness(img, fil):
fil_heigh = fil.shape[0]
fil_width = fil.shape[1]
conv_heigh = img.shape[0] - fil.shape[0] + 1
conv_width = img.shape[1]- fil.shape[1] + 1
conv = np.zeros((conv_heigh, conv_width), dtype='uint8')
for i in range(conv_heigh):
for j in range(conv_width):
conv[i][j] = Out_of_bounds_value_handling(img[i:i + fil_heigh, j:j + fil_width], fil)
return conv
def Out_of_bounds_value_handling(img, fil):
res = (img * fil).sum()
if (res < 0):
res = 0
elif res > 255:
res = 255
return res
src = Image.open("./pt1.PNG")
src = src.convert("L")
src = np.array(src)
kernel = np.array([[1.0, 1.0, 1.0], [1.0, 2.0, 1.0], [1.0, 1.0, 1.0]]) / 9.0
image = smoothness(src, kernel)
imageio.imwrite("./test.png", image)
本实验使用的原图如下
通过上述代码处理平滑之后的结果图如下
通过结果处理后可以明显看到图片变得模糊,这就是所谓的平滑,在磨皮时,就是通过将局部区域的像素值进行均值化或者使用特殊的卷积核进行平滑处理而得到的效果,与上述的算法处理效果类似,有兴趣的可以结合我之前博客中讲述的的pyqt模块制作自己的磨皮小工具。