前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Python 让图像变卡通图

Python 让图像变卡通图

作者头像
用户9925864
发布2022-07-27 08:38:15
6410
发布2022-07-27 08:38:15
举报
文章被收录于专栏:算法工程师的学习日志

要创造卡通效果,我们需要注意两件事: 边缘和调色板,这就是照片和卡通的不同之处。为了调整这两个主要组成部分,我们将经历四个主要步骤:

  • 加载图像
  • 创建边缘
  • 减少调色板
  • 将边缘掩模与彩色图像结合

1. 图片导入

代码语言:javascript
复制
import cv2
import numpy as np
img = cv2.imread('xingye.jpg')
cv2.imshow('origin', img)
cv2.waitKey(0)
cv2.destroyAllWindows()

2. 创建边缘掩模

卡通效果强调图像边缘的宽度,使用 cv2.adaptiveThreshold()函数检测图像的边缘。

代码语言:javascript
复制
def edge_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 函数,并定义边缘的线条大小。更大的线条尺寸意味着更宽的边缘,这将在图像中得到展示。

代码语言:javascript
复制
line_size = 7
blur_value = 7
edges = edge_mask(img, line_size, blur_value)
cv2.imshow('edges', edges)
cv2.waitKey(0)
cv2.destroyAllWindows()

3. 减少调色板

照片和绘画的主要区别(就颜色而言)在于每张照片中不同颜色的数量,其中绘画的图像的颜色比照片少。因此,我们使用量化的方式来减少照片中的颜色数量。

为了实现这个图像量化,我们应用了 OpenCV 库提供的 K-Means 算法。为了使下一步更容易,我们可以定义 color_quantization 函数如下。

代码语言:javascript
复制
def color_quantization(img, k):
    data = np.float32(img).reshape((-1, 3))

    criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 20, 0.001)

    ret, label, center = cv2.kmeans(data, k, None, criteria, 10, cv2.KMEANS_RANDOM_CENTERS)
    center = np.uint8(center)
    result = center[label.flatten()]
    result = result.reshape(img.shape)
    return result

k 值是我们想要应用到图像的颜色数量

代码语言:javascript
复制
total_color = 9
img = color_quantization(img, total_color)

双边滤波器

做完图像量化后,我们可以通过使用双边滤波器来降低图像中的噪声。这会给图像带来一点模糊和锐度降低的效果。

代码语言:javascript
复制
blurred = cv2.bilateralFilter(img, d=7, sigmaColor=200, sigmaSpace=200)

调整以下三个参数:

  • d:每个像素邻域的直径
  • sigmaColor:颜色空间滤波器的sigma值。这个参数的值越大,就表明该像素邻域内有更宽广的颜色会被混合到一起,产生较大的半相等颜色区域。
  • sigmaSpace:坐标空间中滤波器的sigma值,坐标空间的标注方差。他的数值越大,意味着越远的像素会相互影响,从而使更大的区域足够相似的颜色获取相同的颜色。

4. 边缘掩模和彩色图像结合

最后一步是将我们前面创建的边缘掩模与经过颜色处理的图像结合起来。为此,可以使用 cv2.bitwise_and 函数

代码语言:javascript
复制
cartoon = cv2.bitwise_and(blurred, blurred, mask=edges)

cv2.imshow('cartoon', cartoon)
cv2.waitKey(0)
cv2.destroyAllWindows()

完整代码如下

代码语言:javascript
复制
import cv2
import numpy as np


def edge_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


img = cv2.imread('xingye.jpg')
cv2.imshow('origin', img)
cv2.waitKey(0)
cv2.destroyAllWindows()

line_size = 7
blur_value = 7
edges = edge_mask(img, line_size, blur_value)
cv2.imshow('edges', edges)
cv2.waitKey(0)
cv2.destroyAllWindows()


def color_quantization(img, k):
    data = np.float32(img).reshape((-1, 3))

    criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 20, 0.001)

    ret, label, center = cv2.kmeans(data, k, None, criteria, 10, cv2.KMEANS_RANDOM_CENTERS)
    center = np.uint8(center)
    result = center[label.flatten()]
    result = result.reshape(img.shape)
    return result


total_color = 9
img = color_quantization(img, total_color)

blurred = cv2.bilateralFilter(img, d=7, sigmaColor=200, sigmaSpace=200)
cartoon = cv2.bitwise_and(blurred, blurred, mask=edges)

cv2.imshow('cartoon', cartoon)
cv2.waitKey(0)
cv2.destroyAllWindows()
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-03-03,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 算法工程师的学习日志 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档