基于Python与OpenCV实现简易动漫图片转换器
本文介绍如何使用Python结合OpenCV和PyQt5库开发一个简易的动漫风格图片转换器。通过构建图形界面与后台处理线程分离的架构,利用双边滤波和边缘检测算法实现照片到动漫风格的转换,确保主界面流畅响应。
项目概述与依赖库
本文的目标是开发一款能够将普通照片转换为动漫风格图片的小型工具,该工具核心依赖于OpenCV这一非标准库来完成图像转换任务。

用户界面(UI)部分选用PyQt5进行构建,鉴于作者对该库较为熟悉,开发过程相对便捷。在开始具体编码前,首先列出本项目所依赖的Python非标准库列表。
环境依赖与模块导入
# PyQt5相关模块
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
# 动漫图片制作的业务模块
import cv2
import sys
import os
# 日志模块
from loguru import logger
接下来进行UI界面的搭建,定义一个名为CartoonUI的类,负责初始化图片转换器的应用程序。由于该应用仅需实现单页面功能,因此CartoonUI类直接继承自QWidget基类。
UI界面类实现
class CartoonUI(QWidget):
def __init__(self):
'''
初始化UI界面应用
'''
super(CartoonUI, self).__init__()
self.init_ui()
def init_ui(self):
'''
自定义实现的ui应用函数
:return:
'''
self.setWindowTitle('动漫图片转换器 公众号:Python 集中营')
self.setWindowIcon(QIcon('ico.png'))
self.setFixedWidth(500)
hbox = QHBoxLayout()
self.input_image_path = QLineEdit()
self.input_image_path.setPlaceholderText('源图片路径')
self.input_image_path.setReadOnly(True)
self.input_image_btn = QPushButton()
self.input_image_btn.setText('导入源图片')
self.input_image_btn.clicked.connect(self.input_image_btn_click)
self.generate_btn = QPushButton()
self.generate_btn.setText('一键生成动漫图片')
self.generate_btn.clicked.connect(self.generate_btn_click)
hbox.addWidget(self.input_image_path)
hbox.addWidget(self.input_image_btn)
hbox.addWidget(self.generate_btn)
self.thread_ = WorkThread(self)
self.thread_.finished.connect(self.finished)
self.setLayout(hbox)
def input_image_btn_click(self):
'''
input_image_btn按钮绑定的槽函数,
用于实现打开文件浏览项
:return:
'''
im_path = QFileDialog.getOpenFileName(self, os.getcwd(), '打开图片',
'Image File(*.jpg);;Image File(*.png);;Image File(*.jpeg)')
self.input_image_path.setText(im_path[0])
def generate_btn_click(self):
'''
generate_btn按钮绑定的槽函数,
用于启动业务子线程
:return:
'''
self.thread_.start()
self.generate_btn.setEnabled(False)
def finished(self,finished):
'''
接收子线程中finished变量,
判定子线程业务是否执行完成,若执行完成则将按钮状态改变为可点击状态
:param finished:
:return:
'''
if finished is True:
self.generate_btn.setEnabled(True)
创建WorkThread类,该类继承自QThread以运行子线程。子线程专门负责执行普通图片到动漫图片的转换业务。采用子线程处理业务逻辑的原因是,若在PyQt5的主线程中直接执行耗时操作,极易导致界面卡顿甚至无响应。
通过独立子线程处理业务逻辑,可以确保PyQt5主线程持续正常运作,从而有效实现业务处理与界面交互的解耦。
后台处理线程逻辑
class WorkThread(QThread):
finished = pyqtSignal(bool)
def __init__(self, parent=None):
'''
子线程初始化函数
:param parent:
'''
super(WorkThread, self).__init__(parent)
self.parent = parent
self.working = True
def __del__(self):
'''
子线程停止函数
:return:
'''
self.working = False
self.wait()
def run(self):
'''
子线程执行函数
:return:
'''
try:
input_picture_name = os.path.basename(self.parent.input_image_path.text().strip())
logger.info(input_picture_name)
output_picture_name = 'cartoon_' + input_picture_name
num_down = 2 # 缩减像素采样的数目
num_bilateral = 7 # 定义双边滤波的数目
img_rgb = cv2.imread(input_picture_name) # 读取图片
# 用高斯金字塔降低取样
img_color = img_rgb
for _ in range(num_down):
img_color = cv2.pyrDown(img_color)
# 重复使用小的双边滤波代替一个大的滤波
for _ in range(num_bilateral):
img_color = cv2.bilateralFilter(img_color, d=9, sigmaColor=9, sigmaSpace=7)
# 升采样图片到原始大小
for _ in range(num_down):
img_color = cv2.pyrUp(img_color)
# 转换为灰度并且使其产生中等的模糊
img_gray = cv2.cvtColor(img_color, cv2.COLOR_RGB2GRAY)
img_blur = cv2.medianBlur(img_gray, 7)
# 检测到边缘并且增强其效果
img_edge = cv2.adaptiveThreshold(img_blur, 255,
cv2.ADAPTIVE_THRESH_MEAN_C,
cv2.THRESH_BINARY,
blockSize=9,
C=2)
# 转换回彩色图像
img_edge = cv2.cvtColor(img_edge, cv2.COLOR_GRAY2RGB)
img_cartoon = cv2.bitwise_and(img_color, img_edge)
# 保存转换后的图片
cv2.imwrite(output_picture_name, img_cartoon)
logger.info('动漫图片转换完成!')
self.finished.emit(True)
except Exception as e:
logger.error(e)
在完成上述业务逻辑开发后,需在main函数中将PyQt5应用实例加入主事件循环,以此启动整个UI应用程序。
程序入口与启动
if __name__ == '__main__':
app = QApplication(sys.argv)
main = CartoonUI()
main.show()
sys.exit(app.exec_())至此,关于基于Python实现简易动漫图片转换器的介绍结束。如需了解更多Python动漫图片转换相关内容,建议搜索本站过往文章或继续阅读后续相关教程,感谢大家的支持!
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









