Python图像处理经典实例
上QQ阅读APP看书,第一时间看更新

1.6 创建卡通图像

在本实例中,我们将介绍如何用图像创建卡通风格的平面纹理图像。同样,有很多方法可以实现这一目的。在本实例中,我们将学习如何使用边缘保持双边滤波器来实现卡通风格的平面纹理图像。

1.6.1 准备工作

让我们先导入以下Python库:

import cv2
import numpy as np
import matplotlib.pylab as plt 

1.6.2 执行步骤

在本实例中,我们将用到OpenCV-Python库的bilateralFilter()函数。我们先对图像进行下采样以创建图像金字塔(更多内容参见第7章),然后重复应用小双边滤波器(用以去除不重要的细节)并将图像上采样到图像原始大小,而后需要应用中值模糊(来使纹理变平),最后使用自适应阈值算法所获得的二值图像来对原始图像添加掩膜。具体步骤如下。

1.读取输入图像,并初始化后面代码所要用到的参数:

img = plt.imread("images/bean.png")
 
num_down = 2 # number of downsampling steps
num_bilateral = 7 # number of bilateral filtering steps
 
w, h, _ = img.shape

2.使用高斯金字塔下采样来减小图像尺寸(并使得后续运算更快):

img_color = np.copy(img)
for _ in range(num_down):
 img_color = cv2.pyrDown(img_color)

3.迭代地应用双边滤波器(使用较小直径值)。其中,参数d表示每个像素的邻域直径,参数sigmaColor表示颜色空间中的滤波器sigma,而参数sigmaSpace则表示坐标空间:

for _ in range(num_bilateral):
 img_color = cv2.bilateralFilter(img_color, d=9, sigmaColor=0.1,
sigmaSpace=0.01)

4.使用上采样将图像放大到原始尺寸:

for _ in range(num_down):
img_color = cv2.pyrUp(img_color) 

5.将通过以上步骤所得到的图像转换为输出图像,并使用中值滤波器对图像进行模糊处理:

img_gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
img_blur = cv2.medianBlur(img_gray, 7) 

6.检测并增强图像边缘:

img_edge = cv2.adaptiveThreshold((255*img_blur).astype(np.uint8), \
            255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, \ 
blockSize=9, C=2) 

7.将灰度边缘图像转换回RGB彩色图像,并与 RGB 彩色图像进行按位与(and)计算,得到最终输出的卡通图像:

img_edge = cv2.cvtColor(img_edge, cv2.COLOR_GRAY2RGB)
img_cartoon = cv2.bitwise_and(img_color, img_edge) 

1.6.3 工作原理

如前所述,在本实例中,我们分别调用了OpenCV-Python库中的bilateralFilter()函数、medianBlur()函数、adaptiveThreshold()函数和bitwise_and()函数。也就是说,先去除图像的弱边缘,然后将图像转换为平面纹理,最后增强图像中的突出边缘。

调用OpenCV-Python库中的bilateralFilter()函数来平滑图像纹理,同时保持图像边缘足够清晰。

参数sigmaColor的值越大,邻域中的像素颜色就会越多地混合在一起。这样,就会在输出图像中产生更大的半等色区域。

参数sigmSpace的值越大,颜色相似的像素之间的相互影响就会越大。

通过对图像下采样,我们就可以创建一个图像金字塔(更多内容参见第7章)。

随后,我们重复应用小双边滤波器来去除不重要的细节,并通过上采样将图像调整为其原始尺寸;最后,应用中值模糊(来使纹理变平),并随后使用自适应阈值算法所获得的二值图像来对原始图像添加掩膜。

运行上述代码,将得到图1-12所示的卡通图像输出。

图1-12

1.6.4 更多实践

请读者使用OpenCV库函数的不同参数值来查看这些参数值对所生成的输出图像的影响。此外,正如前文中所提到的,达到相同效果的方法有多种。例如可尝试使用各向异性扩散来获得平面纹理图像。读者会得到图1-13所示的图像(使用medpy库中的anisotropic_diffusion()函数)。

图1-13