本文转载自公众号“读芯术”(ID:AI_Discovery)。
如今,画素描或创作漫画并不一定要手动完成,许多应用程序可以把你的照片转换成卡通图片。这并不像你想象中那么难,只需几行代码就能实现想要的效果。
有一个名为OpenCV的库,为计算机视觉应用提供了通用基础设施,并对机器学习算法进行了优化。它可用于识别物体、检测并生成高分辨率图像。本教程将展示如何利用OpenCV在Python中赋予图像卡通效果。教程中将使用Google Colab来编写并运行代码。
要想制造出卡通效果,需要注意两点:边缘和调色板。这就是照片和卡通图片之间的区别。要调整这两个要点,将通过四个主要步骤:
- 载入图像
- 创建边缘蒙版
- 减少调色板
- 将边缘蒙版与经过颜色处理的图像结合起来
在开始之前,别忘了在笔记本中导入所需的库,尤其是cv2和NumPy。
- defread_file(filename):
- img = cv2.imread(filename)
- cv2_imshow(img)
- return img
1. 载入图像
第一个步骤是载入图片。定义read_file函数,其中包含cv2_imshow,来载入我们在Google Colab中选择的图片。
- defread_file(filename):
- img = cv2.imread(filename)
- cv2_imshow(img)
- return img
调用创建的函数来载入图像:
- uploaded = files.upload()
- filename = next(iter(uploaded))
- img = read_file(filename)
我选择将下面这张图变为卡通图片:
2. 创建边缘蒙版
常见的卡通效果强调图像中边缘的厚度。可以通过cv2.adaptiveThreshold() 函数来检测图像中的边缘。我们可以将egde_mask函数定义为:
- defedge_mask(img, line_size,blur_value):
- gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
- gray_blur = cv2.medianBlur(gray,blur_value)
- edges = cv2.adaptiveThreshold(gray_blur, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, line_size,blur_value)
- return edges
在该函数中,我们将图像转换成灰度图像,然后使用cv2.medianBlur来减少模糊的灰度图像的噪点。模糊值越大,意味着图像中出现的黑色噪点越少。接着,应用adaptiveThreshold函数,定义边缘的线条粗细。线条越粗,意味着图像中强调的边缘越厚。
定义完函数后,调用函数就可以看到结果了。
- line_size = 7
- blur_value = 7edges = edge_mask(img, line_size, blur_value)
- cv2_imshow(edges)
边缘蒙版检测
3. 减少调色板
在颜色方面,照片和素描的主要区别是它们各自的颜色数量。素描的颜色比照片少。因此,我们使用颜色量化来减少照片中的颜色数量。
要进行颜色量化,我们应用OpenCV库提供的K均值聚类算法。为了在接下来的步骤中使用更方便,可以定义color_quantization函数如下:
- defcolor_quantization(img, k):
- # Transform theimage
- data = np.float32(img).reshape((-1, 3))
- # Determinecriteria
- criteria = (cv2.TERM_CRITERIA_EPS+ cv2.TERM_CRITERIA_MAX_ITER, 20, 0.001)
- # ImplementingK-Means
- ret, label, center = cv2.kmeans(data, k, None, criteria, 10, cv2.KMEANS_RANDOM_CENTERS)
- center = np.uint8(center)
- result = center[label.flatten()]
- resultresult = result.reshape(img.shape)
- return result
可以调整k值来确定想要应用到图像的颜色数量:
- total_color = 9
- img = color_quantization(img, total_color)
在本例中,图像的k值设置为9。结果如下所示:
颜色量化后
完成颜色量化后,可以通过双边滤波来降低图像中的噪点。这会使图像变得稍微模糊,且锐度降低。
- blurred = cv2.bilateralFilter(img, d=7, sigmaColor=200,sigmaSpace=200)
这里有三个参数,你可以根据自己的喜好进行调整。
- d —每个像素邻域的直径。
- sigmaColor —该参数的值越大,表示半等色的区域越大。
- sigmaSpace –该参数的值越大,意味着较远的像素只要其颜色足够接近,就会相互影响。
使用双边滤波后
4. 将边缘蒙版与经过颜色处理的图像相结合
最后一步是将我们之前创建的边缘蒙版与经过颜色处理的图像相结合。要做到这一点,需要使用cv2.bitwise_and函数。
- cartoon = cv2.bitwise_and(blurred, blurred, mask=edges)
这就是原图的“卡通版”:
最终效果
现在你可以开始创建属于自己的卡通效果啦。除了调整我们上面使用的参数值,你还可以从OpenCV中添加另一个函数来给你的照片添加特殊效果,库中还有很多可以探索的东西。尝试愉快!