(十九)AI虚拟拍照、AI虚拟旅游、AI虚拟摄像头,实时抠像、摄像头背景移除_实时抠像摄像头-程序员宅基地

技术标签: 人工智能  Python AI研究  

(十九)AI虚拟拍照、AI虚拟旅游、AI虚拟摄像头,实时抠像、摄像头背景移除

本文代码实现了对摄像头视频的抠像处理,并把人像与背景图融合在一起,可以足不出户,即可拍出精美的旅游风景照片。省去了逐张PS的麻烦;

可以手势自动拍照,省去了按按钮的麻烦;

由于需要实时处理,必须在有GPU的电脑上运行,仅支持英伟达的显卡。

也可以把合成后的摄像映射在一个虚拟摄像头(AI_Camera),此虚拟摄像头可以被各种网络会议软件使用;

还可以把拍的照片自动上传百度,供人查看下载;

在这里插入图片描述

可运行的软件打包上传了网盘:
链接: https://pan.baidu.com/s/1Zlm81gs0yB4djGa8qhGXtg?pwd=8888

本文与前几篇博文关联性较强,请事先阅读前几篇。 对此文感兴趣的可以加微深入探讨:herbert156

话不多说上代码:
界面部分:

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

# Form implementation generated from reading ui file 'AI_Shoot_UI.ui'
#
# Created by: PyQt5 UI code generator 5.15.2
#
# 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_v_cam(object):
    def setupUi(self, v_cam):
        v_cam.setObjectName("v_cam")
        v_cam.resize(883, 528)
        self.horizontalLayoutWidget = QtWidgets.QWidget(v_cam)
        self.horizontalLayoutWidget.setGeometry(QtCore.QRect(10, 10, 861, 241))
        font = QtGui.QFont()
        font.setFamily("宋体")
        font.setPointSize(9)
        self.horizontalLayoutWidget.setFont(font)
        self.horizontalLayoutWidget.setObjectName("horizontalLayoutWidget")
        self.horizontalLayout = QtWidgets.QHBoxLayout(self.horizontalLayoutWidget)
        self.horizontalLayout.setContentsMargins(0, 0, 0, 0)
        self.horizontalLayout.setObjectName("horizontalLayout")
        self.my_label1 = QtWidgets.QLabel(self.horizontalLayoutWidget)
        font = QtGui.QFont()
        font.setFamily("宋体")
        font.setPointSize(9)
        self.my_label1.setFont(font)
        self.my_label1.setObjectName("my_label1")
        self.horizontalLayout.addWidget(self.my_label1)
        self.my_label2 = QtWidgets.QLabel(self.horizontalLayoutWidget)
        font = QtGui.QFont()
        font.setFamily("宋体")
        font.setPointSize(9)
        self.my_label2.setFont(font)
        self.my_label2.setObjectName("my_label2")
        self.horizontalLayout.addWidget(self.my_label2)
        self.option_win = QtWidgets.QGroupBox(v_cam)
        self.option_win.setGeometry(QtCore.QRect(10, 270, 861, 111))
        font = QtGui.QFont()
        font.setFamily("宋体")
        font.setPointSize(9)
        self.option_win.setFont(font)
        self.option_win.setObjectName("option_win")
        self.outButton = QtWidgets.QPushButton(self.option_win)
        self.outButton.setGeometry(QtCore.QRect(10, 20, 61, 23))
        font = QtGui.QFont()
        font.setFamily("宋体")
        font.setPointSize(9)
        self.outButton.setFont(font)
        self.outButton.setObjectName("outButton")
        self.bkfileButton = QtWidgets.QPushButton(self.option_win)
        self.bkfileButton.setGeometry(QtCore.QRect(10, 50, 61, 23))
        font = QtGui.QFont()
        font.setFamily("宋体")
        font.setPointSize(9)
        self.bkfileButton.setFont(font)
        self.bkfileButton.setObjectName("bkfileButton")
        self.txt2 = QtWidgets.QLabel(self.option_win)
        self.txt2.setGeometry(QtCore.QRect(80, 23, 251, 16))
        font = QtGui.QFont()
        font.setFamily("宋体")
        font.setPointSize(9)
        self.txt2.setFont(font)
        self.txt2.setObjectName("txt2")
        self.txt3 = QtWidgets.QLabel(self.option_win)
        self.txt3.setGeometry(QtCore.QRect(80, 53, 251, 16))
        font = QtGui.QFont()
        font.setFamily("宋体")
        font.setPointSize(9)
        self.txt3.setFont(font)
        self.txt3.setObjectName("txt3")
        self.checkBox3 = QtWidgets.QCheckBox(self.option_win)
        self.checkBox3.setGeometry(QtCore.QRect(11, 82, 68, 16))
        font = QtGui.QFont()
        font.setFamily("宋体")
        font.setPointSize(9)
        self.checkBox3.setFont(font)
        self.checkBox3.setObjectName("checkBox3")
        self.txt4 = QtWidgets.QLabel(self.option_win)
        self.txt4.setGeometry(QtCore.QRect(81, 82, 51, 16))
        font = QtGui.QFont()
        font.setFamily("宋体")
        font.setPointSize(9)
        self.txt4.setFont(font)
        self.txt4.setObjectName("txt4")
        self.red = QtWidgets.QLabel(self.option_win)
        self.red.setGeometry(QtCore.QRect(141, 82, 16, 16))
        font = QtGui.QFont()
        font.setFamily("宋体")
        font.setPointSize(9)
        self.red.setFont(font)
        self.red.setObjectName("red")
        self.blue = QtWidgets.QLabel(self.option_win)
        self.blue.setGeometry(QtCore.QRect(243, 82, 16, 16))
        font = QtGui.QFont()
        font.setFamily("宋体")
        font.setPointSize(9)
        self.blue.setFont(font)
        self.blue.setObjectName("blue")
        self.green = QtWidgets.QLabel(self.option_win)
        self.green.setGeometry(QtCore.QRect(191, 82, 16, 16))
        font = QtGui.QFont()
        font.setFamily("宋体")
        font.setPointSize(9)
        self.green.setFont(font)
        self.green.setObjectName("green")
        self.red_e = QtWidgets.QLineEdit(self.option_win)
        self.red_e.setGeometry(QtCore.QRect(158, 80, 31, 20))
        font = QtGui.QFont()
        font.setFamily("宋体")
        font.setPointSize(9)
        self.red_e.setFont(font)
        self.red_e.setObjectName("red_e")
        self.blue_e = QtWidgets.QLineEdit(self.option_win)
        self.blue_e.setGeometry(QtCore.QRect(260, 80, 31, 20))
        font = QtGui.QFont()
        font.setFamily("宋体")
        font.setPointSize(9)
        self.blue_e.setFont(font)
        self.blue_e.setObjectName("blue_e")
        self.green_e = QtWidgets.QLineEdit(self.option_win)
        self.green_e.setGeometry(QtCore.QRect(208, 80, 31, 20))
        font = QtGui.QFont()
        font.setFamily("宋体")
        font.setPointSize(9)
        self.green_e.setFont(font)
        self.green_e.setObjectName("green_e")
        self.camera_lbl = QtWidgets.QLabel(self.option_win)
        self.camera_lbl.setGeometry(QtCore.QRect(420, 20, 81, 16))
        font = QtGui.QFont()
        font.setFamily("宋体")
        font.setPointSize(9)
        self.camera_lbl.setFont(font)
        self.camera_lbl.setObjectName("camera_lbl")
        self.camera_comboBox = QtWidgets.QComboBox(self.option_win)
        self.camera_comboBox.setGeometry(QtCore.QRect(490, 17, 141, 22))
        font = QtGui.QFont()
        font.setFamily("宋体")
        font.setPointSize(9)
        self.camera_comboBox.setFont(font)
        self.camera_comboBox.setObjectName("camera_comboBox")
        self.camera_lbl_2 = QtWidgets.QLabel(self.option_win)
        self.camera_lbl_2.setGeometry(QtCore.QRect(420, 50, 81, 16))
        font = QtGui.QFont()
        font.setFamily("宋体")
        font.setPointSize(9)
        self.camera_lbl_2.setFont(font)
        self.camera_lbl_2.setObjectName("camera_lbl_2")
        self.camera_w_h = QtWidgets.QComboBox(self.option_win)
        self.camera_w_h.setGeometry(QtCore.QRect(490, 47, 141, 22))
        font = QtGui.QFont()
        font.setFamily("宋体")
        font.setPointSize(9)
        self.camera_w_h.setFont(font)
        self.camera_w_h.setObjectName("camera_w_h")
        self.camera_lbl_3 = QtWidgets.QLabel(self.option_win)
        self.camera_lbl_3.setGeometry(QtCore.QRect(420, 80, 71, 16))
        font = QtGui.QFont()
        font.setFamily("宋体")
        font.setPointSize(9)
        self.camera_lbl_3.setFont(font)
        self.camera_lbl_3.setObjectName("camera_lbl_3")
        self.open_fold = QtWidgets.QPushButton(self.option_win)
        self.open_fold.setGeometry(QtCore.QRect(340, 17, 61, 23))
        font = QtGui.QFont()
        font.setFamily("宋体")
        font.setPointSize(9)
        self.open_fold.setFont(font)
        self.open_fold.setObjectName("open_fold")
        self.chk_backfile = QtWidgets.QPushButton(self.option_win)
        self.chk_backfile.setGeometry(QtCore.QRect(340, 49, 61, 23))
        font = QtGui.QFont()
        font.setFamily("宋体")
        font.setPointSize(9)
        self.chk_backfile.setFont(font)
        self.chk_backfile.setObjectName("chk_backfile")
        self.real_camera_w_h = QtWidgets.QLabel(self.option_win)
        self.real_camera_w_h.setGeometry(QtCore.QRect(488, 79, 71, 16))
        font = QtGui.QFont()
        font.setFamily("宋体")
        font.setPointSize(9)
        self.real_camera_w_h.setFont(font)
        self.real_camera_w_h.setObjectName("real_camera_w_h")
        self.camera_lbl_4 = QtWidgets.QLabel(self.option_win)
        self.camera_lbl_4.setGeometry(QtCore.QRect(667, 78, 91, 20))
        font = QtGui.QFont()
        font.setFamily("宋体")
        font.setPointSize(9)
        self.camera_lbl_4.setFont(font)
        self.camera_lbl_4.setObjectName("camera_lbl_4")
        self.frame_rate = QtWidgets.QLabel(self.option_win)
        self.frame_rate.setGeometry(QtCore.QRect(760, 78, 71, 20))
        font = QtGui.QFont()
        font.setFamily("宋体")
        font.setPointSize(9)
        self.frame_rate.setFont(font)
        self.frame_rate.setObjectName("frame_rate")
        self.v_cam_chk = QtWidgets.QCheckBox(self.option_win)
        self.v_cam_chk.setEnabled(True)
        self.v_cam_chk.setGeometry(QtCore.QRect(653, 20, 191, 16))
        font = QtGui.QFont()
        font.setFamily("宋体")
        font.setPointSize(9)
        self.v_cam_chk.setFont(font)
        self.v_cam_chk.setObjectName("v_cam_chk")
        self.camera_lbl_5 = QtWidgets.QLabel(self.option_win)
        self.camera_lbl_5.setGeometry(QtCore.QRect(667, 50, 91, 16))
        font = QtGui.QFont()
        font.setFamily("宋体")
        font.setPointSize(9)
        self.camera_lbl_5.setFont(font)
        self.camera_lbl_5.setObjectName("camera_lbl_5")
        self.cam_frame_rate = QtWidgets.QLabel(self.option_win)
        self.cam_frame_rate.setGeometry(QtCore.QRect(760, 47, 61, 20))
        font = QtGui.QFont()
        font.setFamily("宋体")
        font.setPointSize(9)
        self.cam_frame_rate.setFont(font)
        self.cam_frame_rate.setObjectName("cam_frame_rate")
        self.groupBox_2 = QtWidgets.QGroupBox(v_cam)
        self.groupBox_2.setGeometry(QtCore.QRect(10, 465, 301, 51))
        font = QtGui.QFont()
        font.setFamily("宋体")
        font.setPointSize(9)
        self.groupBox_2.setFont(font)
        self.groupBox_2.setObjectName("groupBox_2")
        self.checkBox1 = QtWidgets.QCheckBox(self.groupBox_2)
        self.checkBox1.setGeometry(QtCore.QRect(16, 22, 81, 16))
        font = QtGui.QFont()
        font.setFamily("宋体")
        font.setPointSize(9)
        self.checkBox1.setFont(font)
        self.checkBox1.setObjectName("checkBox1")
        self.checkBox_fullwin = QtWidgets.QCheckBox(self.groupBox_2)
        self.checkBox_fullwin.setGeometry(QtCore.QRect(173, 22, 81, 16))
        font = QtGui.QFont()
        font.setFamily("宋体")
        font.setPointSize(9)
        self.checkBox_fullwin.setFont(font)
        self.checkBox_fullwin.setObjectName("checkBox_fullwin")
        self.fullwinButton = QtWidgets.QPushButton(self.groupBox_2)
        self.fullwinButton.setGeometry(QtCore.QRect(250, 20, 31, 21))
        font = QtGui.QFont()
        font.setFamily("宋体")
        font.setPointSize(9)
        self.fullwinButton.setFont(font)
        self.fullwinButton.setObjectName("fullwinButton")
        self.fullwinButton0 = QtWidgets.QPushButton(self.groupBox_2)
        self.fullwinButton0.setGeometry(QtCore.QRect(93, 20, 31, 21))
        font = QtGui.QFont()
        font.setFamily("宋体")
        font.setPointSize(9)
        self.fullwinButton0.setFont(font)
        self.fullwinButton0.setObjectName("fullwinButton0")
        self.shootButton = QtWidgets.QPushButton(v_cam)
        self.shootButton.setGeometry(QtCore.QRect(380, 471, 51, 41))
        font = QtGui.QFont()
        font.setFamily("宋体")
        font.setPointSize(9)
        self.shootButton.setFont(font)
        self.shootButton.setObjectName("shootButton")
        self.startButton = QtWidgets.QPushButton(v_cam)
        self.startButton.setGeometry(QtCore.QRect(470, 480, 71, 23))
        font = QtGui.QFont()
        font.setFamily("宋体")
        font.setPointSize(9)
        self.startButton.setFont(font)
        self.startButton.setObjectName("startButton")
        self.stopButton = QtWidgets.QPushButton(v_cam)
        self.stopButton.setGeometry(QtCore.QRect(570, 480, 71, 23))
        font = QtGui.QFont()
        font.setFamily("宋体")
        font.setPointSize(9)
        self.stopButton.setFont(font)
        self.stopButton.setObjectName("stopButton")
        self.helpButton = QtWidgets.QPushButton(v_cam)
        self.helpButton.setGeometry(QtCore.QRect(680, 480, 81, 23))
        font = QtGui.QFont()
        font.setFamily("宋体")
        font.setPointSize(9)
        self.helpButton.setFont(font)
        self.helpButton.setObjectName("helpButton")
        self.quitButton = QtWidgets.QPushButton(v_cam)
        self.quitButton.setGeometry(QtCore.QRect(800, 480, 71, 23))
        font = QtGui.QFont()
        font.setFamily("宋体")
        font.setPointSize(9)
        self.quitButton.setFont(font)
        self.quitButton.setObjectName("quitButton")
        self.groupBox_3 = QtWidgets.QGroupBox(v_cam)
        self.groupBox_3.setGeometry(QtCore.QRect(10, 400, 861, 51))
        font = QtGui.QFont()
        font.setFamily("Agency FB")
        font.setPointSize(9)
        self.groupBox_3.setFont(font)
        self.groupBox_3.setObjectName("groupBox_3")
        self.spinBox = QtWidgets.QSpinBox(self.groupBox_3)
        self.spinBox.setGeometry(QtCore.QRect(240, 20, 31, 16))
        font = QtGui.QFont()
        font.setFamily("宋体")
        font.setPointSize(9)
        self.spinBox.setFont(font)
        self.spinBox.setMinimum(1)
        self.spinBox.setMaximum(15)
        self.spinBox.setProperty("value", 3)
        self.spinBox.setObjectName("spinBox")
        self.delay_comboBox = QtWidgets.QComboBox(self.groupBox_3)
        self.delay_comboBox.setGeometry(QtCore.QRect(90, 18, 31, 22))
        font = QtGui.QFont()
        font.setFamily("宋体")
        font.setPointSize(9)
        self.delay_comboBox.setFont(font)
        self.delay_comboBox.setObjectName("delay_comboBox")
        self.delay_lbl = QtWidgets.QLabel(self.groupBox_3)
        self.delay_lbl.setGeometry(QtCore.QRect(10, 20, 81, 16))
        font = QtGui.QFont()
        font.setFamily("宋体")
        font.setPointSize(9)
        self.delay_lbl.setFont(font)
        self.delay_lbl.setObjectName("delay_lbl")
        self.hand_shoot = QtWidgets.QCheckBox(self.groupBox_3)
        self.hand_shoot.setEnabled(True)
        self.hand_shoot.setGeometry(QtCore.QRect(780, 20, 68, 16))
        font = QtGui.QFont()
        font.setFamily("宋体")
        font.setPointSize(9)
        self.hand_shoot.setFont(font)
        self.hand_shoot.setObjectName("hand_shoot")
        self.auto_chg_bk = QtWidgets.QCheckBox(self.groupBox_3)
        self.auto_chg_bk.setEnabled(True)
        self.auto_chg_bk.setGeometry(QtCore.QRect(139, 20, 101, 16))
        font = QtGui.QFont()
        font.setFamily("宋体")
        font.setPointSize(9)
        self.auto_chg_bk.setFont(font)
        self.auto_chg_bk.setObjectName("auto_chg_bk")
        self.txt2_3 = QtWidgets.QLabel(self.groupBox_3)
        self.txt2_3.setGeometry(QtCore.QRect(288, 20, 91, 16))
        font = QtGui.QFont()
        font.setFamily("宋体")
        font.setPointSize(9)
        self.txt2_3.setFont(font)
        self.txt2_3.setObjectName("txt2_3")
        self.bk_file_dir = QtWidgets.QLabel(self.groupBox_3)
        self.bk_file_dir.setGeometry(QtCore.QRect(370, 20, 391, 16))
        font = QtGui.QFont()
        font.setFamily("宋体")
        font.setPointSize(9)
        self.bk_file_dir.setFont(font)
        self.bk_file_dir.setText("")
        self.bk_file_dir.setObjectName("bk_file_dir")

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

    def retranslateUi(self, v_cam):
        _translate = QtCore.QCoreApplication.translate
        v_cam.setWindowTitle(_translate("v_cam", "AI虚拟拍照系统"))
        self.my_label1.setText(_translate("v_cam", "本区域,显示的是原始视频缩略图..."))
        self.my_label2.setText(_translate("v_cam", "本区域,显示的是替换后的缩略图..."))
        self.option_win.setTitle(_translate("v_cam", "操作设置"))
        self.outButton.setText(_translate("v_cam", "拍照存盘"))
        self.bkfileButton.setText(_translate("v_cam", "背景文件"))
        self.txt2.setText(_translate("v_cam", "拍照存盘"))
        self.txt3.setText(_translate("v_cam", "背景文件"))
        self.checkBox3.setText(_translate("v_cam", "纯色背景"))
        self.txt4.setText(_translate("v_cam", "纯色背景"))
        self.red.setText(_translate("v_cam", "红"))
        self.blue.setText(_translate("v_cam", "蓝"))
        self.green.setText(_translate("v_cam", "绿"))
        self.camera_lbl.setText(_translate("v_cam", "硬件摄像头:"))
        self.camera_lbl_2.setText(_translate("v_cam", "分辨率设置:"))
        self.camera_lbl_3.setText(_translate("v_cam", "实际分辨率:"))
        self.open_fold.setText(_translate("v_cam", "浏览照片"))
        self.chk_backfile.setText(_translate("v_cam", "查看背景"))
        self.real_camera_w_h.setText(_translate("v_cam", "实际分辨率"))
        self.camera_lbl_4.setText(_translate("v_cam", "AI算法处理帧率:"))
        self.frame_rate.setText(_translate("v_cam", "0.0 FPS"))
        self.v_cam_chk.setText(_translate("v_cam", "启动虚拟摄像头:AI_Camera"))
        self.camera_lbl_5.setText(_translate("v_cam", "摄像头读取帧率:"))
        self.cam_frame_rate.setText(_translate("v_cam", "0.0 FPS"))
        self.groupBox_2.setTitle(_translate("v_cam", "显示设置"))
        self.checkBox1.setText(_translate("v_cam", "实时展示->"))
        self.checkBox_fullwin.setText(_translate("v_cam", "拍后显示->"))
        self.fullwinButton.setText(_translate("v_cam", "全屏"))
        self.fullwinButton0.setText(_translate("v_cam", "全屏"))
        self.shootButton.setText(_translate("v_cam", "拍照"))
        self.startButton.setText(_translate("v_cam", "运行"))
        self.stopButton.setText(_translate("v_cam", "停止"))
        self.helpButton.setText(_translate("v_cam", "帮助"))
        self.quitButton.setText(_translate("v_cam", "退出"))
        self.groupBox_3.setTitle(_translate("v_cam", "拍照设置"))
        self.delay_lbl.setText(_translate("v_cam", "拍照延时(秒):"))
        self.hand_shoot.setText(_translate("v_cam", "手势拍照"))
        self.auto_chg_bk.setText(_translate("v_cam", "自动换背景(秒)"))
        self.txt2_3.setText(_translate("v_cam", "背景文件目录:"))

主运行代码:

#视频背景替换工具V1.0
import keyboard
import numpy as np
import os, datetime, sys, time, threading, GPUtil
os.environ['OPENCV_VIDEOIO_PRIORITY_MSMF'] = '0'    #加快打开摄像头的速度
import cv2

import pyvirtualcam  # https://github.com/letmaik/pyvirtualcam
import http.client, win32api, win32con
import configparser as configparser
from PIL import Image,ImageDraw,ImageFont
from bypy import ByPy
from mediapipe import solutions
from PyQt5 import QtWidgets, QtGui
from PyQt5.QtWidgets import QWidget,QMessageBox,QFileDialog,QApplication
from PyQt5.QtCore import Qt, QTimer, QThread, pyqtSlot, pyqtSignal
from PyQt5.QtGui import QPixmap,QIntValidator
from PyCameraList.camera_device import list_video_devices

DEBUG_FLAG = False   #调试用
# DEBUG_FLAG = True   #调试用
from AI_Shoot_UI import Ui_v_cam

def is_contains_chinese():  #运行目录不能包含中文
    strs = os.getcwd()
    for _char in strs:
        if '\u4e00' <= _char <= '\u9fa5':
            win32api.MessageBox(0, f"软件安装目录【{strs}】不能包含中文,\n请移动到其他目录再运行......", '运行错误提示', win32con.MB_OK)
            sys.exit()

def get_web_time(host): #获取网络时间,并设置系统时间
    try:
        conn=http.client.HTTPConnection(host,timeout=20)
        conn.request("GET", "/")
        r=conn.getresponse()
    except:
        win32api.MessageBox(0, f"网络连接超时...", '运行错误提示', win32con.MB_OK); sys.exit()
    ts=  r.getheader('date') #获取http头date部分
    ltime= time.strptime(ts[5:25], "%d %b %Y %H:%M:%S")   #将GMT时间转换成北京时间
    ttime=time.localtime(time.mktime(ltime)+8*60*60)
    date = "%u%02u%02u" % (ttime.tm_year, ttime.tm_mon, ttime.tm_mday)
    return date

#检测显卡是否是Nvidia,并查看型号是否支持
try:
    gpus = GPUtil.getGPUs(); gpu_list = []; gpu_i = 0; gpu_available = 0
    for g in gpus: gpu_list.append([g.name, g.memoryTotal])
    GPU_nums = len(gpu_list)  #显卡数量
    print("【显卡数量】检测出的Nvidia GPU数量:%d个:" %GPU_nums)
    for GPU_Info in gpu_list:
        gpu_i += 1; GPU_name = GPU_Info[0]  #显卡名称
        GPU_memsize = GPU_Info[1]/1024  # 显卡总的显存大小
        print("【显卡:%d】型号:%s | 显存:%dG"%(gpu_i,GPU_name,GPU_memsize))
        if ('GTX' in GPU_name or 'RTX' in GPU_name): gpu_available += 1
    if gpu_available > 0: print("【可用数量】AI处理的可用GPU:%d个:" %gpu_i)
    else:
        win32api.MessageBox(0, "您的GPU是本软件不支持的Nvidia显卡,无法运行本软件!", '运行错误提示',
                            win32con.MB_OK); sys.exit()
except:
    win32api.MessageBox(0, "您的GPU是本软件不支持的显卡,无法运行本软件!", '运行错误提示',
                        win32con.MB_OK); sys.exit()

#读取配置文件AI_Shoot.ini
cfg = configparser.ConfigParser()
if os.path.exists('AI_Shoot.ini'):
    cfg.read('AI_Shoot.ini',encoding="utf-8")

    apikey = cfg.get('BAIDU', 'apikey')
    secretkey = cfg.get('BAIDU', 'secretkey')

    cam_res = cfg.get('AI_SHOOT', 'cam_res')

    autorun = cfg.getboolean('AI_SHOOT', 'autorun')
    change_bg_file = cfg.getboolean('AI_SHOOT', 'change_bg_file')
    hand_shoot_flag = cfg.getboolean('AI_SHOOT', 'hand_shoot_flag')
    upload_baidu = cfg.getboolean('AI_SHOOT', 'upload_baidu')
    full_screen= cfg.getboolean('AI_SHOOT', 'full_screen')
    hide_window= cfg.getboolean('AI_SHOOT', 'hide_window')
    show_scan_code= cfg.getboolean('AI_SHOOT', 'show_scan_code')

    camera_no = cfg.getint('AI_SHOOT', 'camera_no')
    delay_sec = cfg.getint('AI_SHOOT', 'delay_sec')
    chg_bk_counter = cfg.getint('AI_SHOOT', 'chg_bk_counter')
else:
    cam_res='1920x1080'
    camera_no = 0
    delay_sec = 3
    chg_bk_counter = 5
    change_bg_file = False
    hand_shoot_flag = False
    upload_baidu = False
    full_screen = False
    hide_window = False

Win_Open_Full = False
Win_Open_Normal = False
shoot_flag = False
timer_counter = 0

work_path = os.getcwd()+'/kx'; files = []
bg_file=work_path + '/bk.jpg'; out_dir=work_path + '/jpg'
bg_file_list = []; bk_file_no = 0
thread_img = cv2.imread("start_img.jpg")
scan_code_img = Image.open(r'sacn_code.png').resize((200, 200))

run_flag = 0; Box1_flag = False; Box3_flag = False
bk_pix = [8,188,8]; bk_img = np.zeros((1080, 1920, 3), np.uint8)  # Creat a Image
bk_img[:] = bk_pix; filesnums = 1 ; stop_flag = False

cam_lists = list_video_devices()
cam_list = []
cam_fps = 20.0; fr_rate = 10.0
for cams in cam_lists: cam_list.append(cams[1])

my_title = "AI虚拟拍照系统"
pil_img = Image.open("start_img.jpg")
ImageDraw.Draw(pil_img).text((350,200), my_title, (255,255,255),font=ImageFont.truetype("msyh.ttc", 18))
ImageDraw.Draw(pil_img).text((410,330), "正在加载AI模型,请稍后 ......", (255,255,255),font=ImageFont.truetype("msyh.ttc", 16))
img_s = cv2.cvtColor(np.array(pil_img), cv2.COLOR_RGB2BGR)

def showpic():  # 以下代码显示软件初始界面
    global ret, frame
    while run_flag == 0:
        cv2.imshow("AI Camera System", img_s)
        cv2.waitKey(100)
    cv2.destroyAllWindows()
t = threading.Thread(target=showpic)
t.start()

if upload_baidu:
    baidu_yun = ByPy()
    try: baidu_yun.refreshtoken()
    except: print('刷新百度网盘的授权码,发生错误....')

mpHands = solutions.hands   #手势检测
hands = mpHands.Hands(static_image_mode=False, max_num_hands=2, min_detection_confidence=0.5, min_tracking_confidence=0.5)
mp_pose = solutions.pose   #姿势检测
pose = mp_pose.Pose(static_image_mode=True, smooth_landmarks=True, min_detection_confidence=0.5, min_tracking_confidence=0.5)

# class upload_baidu_disk(QThread):
#     def __init__(self, save_name):
#         super(upload_baidu_disk, self).__init__()
#         self.save_name = save_name
#         print(save_name)
#         try:
#             baidu_yun.upload(self.save_name, remotepath='AI摄影', ondup="newcopy")
#         except:
#             print('图片上传百度网盘,发生错误....')
#     def run(self): pass
def upload_baidu_disk(save_name):
    try: baidu_yun.upload(save_name, remotepath='AI摄影', ondup="newcopy")
    except: print('图片上传百度网盘,发生错误....')

def win_on_off():
    if winshot.isHidden():
        winshot.show()
    else:
        winshot.hide()
    print("Switch the Windows!")
keyboard.add_hotkey('ctrl+alt+enter', win_on_off)

class full_win(QWidget):
    def __init__(self):
        super(full_win, self).__init__()
        palette = QtGui.QPalette()
        #palette1.setColor(palette1.Background, QtGui.QColor(0, 0, 0))
        palette.setBrush(self.backgroundRole(), QtGui.QBrush(QtGui.QPixmap(bg_file)))
        self.setPalette(palette)
        self.setWindowTitle("Full_Windows")
        self.setGeometry(320, 180, 640, 360)

        if full_screen:
            desktop = QApplication.desktop()
            screen_count = desktop.screenCount()
            if screen_count > 1:
                self.setGeometry(desktop.screenGeometry(1)); self.showFullScreen()
            else:
                self.setGeometry(desktop.screenGeometry(0)); self.showFullScreen()

        #self.setWindowFlags(Qt.FramelessWindowHint)

class result_win(QWidget):
    def __init__(self):
        super(result_win, self).__init__()
        palette = QtGui.QPalette()
        palette.setBrush(self.backgroundRole(), QtGui.QBrush(QtGui.QPixmap(bg_file)))
        self.setPalette(palette)
        self.setWindowTitle("Result_Windows")
        self.setGeometry(320, 180, 640, 360)

class camera_thread(QThread):
    # sinout = pyqtSignal(str)
    def __init__(self, winshot):
        super(camera_thread, self).__init__()
        self.main_win = winshot

    def run(self):
        global delay_sec, chg_bk_counter, timer_counter
        global thread_img, stop_flag, cam_fps
        while not stop_flag:
            t0 = time.time()
            try: ret, thread_img = self.main_win.cap.read()
            except Exception as errmsg:
                print(repr(errmsg))
                self.main_win.show_error('读取摄像头(编号:%d), 出现错误(Line204)!' % camera_no)
                stop_flag = True; self.main_win.set_True_Btn(); return

            cam_delay = time.time() - t0
            # print(f'Fps:{1 / cam_delay:0.2f}',end="\r")
            try: cam_fps = 1/cam_delay
            except: pass;   #print('float division by zero')
            delay_sleep = 0.04 - cam_delay
            if delay_sleep <= 0: delay_sleep = 0
            else:
                cam_fps = 1 / delay_sleep
                time.sleep(delay_sleep)

class hand_detect_thread(QThread):
        sinout = pyqtSignal(str)
        def __init__(self, winshot):
            super(hand_detect_thread, self).__init__()
            self.main_win = winshot
        def run(self):
            global delay_sec, chg_bk_counter, timer_counter, thread_img, stop_flag
            while not stop_flag:
                t0 = time.time()
                if self.main_win.hand_shoot.isChecked() and timer_counter <= 0:
                    imgRGB = cv2.cvtColor(cv2.flip(thread_img, 1), cv2.COLOR_BGR2RGB)
                    image_height, image_width, _ = np.shape(imgRGB)

                    pose_results = pose.process(imgRGB)
                    if pose_results.pose_landmarks:
                        p11 = pose_results.pose_landmarks.landmark[11].y
                        p12 = pose_results.pose_landmarks.landmark[12].y
                        p15 = pose_results.pose_landmarks.landmark[15].y
                        p16 = pose_results.pose_landmarks.landmark[16].y

                        if p11 > p15 or p12 > p16:
                            hand_results = hands.process(imgRGB)
                            if hand_results.multi_hand_landmarks:
                                if timer_counter <= 0:
                                    # print("发送信号,启动拍照! ")
                                    self.sinout.emit('START')
                delay_sleep = 1/fr_rate - time.time() + t0
                if delay_sleep <= 0: delay_sleep = 0
                time.sleep(delay_sleep)

class Winshot(QWidget, Ui_v_cam):
    def __init__(self):
        super(Winshot, self).__init__()
        self.setupUi(self)
        global hwnd, run_flag

        palette1 = QtGui.QPalette()
        palette1.setColor(palette1.Background, QtGui.QColor(200, 200, 200))

        try: self.ai_shooting = cv2.imread('AI_Shooting.jpg')
        except: print('没找到文件:AI_Shooting.jpg')

        self.shoot_timer = QTimer(self)  # 拍照定时器
        self.shoot_timer.timeout.connect(self.shoot_timer_fuc)
        self.chg_bk_timer = QTimer(self)  # 换背景定时器
        self.chg_bk_timer.timeout.connect(self.chg_bk_timer_fuc)
        self.result_win_timer = QTimer(self)  # 拍后显示定时器
        self.result_win_timer.timeout.connect(self.result_win_timer_fuc)

        self.createLayout()
        self.stopButton.setEnabled(False)
        self.set_rgb_False()
        self.setPalette(palette1)
        self.setWindowTitle(my_title)
        self.setWindowFlags(Qt.WindowMinimizeButtonHint)
        if not hide_window: self.show()
        run_flag = 1

        if autorun: self.start_run()       #自动运行

    def hand_detect_signal(self):
        global delay_sec, chg_bk_counter
        # delay_sec = 3;
        # chg_bk_counter += 3
        self.shootrun()

    def get_cams_name(self):
        cameras = list_video_devices()
        cams_name = []
        for cams in cameras: cams_name.append(cams[1])
        return cams_name

    def result_win_timer_fuc(self):
        palette = QtGui.QPalette()
        palette.setBrush(self.backgroundRole(),
                         QtGui.QBrush(self.CvMatToQImage(
                         cv2.resize(self.ai_shooting,(my_result_win.width(), my_result_win.height())))))
        my_result_win.setPalette(palette)
        self.result_win_timer.stop()

    def chg_bk_timer_fuc(self):
        global chg_bk_counter, change_bg_file, bk_file_no, bg_file
        chg_bk_counter -= 1
        if chg_bk_counter <= 0:
            bg_file = bg_file_list[bk_file_no]
            bk_file_no += 1
            if bk_file_no >= len(bg_file_list): bk_file_no = 0
            change_bg_file = True
            chg_bk_counter = self.spinBox.value()
    def shoot_timer_fuc(self):
        global timer_counter, shoot_flag
        timer_counter -= 1
        if timer_counter < 0: timer_counter = 0

        try: red_color = int(255 * (delay_sec - timer_counter) / delay_sec)
        except: red_color = 111

        if red_color < 1 or red_color >255: red_color = 111
        self.shootButton.setStyleSheet("background-color:rgb(%d,97,22);font-size:30px;font-weight:bold"%red_color)
        self.shootButton.setText(str(timer_counter))

        if timer_counter <= 0:
            self.shoot_timer.stop()
            shoot_flag = True
            self.shootButton.setStyleSheet("background-color:rgb(207,97,22);font-size:20px;font-weight:bold")
            self.shootButton.setText('拍照')

    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个图片合并Image.composite
        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 two_pic_combine_PIL_Paste(self, back_img, fore_img):    #Image.alpha_composite
        back_img = self.CV2toPIL(back_img); fore_img = self.CV2toPIL(fore_img)
        return cv2.cvtColor(self.PILtoCV2(Image.alpha_composite(back_img, fore_img)), cv2.COLOR_BGRA2BGR)

    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 set_False_Btn(self):
        self.outButton.setEnabled(False);    self.shootButton.setEnabled(True)
        # self.bkfileButton.setEnabled(False);
        self.checkBox3.setEnabled(False)
        self.startButton.setEnabled(False); self.stopButton.setEnabled(True)
        self.quitButton.setEnabled(False)
        self.camera_comboBox.setEnabled(False)
        self.camera_w_h.setEnabled(False)

    def set_True_Btn(self):
        self.outButton.setEnabled(True);    self.shootButton.setEnabled(False)
        # self.bkfileButton.setEnabled(True);
        self.checkBox3.setEnabled(True)
        self.startButton.setEnabled(True); self.stopButton.setEnabled(False)
        self.quitButton.setEnabled(True)
        self.camera_comboBox.setEnabled(True)
        self.camera_w_h.setEnabled(True)

    @pyqtSlot()
    def start_run(self):
        global stop_flag, change_bg_file, bg_file, camera_no, shoot_flag
        global back_ground, thread_img, fr_rate, chg_bk_counter

        stop_flag = False;  shoot_flag = False; self.set_False_Btn()
        self.auto_chg_bk_fuc()  #检查自动更换背景

        if not Box3_flag:   #判断是否纯色背景
            try: back_ground = cv2.imdecode(np.fromfile(bg_file, dtype=np.uint8), -1)
            except: self.show_error('\n读取背景文件异常:文件不存在!   \n'); self.set_True_Btn(); return
            if back_ground is None: self.show_error('读取背景文件时,出现错误!\n原因:目录/文件名不能包含中文...... '); return
        else: back_ground = bk_img

        try: self.cap = cv2.VideoCapture(camera_no, cv2.CAP_ANY)  # 读取视频文件
        # try: self.cap = cv2.VideoCapture(camera_no, cv2.CAP_DSHOW)
        except Exception as errmsg:
            print(repr(errmsg)); self.show_error('读取摄像头-477, 出现错误...'); stop_flag = True; self.set_True_Btn(); return

        try:
            camera_w,camera_h = self.camera_w_h.currentText().split('x')
            fourcc = cv2.VideoWriter_fourcc('M', 'J', 'P', 'G')
            self.cap.set(cv2.CAP_PROP_FRAME_WIDTH, int(camera_w))
            self.cap.set(cv2.CAP_PROP_FRAME_HEIGHT, int(camera_h))
            self.cap.set(cv2.CAP_PROP_FOURCC, fourcc)
            # self.cap.set(cv2.CAP_PROP_FPS, 30)

            size_x = int(self.cap.get(cv2.CAP_PROP_FRAME_WIDTH))  # 视频流的帧宽度
            size_y = int(self.cap.get(cv2.CAP_PROP_FRAME_HEIGHT))  # 视频流的帧高度
            fps = self.cap.get(cv2.CAP_PROP_FPS)  # 帧率
            self.real_camera_w_h.setText(f'{size_x}x{size_y}')
        except Exception as errmsg:
            print(repr(errmsg)); self.show_error('读取摄像头-492, 出现错误...'); stop_flag = True; self.set_True_Btn(); return
        # print(size_x, size_y, fps)
        if size_x == 0 or size_y == 0:
            self.show_error('读取摄像头-496(编号:%d), 出现错误...' % camera_no);
            stop_flag = True; self.set_True_Btn(); return

        img1 = cv2.resize(back_ground, (1920, 1080))

        if size_x / size_y > 1.778: fx = 427 / size_x;  fy = fx  # 计算16:9的比例,以便缩放不变形
        else: fy = 240 / size_y;  fx = fy
        palette2 = QtGui.QPalette()
        palette3 = QtGui.QPalette()

        self.new_thread = hand_detect_thread(self)
        self.new_thread.sinout.connect(self.hand_detect_signal)
        self.new_thread.start()
        self.cam_thread = camera_thread(self)
        self.cam_thread.start()

        with pyvirtualcam.Camera(width=size_x, height=size_y, fps=20, backend='unitycapture') as cam:
            # print(f'Camera Name: {cam.device}')
            while True:
                if stop_flag: my_full_win.hide(); my_result_win.hide(); break
                t0 = time.time()

                if (not Box3_flag) and change_bg_file:
                    try:
                        back_ground = cv2.imdecode(np.fromfile(bg_file, dtype=np.uint8), -1)
                        img1 = cv2.resize(back_ground, (1920, 1080))
                        # print("背景文件改变...")
                        # img1 = back_ground
                    except:
                        self.show_error('\n读取背景文件异常:文件不存在!   \n')
                    if back_ground is None: self.show_error('读取背景文件时,出现错误!\n原因:目录/文件名不能包含中文...'); break
                    change_bg_file = False

                # if self.hand_shoot.isChecked() and timer_counter <= 0:
                #     # self.hand_detect(frame) #检测手掌
                #     self.shoot_timer.start(1000)

                frame = cv2.flip(thread_img, 1)

                h1, w1, _ = thread_img.shape     #扩大左右像素到16:9
                if w1/h1 < 1.7:
                    side_pix = int((h1*16/9-w1)/2)
                    frame = cv2.copyMakeBorder(frame, 0, 0, side_pix, side_pix,
                                               cv2.BORDER_CONSTANT, value=[200,200,200])

                if not DEBUG_FLAG:   #测试用语句
                    img2 = self.koutu(frame)
                else: img2 = frame
                img2 = cv2.resize(img2, (1920, 1080))

                try:
                    img3 = self.two_pic_combine_PIL_Paste(img1, img2)
                    # img3 = self.icanx_water_print(img3)
                 except Exception as errmsg:
                    print(repr(errmsg))
                    self.show_error('读取摄像头-560(编号:%d), 出现错误!' % camera_no)
                    stop_flag = True; self.set_True_Btn(); return

                if self.v_cam_chk.isChecked():
                    cam.send(cv2.cvtColor(img3, cv2.COLOR_BGR2RGB))     #发送到虚拟摄像头
                # cam.sleep_until_next_frame()
                show_img = img3

                if timer_counter > 0:
                    pil_img = self.CV2toPIL(img3)
                    # pos_x = size_x/2-200*1920/size_x
                    ImageDraw.Draw(pil_img).text((450, 870), "摆好姿势," + str(timer_counter)+"秒后拍照",
                                                 (250, 250, 250), font=ImageFont.truetype("msyh.ttc", 150))
                    show_img = self.PILtoCV2(pil_img)

                if Box1_flag:
                    if show_scan_code:  # 写提示文字
                        pil_img = self.CV2toPIL(show_img)
                        # pos_x = size_x/2-200*1920/size_x
                        ImageDraw.Draw(pil_img).text((720, 60), "举手拍照,扫码下载:",
                                                     (250, 250, 250), font=ImageFont.truetype("msyh.ttc", 100))
                        pil_img.paste(scan_code_img, (1680, 40, 1880, 240))  # 显示二维码
                        show_img = self.PILtoCV2(pil_img)
                    palette2.setBrush(self.backgroundRole(),QtGui.QBrush(self.CvMatToQImage(cv2.resize(show_img,
                                      (my_full_win.width(), my_full_win.height())))))
                    my_full_win.setPalette(palette2)

                cv2.waitKey(1)
                if shoot_flag:      #写拍照写盘,存百度网盘
                    save_name = out_dir + '/IMG_' + time.strftime("%y%m%d_%H%M%S", time.localtime())+'.JPG'
                    if not os.path.exists(out_dir): self.show_error('输出文件, 出现错误!\n文件目录可能不存在...')

                    try:
                        # cv2.imwrite(save_name, img3)
                        cv2.imencode('.jpg', img3)[1].tofile(save_name)
                    except: self.show_error('输出文件, 出现错误!\n文件目录可能不存在...')

                    if upload_baidu: threading.Thread(target=upload_baidu_disk, kwargs={
    'save_name':save_name}).start()

                    palette2.setColor(palette2.Background, QtGui.QColor(0,0,0))
                    my_full_win.setPalette(palette2)
                    cv2.waitKey(200)
                    if self.checkBox_fullwin.isChecked():
                        palette3.setBrush(self.backgroundRole(), QtGui.QBrush(self.CvMatToQImage(cv2.resize(img3,
                                        (my_result_win.width(), my_result_win.height())))))
                        my_result_win.setPalette(palette3)
                        self.result_win_timer.start(3000)
                    chg_bk_counter = 0
                    shoot_flag = False

                # t1 = time.time()
                self.my_label1.setPixmap(self.CvMatToQImage(cv2.resize(frame, (427, 240))))
                # self.my_label2.setPixmap(self.CvMatToQImage(cv2.resize(show_img, (0, 0), fx=fx, fy=fy)))
                self.my_label2.setPixmap(self.CvMatToQImage(cv2.resize(show_img, (427, 240))))

                # print(f't2:{(time.time() - t0):0.4f}')

                fr_rate = 1/(time.time() - t0)
                self.frame_rate.setText(f'{fr_rate:.1f} FPS')
                self.cam_frame_rate.setText(f'{cam_fps:.1f} FPS')

        self.cap.release()
        self.set_True_Btn()
        self.frame_rate.setText(f'0.0 FPS')
        self.real_camera_w_h.setText('0x0')
        self.my_label1.setPixmap(QPixmap("start_img.jpg"))
        self.my_label2.setPixmap(QPixmap("start_img.jpg"))

    @pyqtSlot()
    def shootrun(self):
        global shoot_flag,timer_counter, delay_sec, chg_bk_counter
        if delay_sec == 0 : shoot_flag = True
        else:
            chg_bk_counter += delay_sec
            self.shootButton.setStyleSheet("background-color:rgb(20,97,22);font-size:30px;font-weight:bold")
            self.shootButton.setText(str(delay_sec))
            timer_counter = delay_sec
            self.shoot_timer.start(1000)

    @pyqtSlot()
    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

    @pyqtSlot()
    def helpWin(self):
        str="\n\n\n1、【选择摄像头】选择电脑连接的物理摄像头编号;\n2、【拍照存盘】拍照后的JPG文件保存目录,文件名:IMG_日期_时间.JPG;\n"+\
        "3、【背景文件】选择后,人物视频的背景都被替换成此背景;\n4、【纯色背景】点选后,所有视频背景替换成纯色的;\n"+ \
        "5、【手势拍照】将手臂举过头顶,AI识别3秒后开始拍照;\n6、【实时显示】点选后,可在大屏幕上全屏显示;\n" + \
        "7、虚拟摄像头名称:AI_Camera,可以在腾讯会议、Zoom会议、OBS等软件中使用;\n\n\n"+ \
        "      本软件著作权归属:XXX        网址:www.xxx-x.com\n\n"
        QMessageBox.question(self, my_title, str, QMessageBox.Ok)

    @pyqtSlot()
    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:
            hands.close(); pose.close(); sys.exit()

    @pyqtSlot()
    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)

    # @pyqtSlot()
    def bkfileButton_fuc(self):
        global bg_file, change_bg_file
        bg_file, ok1 = QFileDialog.getOpenFileName(self,"选择背景图片文件",work_path,"*.jpg;;*.png;;*.gif")
        if bg_file == '': self.txt3.setText('请选择背景图片文件......')
        else: self.txt3.setText(bg_file); change_bg_file = True

    def click_camera_comboBox(self, text):
        global camera_no
        # self.camera_comboBox.addItems(self.get_cams_name())
        self.camera_comboBox.currentIndex()
        if 'OBS' in text or 'AI_Camera' in text:
            self.show_error("只能对物理摄像头进行抠像处理,请重新选择...")
            self.camera_comboBox.setCurrentIndex(-1)
        else:
            camera_no = self.camera_comboBox.currentIndex()

    def click_delay_comboBox(self, text):
        global delay_sec
        delay_sec = int(text)

    @pyqtSlot()
    def box_choose1(self):
        global Box1_flag
        if self.checkBox1.isChecked():
            Box1_flag = True; my_full_win.show()
        else:
            Box1_flag = False;my_full_win.hide()

    def checkBox_fullwin_func(self):
        if self.checkBox_fullwin.isChecked():
            my_result_win.show()
        else:
            my_result_win.hide()

    @pyqtSlot()
    def fullwinButton0_func(self):
        if self.checkBox1.isChecked():
            if my_full_win.isFullScreen():  my_full_win.showNormal()
            else: my_full_win.showFullScreen()

    def fullwinButton_func(self):
        if self.checkBox_fullwin.isChecked():
            if my_result_win.isFullScreen():  my_result_win.showNormal()
            else: my_result_win.showFullScreen()

            palette = QtGui.QPalette()
            palette.setBrush(self.backgroundRole(),
                             QtGui.QBrush(self.CvMatToQImage(
                             cv2.resize(self.ai_shooting,(my_result_win.width(), my_result_win.height())))))
            my_result_win.setPalette(palette)

    @pyqtSlot()
    def box_choose3(self):
        global Box3_flag
        if self.checkBox3.isChecked():
            self.txt3.setEnabled(False); self.bkfileButton.setEnabled(False)
            self.txt3.setText('已经选择纯色背景......')
            self.set_rgb_True()
            Box3_flag = True
        else:
            self.txt3.setEnabled(True);  self.bkfileButton.setEnabled(True)
            self.txt3.setText(bg_file)
            self.set_rgb_False()
            Box3_flag = False
    def set_rgb_False(self):
        self.red.setEnabled(False);     self.red_e.setEnabled(False); self.green.setEnabled(False)
        self.green_e.setEnabled(False); self.blue.setEnabled(False);  self.blue_e.setEnabled(False)
    def set_rgb_True(self):
        self.red.setEnabled(True);     self.red_e.setEnabled(True); self.green.setEnabled(True)
        self.green_e.setEnabled(True); self.blue.setEnabled(True);  self.blue_e.setEnabled(True)
    def red_e_fuc(self, text):
        if text =='': rgb = 0
        else: rgb = int(text)
        bk_pix[2] = rgb; bk_img[:] = bk_pix
        self.txt4.setPixmap(self.CvMatToQImage(cv2.resize(bk_img, (50, 18))))
    def green_e_fuc(self, text):
        if text =='': rgb = 0
        else: rgb = int(text)
        bk_pix[1] = rgb; bk_img[:] = bk_pix
        self.txt4.setPixmap(self.CvMatToQImage(cv2.resize(bk_img, (50, 18))))
    def blue_e_fuc(self, text):
        if text =='': rgb = 0
        else: rgb = int(text)
        bk_pix[0] = rgb; bk_img[:] = bk_pix
        self.txt4.setPixmap(self.CvMatToQImage(cv2.resize(bk_img, (50, 18))))
    def open_fold_fuc(self):
        try: os.startfile(out_dir)
        except:pass
    def chk_bk_file_fuc(self):
        try: os.startfile(bg_file)
        except: pass

    def v_cam_chk_fuc(self):
        if self.v_cam_chk.isChecked():
            if not 'AI_Camera' in cam_list:
                win32api.MessageBox(0, "       首次运行,您必须安装AI_Camera虚拟摄像头才能正常使用!\n\n"
                                       "       请在安装目录下执行一次【安装虚拟摄像头.exe】即可。\n", '运行信息提示',
                                    win32con.MB_OK)
                self.v_cam_chk.setChecked(False)

    def auto_chg_bk_fuc(self):
        global bg_file_list, chg_bk_counter
        if self.auto_chg_bk.isChecked():
            if bg_file == '':
                self.show_error('\n读取背景文件异常,您必须至少选择1个背景文件... \n')
                self.auto_chg_bk.setChecked(False); return

            bg_file_list = []
            jpg_path = os.path.split(bg_file)[0]
            self.bk_file_dir.setText(jpg_path)
            for ff in os.listdir(jpg_path):
                jpg_file = jpg_path + '/' + ff
                if os.path.isfile(jpg_file): bg_file_list.append(jpg_file)
            # print(bg_file_list)
            chg_bk_counter = int(self.spinBox.value())
            self.chg_bk_timer.start(1000)
        else: self.chg_bk_timer.stop()

    def spinBox_fuc(self):
        global chg_bk_counter
        chg_bk_counter = int(self.spinBox.value())

    def createLayout(self):
        global Box1_flag
        self.my_label1.setPixmap(QPixmap("start_img.jpg"))
        self.my_label2.setPixmap(QPixmap("start_img.jpg"))
        # 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("本区域,显示的是替换后的缩略图...")

        if full_screen: self.checkBox1.setChecked(True); Box1_flag =True
        self.checkBox1.stateChanged.connect(self.box_choose1)
        self.checkBox_fullwin.stateChanged.connect(self.checkBox_fullwin_func)

        self.txt2.setText(out_dir);   self.txt3.setText(bg_file)
        self.bk_file_dir.setText(os.path.split(bg_file)[0])
        self.txt4.setPixmap(self.CvMatToQImage(cv2.resize(bk_img, (50, 18))))

        self.checkBox3.stateChanged.connect(self.box_choose3)
        self.v_cam_chk.stateChanged.connect(self.v_cam_chk_fuc)
        self.auto_chg_bk.stateChanged.connect(self.auto_chg_bk_fuc)
        self.spinBox.valueChanged.connect(self.spinBox_fuc)
        self.hand_shoot.setChecked(hand_shoot_flag)
        self.v_cam_chk.setToolTip("启动虚拟摄像头,可以在腾讯会议、Zoom会议、OBS等软件中使用...")
        self.auto_chg_bk.setToolTip("启动自动换背景,间隔几秒后,自动更换背景...")
        self.spinBox.setToolTip("选择自动换背景的时间间隔...")
        self.hand_shoot.setToolTip("举起手、摆出【OK】手势,放下手,n秒后启动拍照...")
        self.checkBox1.setToolTip("合成后的视频在窗口(可全屏)显示...")
        self.checkBox_fullwin.setToolTip("拍照后的照片在窗口(可全屏)显示3秒钟...")

        self.spinBox.setValue(delay_sec)
        self.auto_chg_bk.setChecked(change_bg_file)

        self.red_e.setText('8'); self.green_e.setText('188'); self.blue_e.setText('8')
        self.red_e.setValidator(QIntValidator(0, 254))
        self.green_e.setValidator(QIntValidator(0, 254))
        self.blue_e.setValidator(QIntValidator(0, 254))

        self.red_e.textChanged[str].connect(self.red_e_fuc)
        self.green_e.textChanged[str].connect(self.green_e_fuc)
        self.blue_e.textChanged[str].connect(self.blue_e_fuc)

        self.camera_comboBox.addItems(self.get_cams_name())
        self.camera_comboBox.activated[str].connect(self.click_camera_comboBox)
        self.camera_comboBox.setToolTip("物理摄像头,选择电脑上安装的物理硬件摄像头...")
        if 'OBS' in self.camera_comboBox.currentText() or 'AI_Camera' in self.camera_comboBox.currentText():
            self.camera_comboBox.setCurrentIndex(-1)
        else: self.camera_comboBox.setCurrentIndex(0)

        self.delay_comboBox.addItems(['1', '2', '3', '4', '5', '6', '7', '8', '9'])
        self.delay_comboBox.setCurrentIndex(chg_bk_counter-1)
        self.delay_comboBox.activated[str].connect(self.click_delay_comboBox)

        self.camera_w_h.addItems(['640x360', '800x600','960x540','1280x720','1440x900','1920x1080','2560x1440','3840x2160'])
        if cam_res == '1280x720': self.camera_w_h.setCurrentIndex(3)
        else: self.camera_w_h.setCurrentIndex(5)
        self.camera_w_h.setToolTip("设置摄像头分辨率,如果设置成功,实际分辨率将在下面显示...")
        self.real_camera_w_h.setText('0x0')
        self.real_camera_w_h.setToolTip("显示设置成功后的实际分辨率...")

        self.shootButton.clicked.connect(self.shootrun)
        self.shootButton.setStyleSheet("background-color:rgb(207,97,22);font-size:20px;font-weight:bold")
        self.shootButton.setEnabled(False)

        self.startButton.clicked.connect(self.start_run)
        self.stopButton.clicked.connect(self.stoprun)
        self.helpButton.clicked.connect(self.helpWin)
        self.quitButton.clicked.connect(self.quitWin)
        self.outButton.clicked.connect(self.outButton_fuc)
        self.bkfileButton.clicked.connect(self.bkfileButton_fuc)
        self.open_fold.clicked.connect(self.open_fold_fuc)
        self.chk_backfile.clicked.connect(self.chk_bk_file_fuc)
        self.fullwinButton0.clicked.connect(self.fullwinButton0_func)
        self.fullwinButton.clicked.connect(self.fullwinButton_func)

        self.outButton.setToolTip("选择输出文件目录,拍照后的文件将存在此目录...")
        self.bkfileButton.setToolTip("选择可用作背景的图片文件,建议分辨率:1920x1080...")
        self.fullwinButton.setToolTip("拍照后的照片全屏幕显示3秒钟...")
        self.fullwinButton0.setToolTip("合成的视频全屏幕显示...")

#if __name__ == '__main__':
QApplication.setAttribute(Qt.AA_EnableHighDpiScaling)
app = QtWidgets.QApplication(sys.argv)
my_full_win = full_win()
my_result_win = result_win()
winshot = Winshot()
sys.exit(app.exec_())

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_42398606/article/details/132360521

智能推荐

c# 调用c++ lib静态库_c#调用lib-程序员宅基地

文章浏览阅读2w次,点赞7次,收藏51次。四个步骤1.创建C++ Win32项目动态库dll 2.在Win32项目动态库中添加 外部依赖项 lib头文件和lib库3.导出C接口4.c#调用c++动态库开始你的表演...①创建一个空白的解决方案,在解决方案中添加 Visual C++ , Win32 项目空白解决方案的创建:添加Visual C++ , Win32 项目这......_c#调用lib

deepin/ubuntu安装苹方字体-程序员宅基地

文章浏览阅读4.6k次。苹方字体是苹果系统上的黑体,挺好看的。注重颜值的网站都会使用,例如知乎:font-family: -apple-system, BlinkMacSystemFont, Helvetica Neue, PingFang SC, Microsoft YaHei, Source Han Sans SC, Noto Sans CJK SC, W..._ubuntu pingfang

html表单常见操作汇总_html表单的处理程序有那些-程序员宅基地

文章浏览阅读159次。表单表单概述表单标签表单域按钮控件demo表单标签表单标签基本语法结构<form action="处理数据程序的url地址“ method=”get|post“ name="表单名称”></form><!--action,当提交表单时,向何处发送表单中的数据,地址可以是相对地址也可以是绝对地址--><!--method将表单中的数据传送给服务器处理,get方式直接显示在url地址中,数据可以被缓存,且长度有限制;而post方式数据隐藏传输,_html表单的处理程序有那些

PHP设置谷歌验证器(Google Authenticator)实现操作二步验证_php otp 验证器-程序员宅基地

文章浏览阅读1.2k次。使用说明:开启Google的登陆二步验证(即Google Authenticator服务)后用户登陆时需要输入额外由手机客户端生成的一次性密码。实现Google Authenticator功能需要服务器端和客户端的支持。服务器端负责密钥的生成、验证一次性密码是否正确。客户端记录密钥后生成一次性密码。下载谷歌验证类库文件放到项目合适位置(我这边放在项目Vender下面)https://github.com/PHPGangsta/GoogleAuthenticatorPHP代码示例://引入谷_php otp 验证器

【Python】matplotlib.plot画图横坐标混乱及间隔处理_matplotlib更改横轴间距-程序员宅基地

文章浏览阅读4.3k次,点赞5次,收藏11次。matplotlib.plot画图横坐标混乱及间隔处理_matplotlib更改横轴间距

docker — 容器存储_docker 保存容器-程序员宅基地

文章浏览阅读2.2k次。①Storage driver 处理各镜像层及容器层的处理细节,实现了多层数据的堆叠,为用户 提供了多层数据合并后的统一视图②所有 Storage driver 都使用可堆叠图像层和写时复制(CoW)策略③docker info 命令可查看当系统上的 storage driver主要用于测试目的,不建议用于生成环境。_docker 保存容器

随便推点

网络拓扑结构_网络拓扑csdn-程序员宅基地

文章浏览阅读834次,点赞27次,收藏13次。网络拓扑结构是指计算机网络中各组件(如计算机、服务器、打印机、路由器、交换机等设备)及其连接线路在物理布局或逻辑构型上的排列形式。这种布局不仅描述了设备间的实际物理连接方式,也决定了数据在网络中流动的路径和方式。不同的网络拓扑结构影响着网络的性能、可靠性、可扩展性及管理维护的难易程度。_网络拓扑csdn

JS重写Date函数,兼容IOS系统_date.prototype 将所有 ios-程序员宅基地

文章浏览阅读1.8k次,点赞5次,收藏8次。IOS系统Date的坑要创建一个指定时间的new Date对象时,通常的做法是:new Date("2020-09-21 11:11:00")这行代码在 PC 端和安卓端都是正常的,而在 iOS 端则会提示 Invalid Date 无效日期。在IOS年月日中间的横岗许换成斜杠,也就是new Date("2020/09/21 11:11:00")通常为了兼容IOS的这个坑,需要做一些额外的特殊处理,笔者在开发的时候经常会忘了兼容IOS系统。所以就想试着重写Date函数,一劳永逸,避免每次ne_date.prototype 将所有 ios

如何将EXCEL表导入plsql数据库中-程序员宅基地

文章浏览阅读5.3k次。方法一:用PLSQL Developer工具。 1 在PLSQL Developer的sql window里输入select * from test for update; 2 按F8执行 3 打开锁, 再按一下加号. 鼠标点到第一列的列头,使全列成选中状态,然后粘贴,最后commit提交即可。(前提..._excel导入pl/sql

Git常用命令速查手册-程序员宅基地

文章浏览阅读83次。Git常用命令速查手册1、初始化仓库git init2、将文件添加到仓库git add 文件名 # 将工作区的某个文件添加到暂存区 git add -u # 添加所有被tracked文件中被修改或删除的文件信息到暂存区,不处理untracked的文件git add -A # 添加所有被tracked文件中被修改或删除的文件信息到暂存区,包括untracked的文件...

分享119个ASP.NET源码总有一个是你想要的_千博二手车源码v2023 build 1120-程序员宅基地

文章浏览阅读202次。分享119个ASP.NET源码总有一个是你想要的_千博二手车源码v2023 build 1120

【C++缺省函数】 空类默认产生的6个类成员函数_空类默认产生哪些类成员函数-程序员宅基地

文章浏览阅读1.8k次。版权声明:转载请注明出处 http://blog.csdn.net/irean_lau。目录(?)[+]1、缺省构造函数。2、缺省拷贝构造函数。3、 缺省析构函数。4、缺省赋值运算符。5、缺省取址运算符。6、 缺省取址运算符 const。[cpp] view plain copy_空类默认产生哪些类成员函数

推荐文章

热门文章

相关标签