一、说明
在图像处理领域,将图像卡通化是一种新趋势。人们使用不同的应用程序将他们的图像转换为卡通图像。如今,玩弄图像是许多人的爱好。人们通常会点击图片并添加滤镜或使用不同的东西自定义图像并将其发布到社交媒体上。但我们是程序员,我们做的不是普通人做的事。我们对将简单的 RGB 图像转换为卡通图像的过程更感兴趣。在这个图像处理部分中,我们将使用 OpenCV-Python 将图像卡通化。
二、图像到卡通的转换
好吧,将图像转换为卡通更多的是关于图像边缘的检测。如果你能很好地检测图像的边缘,那么卡通效果将对该图像更加有效。有许多算法可用于此,因此有多种方法可以做到这一点。我们将使用 OpenCV-Python 中的 BilateralFilter() 函数。
我通常在 Google Colab 中编写和运行代码。您可以在此处访问 Google Colab 中的完整代码。在这个项目中,我们将经历以下主要步骤:
导入所需的库
加载图像
初始化要使用的参数
使用高斯金字塔的下采样来减小图像尺寸
迭代应用双边滤波器
使用上采样将图像放大到原始大小
使用中值滤波器模糊图像
检测并增强边缘
将灰度边缘图像转换回 RGB 彩色图像
显示图像
我们必须完成这九个步骤才能获得所需的输出。那么,让我们开始吧。
三、代码实现
步骤1:库导入
import cv2
import numpy as np
import matplotlib.pylab as plt
from google.colab.patches import cv2_imshow
from google.colab import files
第2步:图像读入
def read_file(filename):
image = cv2.imread(filename)
cv2_imshow(image)
return image
uploaded = files.upload()
filename = next(iter(uploaded))
image = read_file(filename)
如果您正在使用 Google Colab,那么您可以写下上述代码。但如果您使用的是Jupyter 笔记本,那么只需添加要使用的图像的路径即可。两者是同一件事。
步骤3:双边滤波
num_down = 2
num_bilateral = 7
w, h, _ = image.shape
初始化我们将要使用的参数。num_down 表示下采样步骤的数量。num_bilateral 表示双边滤波步骤的数量。
步骤4:金字塔处理
img_color = np.copy(image)
for _ in range(num_down):
img_color = cv2.pyrDown(img_color)
这里我们缩小了图片的尺寸。为了缩小尺寸,我们使用了高斯金字塔的下采样操作。我们缩小图片的尺寸是为了使后续操作更快。
步骤5:双边
for _ in range(num_bilateral):
img_color = cv2.bilateralFilter(img_color, d=9, sigmaColor=0.1, sigmaSpace=0.01)
这里sigmaColor表示颜色中的滤波器 sigma,sigmaSpace表示坐标空间。我们在这里迭代地应用具有较小直径值的双边滤波器。参数d表示每个像素邻域的直径。
步骤6:
for _ in range(num_down):
img_color = cv2.pyrUp(img_color)
为了将图像放大到原始尺寸,我们在这里使用上采样。
步骤7:
img_gray = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)
img_blur = cv2.medianBlur(img_gray, 7)
我们将步骤 6 中的输出图像转换为灰度,并使用称为中值过滤器对图像进行模糊处理。
步骤8:
img_edge = cv2.adaptiveThreshold((255*img_blur).astype(np.uint8),\
255,cv2.ADAPTIVE_THRESH_MEAN_C,cv2.THRESH_BINARY,\
blockSize=9,C=2)
正如我们上面所讨论的,对图像进行卡通化更多的是检测图像的边缘。因此,在这一步中,我们将检测和增强所用图像的边缘。
步骤9:
img_edge = cv2.cvtColor(img_edge,cv2.COLOR_GRAY2RGB)
img_cartoon = cv2.bitwise_and(img_color,img_edge)
将灰度图像转换回 RGB 图像,并与 RGB 图像进行按位与运算以获得最终输出的卡通图像。
步骤10:
fig = plt.figure(figsize=(20,10))
fig.subplots_adjust(left=0, right=1, bottom=0, top=1, hspace=0.05, wspace=0.05)
plt.subplot(121)
plt.imshow(image)
plt.axis('off')
plt.title('原始图像', size=20)
plt.subplot(122)
plt.imshow(img_cartoon)
plt.axis('off')
plt.title('卡通化图像', size=20)
plt.显示()
最后,显示输出。
四、卡通图像代码背后的逻辑
在项目中,首先,我们必须去除图像的弱边缘,然后将图像转换为平面纹理,最后增强图像的突出边缘。为此,我们使用了 OpenCV-Python 中的bilateralFilter()、medianBlur()、adaptiveThreshold() 和 bitwise_and() 函数。
为了保持边缘清晰、纹理光滑,我们使用了 OpenCV-Python 中的 BilateralFilter() 函数。更改 sigmaColor 和 sigmaSpace 的值,并查看图像输出的变化。
此外,对图像进行下采样以创建图像金字塔。接下来,我们使用双边滤波器去除不重要的细节,然后使用后续的上采样将图像调整为原始大小。最后,为了使纹理平坦化,应用了中值模糊,然后用自适应阈值获得的二值图像掩盖原始图像,成功执行上述代码后,您将看到输出图像。我尝试使用小罗伯特·唐尼的图像,得到了这个输出图像。