首頁 > 軟體

基於Python實現簡易的動漫圖片轉換器

2022-08-26 14:01:24

本文旨在製作一個將普通照片轉換成動漫圖片的小工具,其中使用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,因為這裡只需要製作一個單頁面的應用,因此,這裡只繼承了QWidget。

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的主執行緒正常的執行,將業務實現和介面應用分離開來。

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動漫圖片轉換器內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com