(十七)最新批量视频换脸、无训练高速换脸、一张图片即可完成、批量处理

最新批量视频换脸、无训练高速换脸、一张图片即可完成、批量处理

前期发布的视频换脸软件【https://blog.csdn.net/weixin_42398606/article/details/128235374】的效果不是非常好,人脸融合有瑕疵。

本文结合最新的AI模型实现人脸融合,效果得到很好提升。本模型使用多尺度编码器提取原图属性特征,使用预训练人脸识别模型数据提取用户图的ID特征,通过引入可行变特征的融合结构, 将ID特征嵌入其属性特征空间,以光流场的形式实现人脸面部自适应变化,最终使其融合效果真实、融洽、保真,并且支持对目标脸型的自适应感知。
在任意真实人物图像进行直接推理,不用事先训练模型。最好是正脸或偏侧一定小范围角度的侧脸图像,人脸五官轮廓清晰无遮挡,图像分辨率大于128x128,小于3840×2160。

本代码功能是:可以对人物视频进行换脸操作,不用预先耗时训练模型,效率极高;可进行批量视频处理,使用了最新的人工智能的算法。

本文与前几篇博文关联性较强,请事先阅读前几篇。 对此文感兴趣的可以加微深入探讨:herbert156
可运行的试用版本下载:https://pan.baidu.com/s/1JRGaWkj3MzkuBrj6T0idfw
提取码: up3j

如果提示过期,可以向博主索要新的SN文件。

一、主要功能:
以下的Python代码的功能:批量选择视频、批量处理,主要包括:
1、对视频进行换脸操作,并输出变换后的文件;
2、可以批量处理,在选择文件的对话框里可以选择多个文件,进行批量操作;
3、如果电脑有GPU,则会自动选择GPU处理,加快处理速度;
4、信息统计里面可以实时显示处理的各种统计信息;
5、视频处理完毕后自动进行音频的处理与合成。

软件运行界面如下:
在这里插入图片描述
二、主要代码:

话不多说,上代码!

UI的Python代码:

# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file 'AI_SwapFace1_UI.ui'
#
# Created by: PyQt5 UI code generator 5.15.4
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again.  Do not edit this file unless you know what you are doing.


from PyQt5 import QtCore, QtGui, QtWidgets


class Ui_ai_repire(object):
    def setupUi(self, ai_repire):
        ai_repire.setObjectName("ai_repire")
        ai_repire.setEnabled(True)
        ai_repire.resize(912, 681)
        font = QtGui.QFont()
        font.setFamily("宋体")
        font.setPointSize(12)
        ai_repire.setFont(font)
        ai_repire.setMouseTracking(False)
        self.layoutWidget = QtWidgets.QWidget(ai_repire)
        self.layoutWidget.setGeometry(QtCore.QRect(360, 626, 531, 41))
        self.layoutWidget.setObjectName("layoutWidget")
        self.horizontalLayout_5 = QtWidgets.QHBoxLayout(self.layoutWidget)
        self.horizontalLayout_5.setContentsMargins(0, 0, 0, 0)
        self.horizontalLayout_5.setObjectName("horizontalLayout_5")
        self.startButton = QtWidgets.QPushButton(self.layoutWidget)
        font = QtGui.QFont()
        font.setFamily("宋体")
        font.setPointSize(12)
        self.startButton.setFont(font)
        self.startButton.setObjectName("startButton")
        self.horizontalLayout_5.addWidget(self.startButton)
        self.stopButton = QtWidgets.QPushButton(self.layoutWidget)
        font = QtGui.QFont()
        font.setFamily("宋体")
        font.setPointSize(12)
        self.stopButton.setFont(font)
        self.stopButton.setObjectName("stopButton")
        self.horizontalLayout_5.addWidget(self.stopButton)
        spacerItem = QtWidgets.QSpacerItem(60, 20, QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Minimum)
        self.horizontalLayout_5.addItem(spacerItem)
        self.helpButton = QtWidgets.QPushButton(self.layoutWidget)
        font = QtGui.QFont()
        font.setFamily("宋体")
        font.setPointSize(12)
        self.helpButton.setFont(font)
        self.helpButton.setObjectName("helpButton")
        self.horizontalLayout_5.addWidget(self.helpButton)
        self.quitButton = QtWidgets.QPushButton(self.layoutWidget)
        font = QtGui.QFont()
        font.setFamily("宋体")
        font.setPointSize(12)
        self.quitButton.setFont(font)
        self.quitButton.setObjectName("quitButton")
        self.horizontalLayout_5.addWidget(self.quitButton)
        self.groupBox_2 = QtWidgets.QGroupBox(ai_repire)
        self.groupBox_2.setGeometry(QtCore.QRect(10, 20, 881, 281))
        self.groupBox_2.setContextMenuPolicy(QtCore.Qt.DefaultContextMenu)
        self.groupBox_2.setAlignment(QtCore.Qt.AlignCenter)
        self.groupBox_2.setObjectName("groupBox_2")
        self.my_label1 = QtWidgets.QLabel(self.groupBox_2)
        self.my_label1.setGeometry(QtCore.QRect(12, 30, 427, 240))
        self.my_label1.setObjectName("my_label1")
        self.my_label2 = QtWidgets.QLabel(self.groupBox_2)
        self.my_label2.setGeometry(QtCore.QRect(443, 30, 427, 240))
        self.my_label2.setObjectName("my_label2")
        self.groupBox_4 = QtWidgets.QGroupBox(ai_repire)
        self.groupBox_4.setGeometry(QtCore.QRect(10, 320, 881, 151))
        self.groupBox_4.setAlignment(QtCore.Qt.AlignCenter)
        self.groupBox_4.setObjectName("groupBox_4")
        self.filesButton = QtWidgets.QPushButton(self.groupBox_4)
        self.filesButton.setGeometry(QtCore.QRect(20, 30, 78, 24))
        font = QtGui.QFont()
        font.setFamily("宋体")
        font.setPointSize(12)
        self.filesButton.setFont(font)
        self.filesButton.setObjectName("filesButton")
        self.outButton = QtWidgets.QPushButton(self.groupBox_4)
        self.outButton.setGeometry(QtCore.QRect(20, 108, 78, 24))
        font = QtGui.QFont()
        font.setFamily("宋体")
        font.setPointSize(12)
        self.outButton.setFont(font)
        self.outButton.setObjectName("outButton")
        self.txt1 = QtWidgets.QLabel(self.groupBox_4)
        self.txt1.setGeometry(QtCore.QRect(110, 32, 591, 20))
        self.txt1.setObjectName("txt1")
        self.txt2 = QtWidgets.QLabel(self.groupBox_4)
        self.txt2.setGeometry(QtCore.QRect(110, 110, 511, 20))
        self.txt2.setObjectName("txt2")
        self.filesButton1 = QtWidgets.QPushButton(self.groupBox_4)
        self.filesButton1.setGeometry(QtCore.QRect(20, 70, 78, 24))
        font = QtGui.QFont()
        font.setFamily("宋体")
        font.setPointSize(12)
        self.filesButton1.setFont(font)
        self.filesButton1.setObjectName("filesButton1")
        self.txt3 = QtWidgets.QLabel(self.groupBox_4)
        self.txt3.setGeometry(QtCore.QRect(110, 70, 581, 20))
        self.txt3.setObjectName("txt3")
        self.my_label3 = QtWidgets.QLabel(self.groupBox_4)
        self.my_label3.setGeometry(QtCore.QRect(650, 20, 213, 120))
        self.my_label3.setObjectName("my_label3")
        self.groupBox_5 = QtWidgets.QGroupBox(ai_repire)
        self.groupBox_5.setGeometry(QtCore.QRect(10, 496, 881, 101))
        self.groupBox_5.setAlignment(QtCore.Qt.AlignCenter)
        self.groupBox_5.setObjectName("groupBox_5")
        self.txt11 = QtWidgets.QLabel(self.groupBox_5)
        self.txt11.setGeometry(QtCore.QRect(20, 30, 861, 16))
        self.txt11.setObjectName("txt11")
        self.txt12 = QtWidgets.QLabel(self.groupBox_5)
        self.txt12.setGeometry(QtCore.QRect(20, 60, 861, 21))
        self.txt12.setObjectName("txt12")
        self.check_result = QtWidgets.QPushButton(ai_repire)
        self.check_result.setGeometry(QtCore.QRect(130, 630, 121, 31))
        font = QtGui.QFont()
        font.setFamily("宋体")
        font.setPointSize(12)
        self.check_result.setFont(font)
        self.check_result.setObjectName("check_result")

        self.retranslateUi(ai_repire)
        QtCore.QMetaObject.connectSlotsByName(ai_repire)

    def retranslateUi(self, ai_repire):
        _translate = QtCore.QCoreApplication.translate
        ai_repire.setWindowTitle(_translate("ai_repire", "AI换脸工具"))
        self.startButton.setText(_translate("ai_repire", "开始处理"))
        self.stopButton.setText(_translate("ai_repire", "停止处理"))
        self.helpButton.setText(_translate("ai_repire", "帮助"))
        self.quitButton.setText(_translate("ai_repire", "退出"))
        self.groupBox_2.setTitle(_translate("ai_repire", "预览窗口"))
        self.my_label1.setText(_translate("ai_repire", "原图"))
        self.my_label2.setText(_translate("ai_repire", "输出"))
        self.groupBox_4.setTitle(_translate("ai_repire", "文件设置"))
        self.filesButton.setText(_translate("ai_repire", "换脸视频"))
        self.outButton.setText(_translate("ai_repire", "输出目录"))
        self.txt1.setText(_translate("ai_repire", "请选择被换脸的视频文件[Ctrl+A全选、Ctrl/Shift+鼠标可多选]......"))
        self.txt2.setText(_translate("ai_repire", "换脸完成的视频输出目录"))
        self.filesButton1.setText(_translate("ai_repire", "换脸图片"))
        self.txt3.setText(_translate("ai_repire", "请选择自己的脸部图片"))
        self.my_label3.setText(_translate("ai_repire", "换脸图片"))
        self.groupBox_5.setTitle(_translate("ai_repire", "信息统计"))
        self.txt11.setText(_translate("ai_repire", "【视频信息】"))
        self.txt12.setText(_translate("ai_repire", "【运行信息】"))
        self.check_result.setText(_translate("ai_repire", "查看换脸结果"))

主要核心代码:

#AI视频处理工具_
import os, sys, time, cv2, threading
from PIL import Image,ImageDraw,ImageFont
import moviepy.editor as mpe
import numpy as np

from PyQt5 import QtWidgets, QtGui
from PyQt5.QtWidgets import QWidget,QMessageBox,QFileDialog,QApplication
from PyQt5.QtCore import Qt, QTimer
from PyQt5.QtGui import QPixmap, QIcon
from AI_SwapFace1_UI import Ui_ai_repire

os.environ['TORCH_HOME'] = './torch_model'

pil_img = Image.open("start_img.jpg")
ImageDraw.Draw(pil_img).text((160,150), "    AI换脸处理工具", (255,255,255),font=ImageFont.truetype("msyh.ttc", 36))
img_start = cv2.resize(cv2.cvtColor(np.array(pil_img), cv2.COLOR_RGB2BGR), (427, 240))
ImageDraw.Draw(pil_img).text((410,320), "正在加载AI模型,请稍后 ......", (255,255,255),font=ImageFont.truetype("msyh.ttc", 16))
img_s = cv2.cvtColor(np.array(pil_img), cv2.COLOR_RGB2BGR)
run_flag = 0
def showpic():  # 以下代码显示软件初始界面
    global ret, frame
    while run_flag == 0:
        cv2.imshow("AI Repire Transfer System", img_s)
        cv2.waitKey(100)
    cv2.destroyAllWindows()
t = threading.Thread(target=showpic)
t.start()

# savedStdout = sys.stdout  #保存标准输出流
file = open('./log.txt', 'wt')  #运行信息到Log文件
sys.stdout = file  #标准输出重定向至文件

DEBUG_FLAG = False
# DEBUG_FLAG = True
os.environ['TORCH_HOME'] = './torch_model'

my_title = "AI换脸工具"
work_path = os.getcwd()
input_path = work_path + '\input'
pic_input_path = work_path + '\input'
out_dir=work_path + '\output'
my_pic_a_path = work_path + '\\input\\face.jpg'
files = [work_path + '\\input\\test.mp4']

filesnums = 1; stop_flag = False; stop_flag_1 = False; t0 = 0; iii = 0

class MainWin(QWidget, Ui_ai_repire):
    def __init__(self):
        super(MainWin, self).__init__()
        self.setupUi(self)
        global hwnd, run_flag
        self.createLayout()
        self.setWindowIcon(QIcon("anime.ico"))
        self.setWindowFlags(Qt.WindowMinimizeButtonHint)
        self.show()
        run_flag = 1
        self.flash_item = True

    def CV2toPIL(self, img):  # cv2转PIL
        return Image.fromarray(cv2.cvtColor(img, cv2.COLOR_BGRA2RGBA))
    def PILtoCV2(self, img):  # PIL转cv2
        return cv2.cvtColor(np.array(img), cv2.COLOR_RGBA2BGRA)
    def two_pic_combine_PIL(self, back_img, fore_img): #2个图片合并
        back_img = self.CV2toPIL(back_img); fore_img = self.CV2toPIL(fore_img); r,g,b,alpha = fore_img.split()
        return cv2.cvtColor(self.PILtoCV2(Image.composite(fore_img, back_img, alpha)), cv2.COLOR_BGRA2BGR)
    def water_print(self, img):  # 打文字水印
        # cv2.putText(图像,需要添加字符串,需要绘制的坐标,字体类型,字号,字体颜色,字体粗细)
        w = img.shape[1]  # 宽度
        h = img.shape[0]  # 高度
        bk_img = np.zeros((160, 1280, 3), np.uint8)  # Creat a Image
        bk_img = cv2.putText(bk_img, 'wx:herbert156', (80, 130), cv2.LINE_AA, 5, (180, 180, 180), 12)
        bk_img = cv2.resize(bk_img, (w, int(w * 16 / 128)))
        mask = 255 * np.ones(bk_img.shape, bk_img.dtype)
        width, height, channels = img.shape
        center = (height // 2, width // 2)  # 融合的位置,可以自己设置
        res = cv2.seamlessClone(bk_img, img, mask, center, cv2.MONOCHROME_TRANSFER)
        return res

    def RunChange(self, img_path):  #卡通转换功能
        check_face  = self.ulfd_face_detection(img_path)
        if check_face['scores'] == []:
            print("Not found the face......")
            return img_path
        cv2.imwrite('tmp.jpg', img_path)
        template_path = 'tmp.jpg'
        user_path = my_pic_a_path
        result = self.image_face(template_path, user_path).astype(np.uint8)
        # cv2.imwrite('result.png', result[OutputKeys.OUTPUT_IMG])
        # try: os.remove('tmp.jpg')
        # except Exception as errmsg: print(repr(errmsg)); print('删除<tmp.jpg>临时文件发生错误...')
        return result

    def video_change(self, videofile):     #videofile:文件名
        global bg_files, iii, stop_flag, t0
        try: cap = cv2.VideoCapture(videofile)  # 读取视频文件
        except: self.show_error('读取视频文件:'+videofile+'时,出现错误(类型:视频文件无法解码)!'); return
        fps = cap.get(cv2.CAP_PROP_FPS)  # 帧率
        total_fr = cap.get(cv2.CAP_PROP_FRAME_COUNT)  # 总帧数
        size_x = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))  # 视频流的帧宽度
        size_y = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))  # 视频流的帧高度
        if fps==0 or total_fr==0 or size_x==0 or size_y==0:
            self.show_error('读取视频文件:' + videofile + '时,出现错误(类型:视频文件格式错误)!'); return
        try: len_m,len_s = divmod(total_fr/fps, 60)
        except: self.show_error('读取视频文件:' + videofile + '时,出现错误(类型:视频文件内容为空)!'); return

        videoinfo = '【文件信息】 视频总数:%d|正在处理(%d/%d):'%(filesnums,iii,filesnums) + os.path.split(videofile)[1]+\
                    '|帧分辨率:%dx%d|视频长度:%d分%d秒|FPS:%.2f帧/秒'%(size_x,size_y,len_m,len_s,fps)
        self.txt11.setText(videoinfo)

        # tempfile = os.path.split(bg_files[0])[0]+'\\out.mp4'
        tempfile = 'out.mp4'
        out = cv2.VideoWriter(tempfile, cv2.VideoWriter_fourcc(*'mp4v'), fps, (size_x, size_y))
        t1 = time.time(); next_fr = 0
        if size_x / size_y > 1.778: fx = 427 / size_x; fy = fx   # 计算16:9的比例,以便缩放不变形
        else: fx = 240 / size_y; fy = fx

        while (True):
            t2 = time.time()
            if stop_flag:
                cap.release();  out.release(); os.remove(tempfile)
                self.txt11.setText('【文件信息】 文件总数:%d个 | 处理完成:%d个' % (filesnums, iii))
                self.txt12.setText('【运行信息】 用户终止了正在进行的转换进程......')
                return
            next_fr += 1
            ret, frame = cap.read()
            if ret:
                if not DEBUG_FLAG: img2 = self.RunChange(frame)
                else: img2 = frame
                #img2 = cv2.cvtColor(frame.copy(), cv2.COLOR_BGR2BGRA)   #测试用语句
                out.write(img2)  # 帧转成视频
            else: break

            self.my_label1.setPixmap(self.CvMatToQImage(cv2.resize(frame,(0,0),fx=fx,fy=fy)))
            self.my_label2.setPixmap(self.CvMatToQImage(cv2.resize(img2, (0, 0), fx=fx, fy=fy)))

            cv2.waitKey(1)
            t3 = time.time(); m1, s1 = divmod(t3-t0, 60); m2, s2 = divmod(t3-t1, 60)
            runinfo = '【运行信息】 总进度:%d%% | 总耗时:%d分%d秒 | 当前耗时:%d分%d秒 | 帧耗时:%.2f秒 | 速度:%.1fFPS'\
                      %(100*next_fr/total_fr, m1, s1, m2, s2,(t3-t2),1/(t3-t2))
            self.txt12.setText(runinfo)

        cap.release(); out.release()
        self.txt12.setText('【运行信息】 正在分离、合成音轨(大概需要:%.1f分钟,不要关闭软件),请稍后......'%(len_m/2))
        cv2.waitKey(1)
        try:
            audio = mpe.AudioFileClip(videofile)  # 分离声轨
            clip = mpe.VideoFileClip(tempfile)
            videoclip = clip.set_audio(audio)  # 写入声轨

            videoclip.write_videofile(out_dir+'/'+os.path.splitext(os.path.split(videofile)[1])[0]+ '_1.mp4',
                                      audio_codec = 'aac')
            # out_file = out_dir + '\\' + os.path.splitext(os.path.split(file)[1])[0] + '_1.mp4'

        except Exception as errmsg: print(repr(errmsg)); print('分离声音发生错误...')
        try: os.remove(tempfile)
        except Exception as errmsg: print(repr(errmsg)); print('删除临时文件发生错误...')
        t3 = time.time()
        self.txt12.setText('【运行信息】 处理完毕!总消耗时间:%d分%d秒'%(m1, s1))
        self.txt11.setText('【文件信息】 文件总数:%d个 | 处理完成:%d个'%(filesnums,iii))


    def CvMatToQImage(self, ptr):  # Converts an opencv MAT format into a QImage
        ptr = cv2.cvtColor(ptr, cv2.COLOR_BGRA2RGBA)  # 颜色格式转换
        QtImg = QtGui.QImage(ptr.data, ptr.shape[1], ptr.shape[0], QtGui.QImage.Format_RGBA8888)
        return QtGui.QPixmap.fromImage(QtImg)

    def show_error(self, str):
        r_button = QMessageBox.question(self, my_title,'\n\n'+str+'\n\n', QMessageBox.Ok)
    # def show_error(self, str):
    #     infoBox = QMessageBox()
    #     infoBox.setIcon(QMessageBox.Information)
    #     infoBox.setText(str)
    #     infoBox.setStandardButtons(QMessageBox.Ok)
    #     infoBox.button(QMessageBox.Ok).animateClick(30000)  # 10秒自动关闭
    #     infoBox.exec_()

    def set_False_Btn(self):
        self.filesButton.setEnabled(False);       self.outButton.setEnabled(False)
        self.startButton.setEnabled(False);       self.stopButton.setEnabled(True)
        self.quitButton.setEnabled(False);        self.filesButton1.setEnabled(False)
    def set_True_Btn(self):
        self.filesButton.setEnabled(True);       self.outButton.setEnabled(True)
        self.startButton.setEnabled(True);       self.stopButton.setEnabled(False)
        self.quitButton.setEnabled(True);        self.filesButton1.setEnabled(True)

    def startrun(self):
        global iii,stop_flag, stop_flag_1, t0
        iii = 0; stop_flag = False
        stop_flag_1 = False
        t0 = time.time()
        if files == []: self.show_error('请选择需要处理的视频文件!'); return
        if my_pic_a_path == '': self.show_error('请选择自己的人像文件!'); return
        if not os.path.exists(out_dir): self.show_error('输出目录不存在,请重新选择!'); return
        self.set_False_Btn()
        self.txt12.setText('【运行信息】 正在初始化AI模型......')

        def run_thread():
            global iii, stop_flag, stop_flag_1, t0
        
            for file in files:
                iii += 1
                if stop_flag: break
                self.video_change(file)
            stop_flag_1 = True

        t = threading.Thread(target=run_thread)
        t.start()

        self.my_timer = QTimer(self)
        self.my_timer.start(500)
        self.my_timer.timeout.connect(self.set_run_over)

    def set_run_over(self):
        if stop_flag_1:
            self.my_timer.stop()
            self.set_True_Btn()
            return

        # if self.txt12.text() == '【运行信息】': self.txt12.setText(self.flash_item_str)
        # else: self.txt12.setText('【运行信息】')

    def stoprun(self):
        global stop_flag
        r_button = QMessageBox.question(self, my_title,
                                        "\n\n    确定要停止视频处理吗?\n\n", QMessageBox.Yes | QMessageBox.No)
        if r_button == QMessageBox.Yes: stop_flag = True

    def helpWin(self):
        str="\n\n\n1、【换脸视频】选择需要处理的视频文件(可多选);\n" \
            "2、【换脸图片】选择自己的脸部图片(单选);\n" + \
            "3、【输出目录】处理后的文件目录,文件名:源文件_*.mp4;\n"+\
            "4、本软件只支持Nvidia系列GPU;\n\n\n"+\
            "      本软件著作权归属:xxx         网址:xxx.com\n\n"
        QMessageBox.question(self, my_title, str, QMessageBox.Ok)
    def quitWin(self):
        r_button = QMessageBox.question(self, my_title,
                                        "\n\n退出将终止处理过程...... \n\n确认退出吗?\n\n", QMessageBox.Yes | QMessageBox.No)
        if r_button == QMessageBox.Yes: sys.exit()

    def checkresult(self):
        os.startfile(out_dir)

    def filesButton_fuc(self):  #选择视频
        global files,filesnums,input_path
        files, ok1 = QFileDialog.getOpenFileNames(self,'请选择视频文件[全选:Ctrl+A、多选:Ctrl/Shift+鼠标]',
                                                       input_path,"*.mp4;*.avi;*.mkv;;*.*")
        filesnums = len(files)
        if files!=[]:
            txt='目录:'+os.path.split(files[0])[0]+'|已选文件:'+str(filesnums)+'个|文件名:'
            for file in files: txt=txt+ os.path.split(file)[1]+'; '
            self.txt1.setText(txt)
            input_path = os.path.dirname(files[0])
        else:
            self.txt1.setText('请选择视频文件[全选:Ctrl+A、多选:Ctrl/Shift+鼠标]......')
    def filesButton1_fuc(self): #选择自己的人脸图片
        global pic_input_path, my_pic_a_path
        my_pic_a_path, _ = QFileDialog.getOpenFileName(self,'请选择脸部图片文件[只能单选]',
                                                       pic_input_path, "*.jpg;*.png;;*.*")
        if my_pic_a_path != '':
            print(my_pic_a_path)
            try:
                img = cv2.imread(my_pic_a_path)
                if img is None: self.show_error('\n图片路径、名称不能包含中文.....\n\n' + '图片名称:' + my_pic_a_path);  return
            except:
                self.show_error('\n图片路径、名称不能包含中文.....\n\n'+'图片名称:'+my_pic_a_path);  return

            size_x = img.shape[1]  # 宽度
            size_y = img.shape[0]  # 高度
            if size_x < 512 or size_y < 512:
                my_pic_a_path = []
                self.show_error('\n请保证图片分辨率大于512x512.....\n\n'+
                                '您选择的图片分辨率:'+str(size_x)+'x'+str(size_y));  return

            self.txt3.setText(my_pic_a_path + ' | 分辨率:'+str(size_x)+'x'+str(size_y))
            pic_input_path = os.path.dirname(my_pic_a_path)
            pix_img = QPixmap(my_pic_a_path)
            pix_img = pix_img.scaled(213, 120, Qt.KeepAspectRatio)
            self.my_label3.setAlignment(Qt.AlignRight)
            self.my_label3.setPixmap(pix_img)
        else:
            self.txt3.setText('请选择脸部图片文件[只能单选]......')
    def outButton_fuc(self):
        global out_dir
        out_dir = QFileDialog.getExistingDirectory(self,'选择转换后的输出文件夹', work_path)
        if out_dir == '': self.txt2.setText('请选择视频变换后的文件保存目录......')
        else: self.txt2.setText(out_dir)

    def createLayout(self):
        self.my_label1.setPixmap(self.CvMatToQImage(img_start))
        self.my_label2.setPixmap(self.CvMatToQImage(img_start))
        pix_img = QPixmap(my_pic_a_path)
        pix_img = pix_img.scaled(213, 120, Qt.KeepAspectRatio)
        self.my_label3.setAlignment(Qt.AlignRight)
        self.my_label3.setPixmap(pix_img)

        self.my_label1.setAlignment(Qt.AlignCenter)
        self.my_label2.setAlignment(Qt.AlignCenter)
        self.my_label1.setFixedSize(427, 240)
        self.my_label2.setFixedSize(427, 240)
        self.my_label1.setAlignment(Qt.AlignCenter)
        self.my_label2.setAlignment(Qt.AlignCenter)
        self.my_label1.setToolTip("本区域,显示的是原始视频缩略图...")
        self.my_label2.setToolTip("本区域,显示的是处理后的缩略图...")
        self.my_label3.setToolTip("本区域,显示的是用户选择的人脸图片...")

        self.filesButton.setToolTip("选择即将被处理的的视频文件,可单选、多选...")
        self.filesButton1.setToolTip("选择请选择自己的脸部图片...")
        self.outButton.setToolTip("选择输出文件目录,处理后的文件将存在此目录...")

        self.txt1.setText(files[0])
        self.txt2.setText(out_dir)
        self.txt3.setText(my_pic_a_path)

        self.filesButton.clicked.connect(self.filesButton_fuc)
        self.filesButton1.clicked.connect(self.filesButton1_fuc)
        self.outButton.clicked.connect(self.outButton_fuc)

        self.stopButton.setEnabled(False)
        self.startButton.clicked.connect(self.startrun)
        self.stopButton.clicked.connect(self.stoprun)
        self.helpButton.clicked.connect(self.helpWin)
        self.quitButton.clicked.connect(self.quitWin)
        self.check_result.clicked.connect(self.checkresult)

#if __name__ == '__main__':
QApplication.setAttribute(Qt.AA_EnableHighDpiScaling)
app = QtWidgets.QApplication(sys.argv)
MainWin = MainWin()
sys.exit(app.exec_())


猜你喜欢

转载自blog.csdn.net/weixin_42398606/article/details/129708176
今日推荐