巧用python实现图片转换成素描和漫画格式

1. 简介

人们一直以来对于艺术的追求,包括绘画,一直是人类探索的方向之一。而随着技术的发展,现在我们可以通过计算机来实现各种各样的绘画效果,从而满足人们的需求。本文主要介绍如何利用Python实现将普通图片转变为素描和漫画风格的图片。

2. Python绘图库介绍

在这个教程中,我们会使用两个Python绘图库来完成转换工作,它们分别是:

OpenCV:是一款流行的计算机视觉库,提供了各种各样的图像处理函数和模块。

Stylized-Image:是一个基于PyTorch的深度学习库,可以进行图像转换和风格转移。

3. 素描效果

3.1 准备工作

在这个部分,我们将介绍如何使用OpenCV将图片转换为素描效果的图像。

首先,我们先安装必要的库:

!pip install opencv-python-headless

!pip install opencv-contrib-python-headless

然后读入一张图片,代码如下:

import cv2

image = cv2.imread("test.jpg")

这里我们读入的图片是一张风景图片,我们将它转换成灰度图,如下所示:

gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

接下来,我们将使用Canny算子进行边缘提取,如下所示:

canny_output = cv2.Canny(gray_image, 100, 200)

然后再使用高斯滤波进行模糊,代码如下:

blurred = cv2.GaussianBlur(canny_output, (11, 11), 0)

最后,我们将边缘图与原图结合起来,得到绘画风格的图片:

edged = cv2.bitwise_or(blurred, canny_output) 

result = cv2.bitwise_or(image, edged)

3.2 模块封装

为了方便使用,我们将上面的代码进行封装成模块,供后续使用:

import cv2

class Sketch:

def __init__(self, img_path):

self.image = cv2.imread(img_path)

def sketch(self, ksize=5, sigmaX=0, sigmaY=0):

gray_image = cv2.cvtColor(self.image, cv2.COLOR_BGR2GRAY)

# 边缘提取

canny_output = cv2.Canny(gray_image, 100, 200)

# 高斯滤波

blurred = cv2.GaussianBlur(canny_output, (ksize, ksize), sigmaX, sigmaY)

# 结合图像

edged = cv2.bitwise_or(blurred, canny_output)

result = cv2.bitwise_or(self.image, edged)

return result

这样,我们就可以轻松地使用上面的代码,生成我们的绘画风格图片了:

image_path = "test.jpg"

s = Sketch(image_path)

sketch = s.sketch()

cv2.imwrite("sketch_test.jpg", sketch)

运行上面的代码,我们可以得到以下素描风格的图片:

4. 漫画效果

4.1 准备工作

这里我们将介绍如何使用Stylized-Image模块,将图片转换为漫画效果的图像。漫画风格通常是应用一些特定的图像处理方法,例如:

边缘检测

图像平滑

颜色量化

接下来,我们将一步步地实现这个过程。

首先,我们需要安装必要的库:

!pip install torch torchvision

!pip install stylized-image

然后,我们读入一张图片:

import cv2

import numpy as np

import torch

import torchvision.transforms as transforms

from PIL import Image

from stylized_image.models import TransformerNet

image = cv2.imread("test.jpg")

image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)

我们使用了PyTorch提供的transforms类,将图片转换为一个PIL类型的对象。

4.2 边缘检测

接下来,我们将使用Canny算法进行边缘检测:

gray_image = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)

edges = cv2.Canny(gray_image, 100, 200)

这里我们得到的是一个边缘检测的二值图像:

4.3 图像平滑

接下来,我们将对上面得到的二值图像进行平滑处理,使整个图像变得更加自然。

我们使用OpenCV提供的Bilateral Filter算法进行平滑处理。它能够使边缘保留得更好,同时去除噪声。

#Bilateral Filter

color = cv2.bilateralFilter(image, 9, 250, 250)

# 将颜色图像转换为灰度图像

gray = cv2.cvtColor(color, cv2.COLOR_BGR2GRAY)

# 将值域缩小为0到10之间

gray = cv2.convertScaleAbs(gray, alpha=10, beta=0)

# 将灰度图像和边缘图像通过逻辑“与”操作

cartoon = cv2.bitwise_and(gray, gray, mask=edges)

我们可以看到,处理后的图片变得更加平滑和自然:

4.4 颜色量化

最后,我们将对上面得到的图像进行颜色量化。这里我们使用Python中的Pillow模块,将图像的颜色数量限制到10种左右。

# 转换为Pillow图片

cartoon = Image.fromarray(cartoon)

# 定义色板

color_palette = Image.new('P', (1, 1))

color_palette.putpalette(np.array([

0, 0, 0,

63, 31, 31,

94, 47, 47,

127, 63, 63,

159, 79, 79,

191, 95, 95,

223, 111, 111,

255, 127, 127,

223, 159, 159,

255, 223, 223,

]).astype('uint8'))

# 重新调整图片大小

cartoon = cartoon.quantize(colors=10, palette=color_palette)

# 转换为OpenCV格式图片

cartoon = cv2.cvtColor(np.asarray(cartoon), cv2.COLOR_RGB2BGR)

处理后的图片:

4.5 模块封装

为了方便使用,我们将上述代码进行封装成模块:

import cv2

import numpy as np

import torch

import torchvision.transforms as transforms

from PIL import Image

from stylized_image.models import TransformerNet

class Cartoonify:

def __init__(self, img_path):

self.image = cv2.imread(img_path)

self.net = self.load_network('https://www.dropbox.com/s/w463to8he8b3w4g/mosaic.pth?dl=1')

def load_network(self, url):

state_dict = torch.utils.model_zoo.load_url(url)

net = TransformerNet()

net.load_state_dict(state_dict)

return net.eval().cuda()

def cartoonify(self):

# 边缘检测

gray_image = cv2.cvtColor(self.image, cv2.COLOR_BGR2GRAY)

edges = cv2.Canny(gray_image, 100, 200)

# 平滑处理

color = cv2.bilateralFilter(self.image, 9, 250, 250)

gray = cv2.cvtColor(color, cv2.COLOR_BGR2GRAY)

gray = cv2.convertScaleAbs(gray, alpha=10, beta=0)

cartoon = cv2.bitwise_and(gray, gray, mask=edges)

# 颜色量化

cartoon = Image.fromarray(cartoon)

color_palette = Image.new('P', (1, 1))

color_palette.putpalette(np.array([

0, 0, 0,

63, 31, 31,

94, 47, 47,

127, 63, 63,

159, 79, 79,

191, 95, 95,

223, 111, 111,

255, 127, 127,

223, 159, 159,

255, 223, 223,

]).astype('uint8'))

cartoon = cartoon.quantize(colors=10, palette=color_palette)

cartoon = cv2.cvtColor(np.asarray(cartoon), cv2.COLOR_RGB2BGR)

return cartoon

使用上面封装好的模块,我们可以轻松地将我们的图片转换为漫画效果:

image_path = "test.jpg"

c = Cartoonify(image_path)

cartoon = c.cartoonify()

cv2.imwrite("cartoon_test.jpg", cartoon)

运行上面的代码,我们可以得到以下漫画风格的图片:

总结

本文主要介绍如何利用Python实现将普通图片转变为素描和漫画风格的图片。其中,我们使用了OpenCV和Stylized-Image两个Python绘图库,分别实现素描风格和漫画风格转换。同时,我们还封装了两个模块,使得转换过程更加简单和方便。

免责声明:本文来自互联网,本站所有信息(包括但不限于文字、视频、音频、数据及图表),不保证该信息的准确性、真实性、完整性、有效性、及时性、原创性等,版权归属于原作者,如无意侵犯媒体或个人知识产权,请来电或致函告之,本站将在第一时间处理。猿码集站发布此文目的在于促进信息交流,此文观点与本站立场无关,不承担任何责任。

后端开发标签