(六)图像背景移除/去背景/换背景/抠图/抠像代码示例:AI实时抠图、AI实时抠像、PaddlePaddle模型、虚拟现实视频会议、沉浸式会议场景、人像去背景、视频背景消除、摄像头背景移除

(六)图像背景移除/去背景/换背景/抠图/抠像代码示例:AI实时抠图、AI实时抠像、PaddlePaddle模型、虚拟现实视频会议、沉浸式会议场景、人像去背景、视频背景消除、摄像头背景移除

本文与前几篇博文关联性较强,请事先阅读前几篇。 对此文感兴趣的可以加微深入探讨:herbert156
软件打包上传了百度网盘:
【视频背景移除】链接: https://pan.baidu.com/s/1Dhr7MHkGd8vlXfyETrK3xQ 提取码: 29n2
【图像背景移除】链接: https://pan.baidu.com/s/1nhuWMYWvTV3B0d0CdGDhFQ 提取码: q46x
【摄像头背景移除】链接: https://pan.baidu.com/s/1tx88C3dCH3ej3PJcKLDmdQ 提取码: g7xy

一、图片抠图
代码主要功能是:图像背景移除、去背景、人像抠图、换背景等,主要包括:
1、对人像图片进行抠图,可以存成PNG格式的透明图片,也可选择替换背景(可选择替换成纯色的、也可选替换成指定背景图片);
2、可以批量抠图,在选择文件的对话框里可以选择多个文件,同时抠图、批量操作;
3、软件设置里可以设置使用GPU处理还是CPU处理,软件只支持英伟达(Nvidia)的GTX/RTX系列的GPU;
4、抠图算法的模型有复杂模型和简易模型,可以根据原始图片的背景复杂度随意选择。

在这里插入图片描述

二、图片抠图代码

def image_change_background(self, imagefile, backfile):
    global bg_file, iii, stop_flag, t0

    #try:  img2= cv2.imread(imagefile)  # 读取文件
    try:
        img2= cv2.imdecode(np.fromfile(imagefile, dtype=np.uint8), -1)
        if img2.shape[2] == 4: img2 = cv2.cvtColor(img2, cv2.COLOR_BGRA2BGR)

    except: self.show_error('读取图片文件【'+imagefile+'】时,出现错误!\n\n原因:目录/文件名不能包含中文......'); return
    if img2 is None: self.show_error('读取图片文件【'+imagefile+'】时,出现错误!\n\n原因:目录/文件名不能包含中文......'); return

    size_x = img2.shape[1]  # 宽度
    size_y = img2.shape[0]  # 高度
    imageinfo = '【图片信息】 文件总数:%d | 正在处理(%d/%d):'%(filesnums,iii,filesnums) + os.path.split(imagefile)[1]+\
                ' | 图像分辨率:%dx%d '%(size_x,size_y)
    self.txt11.setText(imageinfo)
    img1 = cv2.resize(backfile, (size_x, size_y))
    t1 = time.time()
    if size_x / size_y > 1.778: fx = 427 / size_x; fy = fx   # 计算16:9的比例,以便缩放不变形
    else: fx = 240 / size_y; fy = fx

    if stop_flag:
        self.txt11.setText('【视频信息】 文件总数:%d个 | 处理完成:%d个' % (filesnums, iii))
        self.txt12.setText('【运行信息】 用户终止了正在运行的程序......')
        return
    img3 = self.koutu(img2)
    #img3 = cv2.cvtColor(img2.copy(), cv2.COLOR_BGR2BGRA)   #测试用语句
    png_name = out_dir+'/'+os.path.splitext(os.path.split(imagefile)[1])[0]+'_1.png'
    #cv2.imwrite(png_name,img3)
    cv2.imencode('.png', img3)[1].tofile(png_name)

    if not only_png:
        img4 = self.two_pic_combine_PIL(img1,img3)     #img1:背景文件;img2:源文件;img3:抠图文件;img4:合并背景文件
        if Box2_flag: self.my_label2.setPixmap(self.CvMatToQImage(cv2.resize(img4, (0, 0), fx=fx, fy=fy)))
        jpg_name = out_dir+'/'+os.path.splitext(os.path.split(imagefile)[1])[0]+'_1.jpg'
        #cv2.imwrite(jpg_name,img4)
        cv2.imencode('.jpg', img4)[1].tofile(jpg_name)
    else:
        if Box2_flag: self.my_label2.setPixmap(self.CvMatToQImage(cv2.resize(img3,(0,0),fx=fx,fy=fy)))
    if Box1_flag: self.my_label1.setPixmap(self.CvMatToQImage(cv2.resize(img2,(0,0),fx=fx,fy=fy)))

    cv2.waitKey(1); t2 = time.time()
    runinfo = '【运行信息】 当前图片处理耗时:%.3f秒 | 总处理耗时:%.1f秒 | 处理进度:%.1f%%'%((t2-t1),(t2-t0),100*(iii/filesnums))
    self.txt12.setText(runinfo);  cv2.waitKey(1)
    self.txt12.setText('【运行信息】 处理完毕!总消耗时间:%d秒'%(t2-t0))
    self.txt11.setText('【视频信息】 文件总数:%d个 | 处理完成:%d个'%(filesnums,iii))

在这里插入代码片

三、界面操作代码

    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.filesButton.setEnabled(False);       self.outButton.setEnabled(False)
        #self.bkfileButton.setEnabled(False);      #self.checkBox3.setEnabled(False)
        self.startButton.setEnabled(False);       self.stopButton.setEnabled(True)
        self.quitButton.setEnabled(False);        #self.checkBox3_0.setEnabled(False)
    def set_True_Btn(self):
        self.filesButton.setEnabled(True);       self.outButton.setEnabled(True)
        #self.bkfileButton.setEnabled(True);      #self.checkBox3.setEnabled(True)
        self.startButton.setEnabled(True);       self.stopButton.setEnabled(False)
        self.quitButton.setEnabled(True);        #self.checkBox3_0.setEnabled(True)

    def startrun(self):
        global iii,stop_flag,t0
        iii = 0; stop_flag = False

        self.txt12.setText('【运行信息】 正在初始化AI模型......');cv2.waitKey(1)
        t0 = time.time()

        if files == []: self.show_error('请选择需要抠图或替换背景的图像文件!'); return
        if not os.path.exists(out_dir): self.show_error('输出目录不存在,请重新选择!'); return
        self.set_False_Btn()

        if not Box3_flag and not only_png:
            #try: back_ground = cv2.imread(bg_file)  # 读取背景文件
            try: back_ground = cv2.imdecode(np.fromfile(bg_file, dtype=np.uint8), -1)
            except: self.show_error('读取背景文件时,出现错误!'); self.set_True_Btn(); return
            if back_ground is None: self.show_error('读取背景文件时,出现错误!\n\n原因:文件不存在或文件名包含中文...... '); self.set_True_Btn(); return
        else: back_ground = bk_img

        for file in files:
            iii += 1
            if stop_flag: break
            self.image_change_background(file, back_ground)

        self.set_True_Btn()
        #self.my_label1.setPixmap(QPixmap("ican_logo.png"))
        #self.my_label2.setPixmap(QPixmap("ican_logo.png"))

    def stoprun(self):
        global stop_flag
        r_button = QMessageBox.question(self, my_title, "\n\n    确定要停止替换背景吗?\n\n", QMessageBox.Yes | QMessageBox.No)
        if r_button == QMessageBox.Yes: stop_flag = True
    def helpWin(self):
        str="\n\n\n1、【选择文件】选择需要抠图、替换背景的图像文件;\n2、【输出目录】替换后的文件目录,文件名:源文件_1.mp4;\n"+\
        "3、【背景文件】选择后,人物图像的背景都被替换成此背景;\n4、【纯色背景】点选后,所有图片背景替换成纯色的;\n"+ \
        "5、可以选择只输出PNG透明文件或同时输出背景替换文件;\n" + \
        "6、如没有Nvidia系列GPU,就选CPU处理,AI需选【简易】;\n7、AI抠图算法有简易、复杂2种,可在软件设置栏目里面选择;\n\n\n"+\
        "      本软件著作权归属:XXX        网址:www.???.com\n\n"
        QMessageBox.question(self, my_title, str, QMessageBox.Ok)
    def quitWin(self):
        r_button = QMessageBox.question(self, my_title, "\n\n    退出将终止替换进程\n\n    确认退出吗?\n\n", QMessageBox.Yes | QMessageBox.No)
        if r_button == QMessageBox.Yes: sys.exit()

    def filesButton_fuc(self):
        global files,filesnums
        files, ok1 = QFileDialog.getOpenFileNames(self,'请选择图像文件[全选:Ctrl+A、多选:Ctrl/Shift+鼠标]',
                                                       input_path,"*.jpg;;*.png")
        filesnums = len(files)
        if files!=[]:
            txt='目录:'+os.path.split(files[0])[0]+' | 已选文件:'+str(filesnums)+'个 | 文件名:'
            for file in files: txt=txt+ os.path.split(file)[1]+'; '
            self.txt1.setText(txt)
        else: self.txt1.setText('请选择图像文件[全选:Ctrl+A、多选:Ctrl/Shift+鼠标]......')
    def outButton_fuc(self):
        global out_dir
        out_dir = QFileDialog.getExistingDirectory(self,'选择转换后的输出文件夹', work_path)
        if out_dir == '': self.txt2.setText('请选择背景替换后文件保存目录......')
        else: self.txt2.setText(out_dir)
    def bkfileButton_fuc(self):
        global 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)

    def click_comboBox1(self, text):
        global if_use_gpu,if_good_model
        if text == 'GPU':
            if GPU_memsize < 3 and self.comboBox2.currentIndex() == 1:
                self.show_error("\nGPU名称:%s\nGPU内存:%dG\n\n注意:\nGPU内存必须大于3G才能进行复杂AI模型,\n请选择简易模型!"
                                %(GPU_name,GPU_memsize))
                self.comboBox2.setCurrentIndex(0);if_good_model = False
            if_use_gpu = True
        else: if_use_gpu = False
    def click_comboBox2(self, text):
        global if_good_model,if_use_gpu
        if text == '复杂':
            if GPU_memsize < 3 and self.comboBox1.currentIndex() == 1:
                self.show_error("\nGPU名称:%s\nGPU内存:%dG\n\n注意:\nGPU内存必须大于3G才能进行复杂AI模型,\n请选择简易模型或CPU处理!"
                                % (GPU_name, GPU_memsize))
                self.comboBox1.setCurrentIndex(0);if_use_gpu = False
            if_good_model = True
        else: if_good_model = False
    def box_choose(self):
        global Box1_flag, Box2_flag
        if self.checkBox1.isChecked(): Box1_flag = True
        else:Box1_flag = False;  self.my_label1.setPixmap(QPixmap("start_img.jpg"))
        if self.checkBox2.isChecked(): Box2_flag = True
        else:Box2_flag = False;  self.my_label2.setPixmap(QPixmap("start_img.jpg"))
    def box_choose3_0(self):
        global only_png
        if self.checkBox3_0.isChecked():
            self.txt3.setEnabled(False); self.bkfileButton.setEnabled(False)
            self.checkBox3.setEnabled(False)
            self.txt3.setText('只输出PNG透明文件,不更换背景......')
            only_png = True
        else:
            self.txt3.setEnabled(True); self.bkfileButton.setEnabled(True)
            self.txt3.setText(bg_file); self.checkBox3.setEnabled(True)
            only_png = False
    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 createLayout(self):
        mainLayout = QtWidgets.QVBoxLayout();topLayout1 = QtWidgets.QHBoxLayout();topLayout2 = QtWidgets.QHBoxLayout()
        topLayout3 = QtWidgets.QHBoxLayout();topLayout4 = QtWidgets.QHBoxLayout()

        self.my_label1 = QtWidgets.QLabel(); self.my_label2 = QtWidgets.QLabel()
        topLayout1.addWidget(self.my_label1); topLayout1.addWidget(self.my_label2)

        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("本区域,显示的是替换后的缩略图...")

        self.GroupBox1 = QtWidgets.QGroupBox("软件设置")
        self.GroupBox1.setFixedSize(280, 60)
        self.lbl_1 = QtWidgets.QLabel("处理器:", self)
        self.lbl_1.setFixedSize(45, 25)
        self.comboBox1 = QtWidgets.QComboBox(self)
        self.comboBox1.setFixedSize(50, 25)
        self.comboBox1.addItem("CPU");  self.comboBox1.addItem("GPU")
        if if_use_gpu: self.comboBox1.setCurrentIndex(1)
        self.comboBox1.activated[str].connect(self.click_comboBox1)
        self.lbl_2 = QtWidgets.QLabel("AI算法:", self)
        self.lbl_2.setFixedSize(45, 25)
        self.comboBox2 = QtWidgets.QComboBox(self)
        self.comboBox2.setFixedSize(50, 25)
        self.comboBox2.addItem("简易"); self.comboBox2.addItem("复杂")
        if if_good_model:self.comboBox2.setCurrentIndex(1)
        self.comboBox2.activated[str].connect(self.click_comboBox2)
        GroupBox1Layout = QtWidgets.QHBoxLayout()
        GroupBox1Layout.addWidget(self.lbl_2)
        GroupBox1Layout.addWidget(self.comboBox2)
        GroupBox1Layout.addWidget(self.lbl_1)
        GroupBox1Layout.addWidget(self.comboBox1)
        self.GroupBox1.setLayout(GroupBox1Layout)
        if not if_use_gpu: self.comboBox1.setEnabled(False)

        self.GroupBox2 = QtWidgets.QGroupBox("显示设置")
        self.GroupBox2.setFixedSize(180, 60)
        self.checkBox1 = QtWidgets.QCheckBox("原始图像")
        self.checkBox2 = QtWidgets.QCheckBox("输出图像")
        GroupBox2Layout = QtWidgets.QHBoxLayout()
        GroupBox2Layout.addWidget(self.checkBox1)
        GroupBox2Layout.addWidget(self.checkBox2)
        self.GroupBox2.setLayout(GroupBox2Layout)
        self.checkBox1.stateChanged.connect(self.box_choose)
        self.checkBox2.stateChanged.connect(self.box_choose)
        self.checkBox1.setChecked(True); self.checkBox2.setChecked(True)

        self.GroupBox4 = QtWidgets.QGroupBox("文件设置")
        self.GroupBox4.setFixedSize(850, 160)
        self.filesButton = self.createButton("选择文件", self.filesButton_fuc)
        self.outButton = self.createButton("输出目录", self.outButton_fuc)
        self.bkfileButton = self.createButton("背景文件", self.bkfileButton_fuc)
        self.filesButton.setToolTip("选择即将被替换背景的图片文件,可单选、多选...")
        self.outButton.setToolTip("选择输出文件目录,替换后的文件将存在此目录...")
        self.bkfileButton.setToolTip("选择可用作背景的图片文件,建议分辨率:1920x1080...")
        self.filesButton.setFixedSize(80,23); self.outButton.setFixedSize(80,23)
        self.bkfileButton.setFixedSize(80,23)
        self.txt1 = QLabel('请选择图像文件[Ctrl+A全选、Ctrl/Shift+鼠标可多选]......', self); self.txt2 = QLabel('输出目录', self)
        self.txt3 = QLabel('背景文件', self); self.txt4 = QLabel('纯色文件', self)
        self.txt2.setText(out_dir);   self.txt3.setText(bg_file);
        self.txt4.setPixmap(self.CvMatToQImage(cv2.resize(bk_img, (50, 18))))
        self.checkBox3_0 = QtWidgets.QCheckBox("只输出PNG文件(不换背景)   ")
        self.checkBox3_0.setToolTip("勾选:只输出透明的PNG文件,不更换背景;\n不勾选:同时输出PNG文件和更换背景的文件。");
        self.checkBox3 = QtWidgets.QCheckBox("纯色背景")
        self.checkBox3_0.stateChanged.connect(self.box_choose3_0)
        self.checkBox3.stateChanged.connect(self.box_choose3)
        self.checkBox3_0.setChecked(True)

        self.red  = QLabel(' 红', self); self.green= QLabel('    绿', self); self.blue = QLabel('    蓝', self)
        self.red_e =   QLineEdit(self);    self.red_e.setText('8')
        self.green_e = QLineEdit(self);    self.green_e.setText('188')
        self.blue_e =  QLineEdit(self);    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.setFixedSize(28, 20);self.green_e.setFixedSize(28, 20);self.blue_e.setFixedSize(28, 20)
        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)

        layout_box1 = QtWidgets.QHBoxLayout()
        layout_box2 = QtWidgets.QHBoxLayout()
        layout_box3 = QtWidgets.QHBoxLayout()
        layout_box1.addWidget(self.filesButton, Qt.AlignLeft| Qt.AlignVCenter)
        layout_box1.addWidget(self.txt1, Qt.AlignLeft| Qt.AlignVCenter)
        layout_box2.addWidget(self.outButton)
        layout_box2.addWidget(self.txt2)
        layout_box2.addWidget(self.bkfileButton)
        layout_box2.addWidget(self.txt3)
        layout_box3.addWidget(self.checkBox3_0)
        layout_box3.addWidget(self.checkBox3)
        layout_box3.addWidget(self.txt4)
        layout_box3.addWidget(self.red)
        layout_box3.addWidget(self.red_e)
        layout_box3.addWidget(self.green)
        layout_box3.addWidget(self.green_e)
        layout_box3.addWidget(self.blue)
        layout_box3.addWidget(self.blue_e)
        layout_box3.addStretch(1)
        layout11 = QWidget();  layout21 = QWidget(); layout31 = QWidget()
        layout11.setLayout(layout_box1);  layout21.setLayout(layout_box2); layout31.setLayout(layout_box3)

        GroupBoxmainLayout = QtWidgets.QVBoxLayout()
        GroupBoxmainLayout.addWidget(layout11, Qt.AlignLeft | Qt.AlignVCenter)
        GroupBoxmainLayout.addWidget(layout21, Qt.AlignLeft | Qt.AlignVCenter)
        GroupBoxmainLayout.addWidget(layout31, Qt.AlignLeft | Qt.AlignVCenter)
        self.GroupBox4.setLayout(GroupBoxmainLayout)

        self.GroupBox5 = QtWidgets.QGroupBox("信息统计")
        self.GroupBox5.setFixedSize(850, 90)
        self.txt11 = QLabel('【图像信息】', self)
        self.txt12 = QLabel('【运行信息】', self)
        GroupBox5Layout = QtWidgets.QGridLayout()
        GroupBox5Layout.addWidget(self.txt11, 0, 1)
        GroupBox5Layout.addWidget(self.txt12, 1, 1)
        self.GroupBox5.setLayout(GroupBox5Layout)

        self.startButton = self.createButton("开始处理", self.startrun)
        self.stopButton = self.createButton("停止", self.stoprun)
        self.helpButton = self.createButton("帮助", self.helpWin)
        self.quitButton = self.createButton("退出", self.quitWin)
        self.startButton.setFixedSize(80,25)
        self.stopButton.setFixedSize(55, 25)
        self.helpButton.setFixedSize(55,25)
        self.quitButton.setFixedSize(55,25)

        topLayout2.addWidget(self.GroupBox4)
        topLayout3.addWidget(self.GroupBox5)
        topLayout4.addWidget(self.GroupBox1)
        topLayout4.addWidget(self.GroupBox2)
        topLayout4.addWidget(self.startButton)
        topLayout4.addWidget(self.stopButton)
        topLayout4.addWidget(self.helpButton)
        topLayout4.addWidget(self.quitButton)
        topLayout4.setSpacing(20)

        layout1 = QWidget();  layout2 = QWidget()
        layout3 = QWidget();  layout4 = QWidget()
        layout1.setLayout(topLayout1);  layout2.setLayout(topLayout2)
        layout3.setLayout(topLayout3);  layout4.setLayout(topLayout4)

        mainLayout.addWidget(layout1, Qt.AlignLeft | Qt.AlignTop)
        mainLayout.addWidget(layout2, Qt.AlignLeft | Qt.AlignBottom)
        mainLayout.addWidget(layout3, Qt.AlignLeft | Qt.AlignBottom)
        mainLayout.addWidget(layout4, Qt.AlignLeft | Qt.AlignBottom)
        self.setLayout(mainLayout)

    def createButton(self, text, member):
        button = QtWidgets.QPushButton(text)
        button.clicked.connect(member)
        return button
  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值