(十九)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

智能推荐

攻防世界_难度8_happy_puzzle_攻防世界困难模式攻略图文-程序员宅基地

文章浏览阅读645次。这个肯定是末尾的IDAT了,因为IDAT必须要满了才会开始一下个IDAT,这个明显就是末尾的IDAT了。,对应下面的create_head()代码。,对应下面的create_tail()代码。不要考虑爆破,我已经试了一下,太多情况了。题目来源:UNCTF。_攻防世界困难模式攻略图文

达梦数据库的导出(备份)、导入_达梦数据库导入导出-程序员宅基地

文章浏览阅读2.9k次,点赞3次,收藏10次。偶尔会用到,记录、分享。1. 数据库导出1.1 切换到dmdba用户su - dmdba1.2 进入达梦数据库安装路径的bin目录,执行导库操作  导出语句:./dexp cwy_init/[email protected]:5236 file=cwy_init.dmp log=cwy_init_exp.log 注释:   cwy_init/init_123..._达梦数据库导入导出

js引入kindeditor富文本编辑器的使用_kindeditor.js-程序员宅基地

文章浏览阅读1.9k次。1. 在官网上下载KindEditor文件,可以删掉不需要要到的jsp,asp,asp.net和php文件夹。接着把文件夹放到项目文件目录下。2. 修改html文件,在页面引入js文件:<script type="text/javascript" src="./kindeditor/kindeditor-all.js"></script><script type="text/javascript" src="./kindeditor/lang/zh-CN.js"_kindeditor.js

STM32学习过程记录11——基于STM32G431CBU6硬件SPI+DMA的高效WS2812B控制方法-程序员宅基地

文章浏览阅读2.3k次,点赞6次,收藏14次。SPI的详情简介不必赘述。假设我们通过SPI发送0xAA,我们的数据线就会变为10101010,通过修改不同的内容,即可修改SPI中0和1的持续时间。比如0xF0即为前半周期为高电平,后半周期为低电平的状态。在SPI的通信模式中,CPHA配置会影响该实验,下图展示了不同采样位置的SPI时序图[1]。CPOL = 0,CPHA = 1:CLK空闲状态 = 低电平,数据在下降沿采样,并在上升沿移出CPOL = 0,CPHA = 0:CLK空闲状态 = 低电平,数据在上升沿采样,并在下降沿移出。_stm32g431cbu6

计算机网络-数据链路层_接收方收到链路层数据后,使用crc检验后,余数为0,说明链路层的传输时可靠传输-程序员宅基地

文章浏览阅读1.2k次,点赞2次,收藏8次。数据链路层习题自测问题1.数据链路(即逻辑链路)与链路(即物理链路)有何区别?“电路接通了”与”数据链路接通了”的区别何在?2.数据链路层中的链路控制包括哪些功能?试讨论数据链路层做成可靠的链路层有哪些优点和缺点。3.网络适配器的作用是什么?网络适配器工作在哪一层?4.数据链路层的三个基本问题(帧定界、透明传输和差错检测)为什么都必须加以解决?5.如果在数据链路层不进行帧定界,会发生什么问题?6.PPP协议的主要特点是什么?为什么PPP不使用帧的编号?PPP适用于什么情况?为什么PPP协议不_接收方收到链路层数据后,使用crc检验后,余数为0,说明链路层的传输时可靠传输

软件测试工程师移民加拿大_无证移民,未受过软件工程师的教育(第1部分)-程序员宅基地

文章浏览阅读587次。软件测试工程师移民加拿大 无证移民,未受过软件工程师的教育(第1部分) (Undocumented Immigrant With No Education to Software Engineer(Part 1))Before I start, I want you to please bear with me on the way I write, I have very little gen...

随便推点

Thinkpad X250 secure boot failed 启动失败问题解决_安装完系统提示secureboot failure-程序员宅基地

文章浏览阅读304次。Thinkpad X250笔记本电脑,装的是FreeBSD,进入BIOS修改虚拟化配置(其后可能是误设置了安全开机),保存退出后系统无法启动,显示:secure boot failed ,把自己惊出一身冷汗,因为这台笔记本刚好还没开始做备份.....根据错误提示,到bios里面去找相关配置,在Security里面找到了Secure Boot选项,发现果然被设置为Enabled,将其修改为Disabled ,再开机,终于正常启动了。_安装完系统提示secureboot failure

C++如何做字符串分割(5种方法)_c++ 字符串分割-程序员宅基地

文章浏览阅读10w+次,点赞93次,收藏352次。1、用strtok函数进行字符串分割原型: char *strtok(char *str, const char *delim);功能:分解字符串为一组字符串。参数说明:str为要分解的字符串,delim为分隔符字符串。返回值:从str开头开始的一个个被分割的串。当没有被分割的串时则返回NULL。其它:strtok函数线程不安全,可以使用strtok_r替代。示例://借助strtok实现split#include <string.h>#include <stdio.h&_c++ 字符串分割

2013第四届蓝桥杯 C/C++本科A组 真题答案解析_2013年第四届c a组蓝桥杯省赛真题解答-程序员宅基地

文章浏览阅读2.3k次。1 .高斯日记 大数学家高斯有个好习惯:无论如何都要记日记。他的日记有个与众不同的地方,他从不注明年月日,而是用一个整数代替,比如:4210后来人们知道,那个整数就是日期,它表示那一天是高斯出生后的第几天。这或许也是个好习惯,它时时刻刻提醒着主人:日子又过去一天,还有多少时光可以用于浪费呢?高斯出生于:1777年4月30日。在高斯发现的一个重要定理的日记_2013年第四届c a组蓝桥杯省赛真题解答

基于供需算法优化的核极限学习机(KELM)分类算法-程序员宅基地

文章浏览阅读851次,点赞17次,收藏22次。摘要:本文利用供需算法对核极限学习机(KELM)进行优化,并用于分类。

metasploitable2渗透测试_metasploitable2怎么进入-程序员宅基地

文章浏览阅读1.1k次。一、系统弱密码登录1、在kali上执行命令行telnet 192.168.26.1292、Login和password都输入msfadmin3、登录成功,进入系统4、测试如下:二、MySQL弱密码登录:1、在kali上执行mysql –h 192.168.26.129 –u root2、登录成功,进入MySQL系统3、测试效果:三、PostgreSQL弱密码登录1、在Kali上执行psql -h 192.168.26.129 –U post..._metasploitable2怎么进入

Python学习之路:从入门到精通的指南_python人工智能开发从入门到精通pdf-程序员宅基地

文章浏览阅读257次。本文将为初学者提供Python学习的详细指南,从Python的历史、基础语法和数据类型到面向对象编程、模块和库的使用。通过本文,您将能够掌握Python编程的核心概念,为今后的编程学习和实践打下坚实基础。_python人工智能开发从入门到精通pdf

推荐文章

热门文章

相关标签