欢迎关注 “小白玩转Python”,发现更多 “有趣”
引言
PhotoShop中有个功能可以将图片卡通化,让图片变得非常有趣。其实在Python中我们也可以通过OpenCV这个强大的图像处理库来实现这个功能,下面让我们开始吧!
如何将一幅图像卡通化呢?
将图像转换为卡通图像通常需要两个主要步骤: 边缘检测和区域平滑。
边缘检测的主要目的是凸显图像的边缘,因为通常卡通图像都有明确界定的边缘。同时,区域平滑的主要目的是去除不重要的颜色边界,减少图像的噪声或纹理,使图像像素化程度降低。
根据不同的滤波器,可以得到不同的图像卡通化效果。在本文中,将有以下四种不同的过滤器:
1. 铅笔素描滤波器
2. 细节增强滤波器
3. 双边滤波器
4. 铅笔边缘滤波器
接下来,我们将展示如何应用每个过滤器,以及从每个过滤器得到什么样的结果。
铅笔素描滤波器
使用铅笔素描过滤器,您的图像将被转换为素描样式,就像使用铅笔绘制图像一样。以下是使用OpenCV将图像转换为铅笔素描的完整代码。
-
# Convert the image into grayscale image
-
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
-
-
-
# Blur the image using Gaussian Blur
-
gray_blur = cv2.GaussianBlur(gray, (
25,
25),
0)
-
-
-
# Convert the image into pencil sketch
-
cartoon = cv2.divide(gray, gray_blur, scale=
250.0)
使用OpenCV只需要三行代码就可以将图像转换成铅笔素描式的图片,是不是很神奇。现在我们来逐行地解释一下图像经历了什么。
在第一行中,我们使用OpenCV的cvtColor()函数将图像从彩色转换为灰度。
接下来,我们使用高斯模糊来模糊图像。通过模糊灰度图像,我们可以实现平滑图像,减少图像的噪声。另外,图像模糊是检测图像边缘的必要步骤。
为了模糊图像,可以使用OpenCV中的GaussianBlur()函数。GaussianBlur()函数的内核大小是(25,25)。
因为我们使用了高斯模糊,核中像素值的分布遵循正态分布。内核的数量越大,标准差就会越大,因此,模糊效果就会越强。下面是不同内核大小的模糊结果的例子。
最后一步将原始灰度图像与模糊灰度图像分割。分割图像给我们两个图像的每个像素之间的变化率。模糊效果越强,每个像素相对于其原点的值变化就越大,因此,它使我们的铅笔素描就越清晰。
下面是使用铅笔素描滤波器的结果。
细节增强滤波器
简而言之,细节增强滤波器通过锐化图像,平滑颜色,增强边缘,实现一个卡通效果。下面是用这个滤波器将图像转换成卡通图像的完整代码。
-
#convert the image into grayscale image
-
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
-
-
-
#Blur the grayscale image with median blur
-
gray_blur = cv2.medianBlur(gray,
3)
-
-
-
#Apply adaptive thresholding to detect edges
-
edges = cv2.adaptiveThreshold(gray_blur,
255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY,
9,
9)
-
-
-
#Sharpen the image
-
color = cv2.detailEnhance(img, sigma_s=
5, sigma_r=
0.5)
-
-
-
#Merge the colors of same images using "edges" as a mask
-
cartoon = cv2.bitwise_and(color, color, mask=edges)
第一步和之前一样,需要把图像转换成灰度图像。
然后使用OpenCV的medianBlur()函数。中值模糊通过计算与核重叠的像素值的中值来实现,然后用计算出的中值替换中心像素值。当然你可以使用高斯模糊。
接下来,我们需要检测图像的边缘。为此,通过OpenCV的adaptiveThreshold()函数应用自适应阈值。自适应阈值的主要目标是根据内核重叠的像素的平均值,将图像每个区域中的每个像素值转换为全黑或全白。
下面是自适应阈值对模糊图像的可视化效果。
最后,利用自适应阈值的结果作为掩模。然后,根据掩模的值对细节增强的结果进行合并,得到边缘清晰的锐利效果。
下面是使用细节增强滤波器的结果。
双边滤波器
使用双边滤波器的一个最大的优点是我们可以在保留边缘的同时平滑图像和颜色。下面是完整代码。
-
#Convert image to grayscale
-
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
-
-
#Apply median blur
-
gray = cv2.medianBlur(gray,
3)
-
-
#Detect edges with adaptive threshold
-
edges = cv2.adaptiveThreshold(gray,
255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY,
9,
9)
-
-
#Apply bilateral filter
-
color = cv2.bilateralFilter(img,
5,
50,
5)
-
-
-
#Merge the colors of same image using "edges" as a mask
-
cartoon = cv2.bitwise_and(color, color, mask=edges)
仔细查看会发现,这些代码与细节增强滤波器十分相似,但这里用的是OpenCV的bilateralFilter()函数来代替detailEnhance()函数。
下面是使用双边滤波器的结果。
铅笔边缘滤波器
铅笔边缘过滤器将创建一个新的图像,只包含有意义的边缘和白色背景。下面是完整的代码。
-
#Convert the image into grayscale image
-
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
-
-
-
#Blur the grayscale image using median blur
-
gray = cv2.medianBlur(gray, 25)
-
-
-
#Detect edges with Laplacian
-
edges = cv2.Laplacian(gray, -1, ksize=3)
-
-
-
#Invert the edges
-
edges_inv = 255-edges
-
-
#Create a pencil edge sketch
-
dummy, cartoon = cv2.threshold(edges_inv, 150, 255, cv2.THRESH_BINARY)
在这里使用的是拉普拉斯滤波器。拉普拉斯滤波器的作用凸显物体的边缘。
接下来,我们反转拉普拉斯滤波器的结果,使较暗的灰色变得更亮,反之亦然。最后,通过应用OpenCV中的threshold()函数,根据指定的阈值将灰度图像转换为全黑或全白。
下面是铅笔边缘滤镜的结果。
结束语
现在我们已经实现了四种将图片卡通化的方法,是不是觉得很酷!快点实现给你展示给你的朋友看看吧~
· END ·
HAPPY LIFE
转载:https://blog.csdn.net/weixin_38739735/article/details/110790247