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

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

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

本文与前几篇博文关联性较强,请事先阅读前几篇。
可运行的试用版本下载:https://pan.baidu.com/s/1JRGaWkj3MzkuBrj6T0idfw
提取码: up3j

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

注意:
1、请根据您的电脑的显卡情况,选择下载CPU或GPU版本。GPU版本仅支持NVIDIA显卡。
2、如果没有NVIDIA显卡,请下载CPU版本,CPU版本处理比较慢,每秒只能处理不到1帧;
3、使用GPU版本,最好下载最新版本显卡驱动:https://www.nvidia.cn/Download/index.aspx?lang=cn

一、主要功能:
以下的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, QtWidgetsclass 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.translateai_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 npfrom 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_repireos.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, framewhile 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 = 0class MainWin(QWidget, Ui_ai_repire):def __init__(self):super(MainWin, self).__init__()self.setupUi(self)global hwnd, run_flagself.createLayout()self.setWindowIcon(QIcon("anime.ico"))self.setWindowFlags(Qt.WindowMinimizeButtonHint)self.show()run_flag = 1self.flash_item = Truedef CV2toPIL(self, img):  # cv2转PILreturn Image.fromarray(cv2.cvtColor(img, cv2.COLOR_BGRA2RGBA))def PILtoCV2(self, img):  # PIL转cv2return 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 Imagebk_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.shapecenter = (height // 2, width // 2)  # 融合的位置,可以自己设置res = cv2.seamlessClone(bk_img, img, mask, center, cv2.MONOCHROME_TRANSFER)return resdef RunChange(self, img_path):  #卡通转换功能check_face  = self.ulfd_face_detection(img_path)if check_face['scores'] == []:print("Not found the face......")return img_pathcv2.imwrite('tmp.jpg', img_path)template_path = 'tmp.jpg'user_path = my_pic_a_pathresult = 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 resultdef video_change(self, videofile):     #videofile:文件名global bg_files, iii, stop_flag, t0try: cap = cv2.VideoCapture(videofile)  # 读取视频文件except: self.show_error('读取视频文件:'+videofile+'时,出现错误(类型:视频文件无法解码)!'); returnfps = 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 + '时,出现错误(类型:视频文件格式错误)!'); returntry: len_m,len_s = divmod(total_fr/fps, 60)except: self.show_error('读取视频文件:' + videofile + '时,出现错误(类型:视频文件内容为空)!'); returnvideoinfo = '【文件信息】 视频总数:%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 = 0if size_x / size_y > 1.778: fx = 427 / size_x; fy = fx   # 计算16:9的比例,以便缩放不变形else: fx = 240 / size_y; fy = fxwhile (True):t2 = time.time()if stop_flag:cap.release();  out.release(); os.remove(tempfile)self.txt11.setText('【文件信息】 文件总数:%d个 | 处理完成:%d个' % (filesnums, iii))self.txt12.setText('【运行信息】 用户终止了正在进行的转换进程......')returnnext_fr += 1ret, 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: breakself.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 QImageptr = 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, t0iii = 0; stop_flag = Falsestop_flag_1 = Falset0 = time.time()if files == []: self.show_error('请选择需要处理的视频文件!'); returnif my_pic_a_path == '': self.show_error('请选择自己的人像文件!'); returnif not os.path.exists(out_dir): self.show_error('输出目录不存在,请重新选择!'); returnself.set_False_Btn()self.txt12.setText('【运行信息】 正在初始化AI模型......')def run_thread():global iii, stop_flag, stop_flag_1, t0for file in files:iii += 1if stop_flag: breakself.video_change(file)stop_flag_1 = Truet = 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_flagr_button = QMessageBox.question(self, my_title,"\n\n    确定要停止视频处理吗?\n\n", QMessageBox.Yes | QMessageBox.No)if r_button == QMessageBox.Yes: stop_flag = Truedef 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_pathfiles, 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_pathmy_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);  returnexcept:self.show_error('\n图片路径、名称不能包含中文.....\n\n'+'图片名称:'+my_pic_a_path);  returnsize_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));  returnself.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_dirout_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_())

(十八)视频换-脸、无训练高速换-脸、一张图片即可完成、批量处理相关推荐

  1. 深度学习入门(三十八)计算性能——多GPU训练

    深度学习入门(三十八)计算性能--多GPU训练 前言 计算性能--多GPU训练 课件 多GPU并行 数据并行VS模型并行 数据并行 总结 教材 1 问题拆分 2 数据并行性 3 简单网络 4 数据同步 ...

  2. 48. 数据结构笔记之四十八的有向无环图的应用关键路径

    48. 数据结构笔记之四十八的有向无环图的应用关键路径 "富贵不淫贫贱乐 , 男儿到此是豪雄.-- 程颢" 来看下有向无环图的另一个应用关键路径. 1.  关键路径 与AOV-网相 ...

  3. 燕十八视频--CSS

    1,浏览器解析标准声明doctype:总共有三种类型,分别为:transitional,strict,frameset transitional:过渡型标准,这种标准允许使用表现层的标识,元素和属性 ...

  4. 布尔教育_燕十八 php,布尔教育_燕十八_HTML视频资源课件

    <布尔教育_燕十八_HTML教程>从最基本的概念开始讲起,步步深入,带领大家学习HTML.CSS样式基础知识,了解各种常用标签的意义以及基本用法,后半部分讲解CSS样式代码添加,为后面的案 ...

  5. (十五)视频处理、不用事先训练

    (十五)视频处理.不用事先训练 本文的代码的功能是:可以对人物视频进行操作,不用预先耗时训练模型,效率极高: 可进行视频处理,使用了人工智能的算法. 注:请移步最新博文(十八)- 一.主要功能: 以下 ...

  6. 节选—Android 视频直播 ( 从快播到直播,从高清到无码 )十年视频开发项目

    本文转载自Android 视频直播 ( 从快播到直播,从高清到无码 )十年视频开发项目,截取其中技术概念比较相关的部分,并做了重新的排版. 视频和直播的准备: android-java层:camera ...

  7. 无人驾驶汽车系统入门(十八)——使用pure pursuit实现无人车轨迹追踪

    无人驾驶汽车系统入门(十八)--使用pure pursuit实现无人车轨迹追踪 对于无人车辆来说,在规划好路径以后(这个路径我们通常称为全局路径),全局路径由一系列路径点构成,这些路径点只要包含空间位 ...

  8. 前端简单入门第十八讲 使用jQuery实现表格的隔行换色

    还记得之前我使用JavaScript来实现表格的隔行换色效果吗?如果读者初次翻阅本文,可记得看看前端简单入门第十二讲 使用JavaScript完成后台数据展示表格的隔行换色!现在我就来使用jQuery ...

  9. 布尔教育mysql优化_布尔教育燕十八mysql优化视频课件源码分享

    目前数据库是大多数系统进行数据存储的基础组件,数据库的效率对系统的稳定和效率有着至关重要的影响:为了有更好的用户体验,数据库的优化显得异常重要.那么我们要从那些方面对我们的数据库进行优化呢?让我们在& ...

最新文章

  1. 已拦截跨源请求:同源策略禁止读取位于XXXXXXXXXXXXXXXX/demo_test.txt 的远程资源。(原因:CORS 请求不是 http)
  2. 如何确定h.264的码率
  3. 字符串固定长度 易语言_易语言字符串操作源码
  4. Google比Baidu快(发一个无聊的帖)
  5. 大学计算机四级网络工程师考试内容,收藏!计算机四级网络工程师考试内容
  6. 文字跳跃率与图片跳跃率
  7. 机房动力环境监测解决方案
  8. GIS添加图层、查询详细
  9. Abp Vnext修改密码强度
  10. mysql 1.4安装步骤_从零开始搭建系统1.4——MySql安装及配置
  11. Linux中RPM、YUN和克隆
  12. 微博情感分析的表情符号平滑语言模型(A11, AAAI2012)
  13. 什么?RecyclerView中获取点击位置的接口被废弃了?
  14. Feign详解4-Contract 源码
  15. windows下使能/关闭硬件
  16. ArcGIS基础:实现 xian1980转换为CGCS2000
  17. 小米网抢购系统开发实践阅读心得
  18. 【论文写作】图像分割学术论文中常用词汇记录
  19. AspectJ切面自定义注解实现参数分组校验——基础概念(2)
  20. 优化网站的几种常见手段 大幅度降低Load time时间

热门文章

  1. 编程语言 - 强弱/动静态类型 - 整理
  2. org.apache.ibatis.binding.BindingException: Invalid bound statement (not found):的三种解决方式
  3. 以匠心守初心!百望云荣膺人民网“第十九届人民匠心飞跃奖”
  4. 如何设置Windows扩展屏幕,扩展屏幕和主屏有何区别,如何优化使用扩展屏幕?
  5. yolo 算法中的IOU算法程序与原理解读
  6. vue项目手机端适配
  7. Excel分组行转列(Power Query透视列,一维表转二维表)
  8. 如何有效提高营销型企业官网客户成交率?
  9. 高德地图api调用demo_高德地图定位如何调用api?
  10. 第一次用python编写的小程序