MENU

Python--一个给证件照换底色的小程序

起因

看到一篇文章介绍了一个AI抠图的库removebg

点我去GitHub,点我去网站官网在线换图片背景

抠图嘛,我也帮朋友干过这事,原来我自己是跟着doyoudo教程做过,网站上直接看需要注册登录

不想注册的可以到优酷上看,在这里顺便安利一下doyoudo这个网站(看到请打钱谢谢):

doyoudo是一个小清新的音视频剪辑软件教程网站

跟着教程熟悉了后大概10分钟就能P一张图,但是!现在有了这个人工智能抠图的库removebg,那肯定要来试一下效果

这个库大概介绍如下:

默认生成的图片格式尺寸是标准的,每月最多免费处理 50 张照片。如果想生成高清甚至 4K 或者处理更多图片需要付费。算下来价格大概是 1 元一张。

于是准备用这个核心代码包装一下,继续做一个PyQt5的小程序,加强一下我的PyQt5功底看下能不能学到一些新东西

无GUI版本

注意:生成的图片会到原图片的目录并且文件名从图片名.图片后缀变为图片名.图片后缀_no_bg.png

替换背景

注册登录后去网站API接口获取自己的API,然后用以下几行代码就可实现基本的图片背景替换:

from removebg import RemoveBg
rmbg = RemoveBg("你的apikey", "error.log")
rmbg.remove_background_from_img_file(r"C:\Users\soapffz\Desktop\640_2.jpg") # 图片位置

效果如下:

为了图片加载速度,这里画质被严重压缩请不要在意。

本文用到的这个核心库只有将背景图片背景移除的功能 ,填充为其他颜色使用PIL里的的Image来实现:

填充颜色

from PIL import Image
img = Image.open(r'640.png').convert("RGBA")
x, y = img.size
card = Image.new("RGBA", img.size, (0, 0, 255))
card.paste(img, (0, 0, x, y), img)
card.save("640_2.jpg", format="png")

效果如下:

GUI版本

这里顺便补充下一直在用但一直忘记说的PyQt5的部分技巧

设计GUI

基础的设计教程都在<<搭建本地 ip 代理池 (完结)>>这篇文章里面,可以在Python目录找到这篇文章

GUI设计图如图所示:

文件选择

参考文章:PyQt5文件对话框QFileDialog的使用

选择单个文件:

from os import path
from sys import argv

    self.exe_path = path.dirname(argv[0])  # 获取当前程序运行的路径
    self.pushButton.clicked.connect(self.chosepic) # 选择文件的按钮被按下时触发函数

    def chosepic(self):
        # 选择图片
        file_name = QtWidgets.QFileDialog.getOpenFileName(
            self, "选取文件", self.exe_path, "Pic Files (*.png;*.jpg);;Text Files (*.txt)")[0]   # 设置文件扩展名过滤,用双分号间隔
        if file_name == "":
            print("用户取消选择")
            return
        print("你选择的文件为:", file_name)

选择单个文件夹:

from os import path
from sys import argv

    self.exe_path = path.dirname(argv[0])  # 获取当前程序运行的路径
    self.pushButton.clicked.connect(self.chosedir) # 选择文件夹的按钮被按下时触发函数
    def chosedir(self):
        # 选择含图片的文件夹
        dir_name = QtWidgets.QFileDialog.getExistingDirectory(
            self, "选取文件夹",  self.exe_path)
        if dir_name == "":
            print("\n取消选择")
            return
        print("你选择的文件夹为:", dir_name)

这里只介绍了常用的两种,多个文件选择可以使用选择单个文件夹再判断文件后缀的方法来实现,其他方法请参考参考文章。

弹框显示实现

常用函数:

# 信息框
QMessageBox.information(self, '框名', '内容', 按钮s, 默认按钮) 
# 问答框
QMessageBox.question(self, '框名', '内容', 按钮s, 默认按钮)
# 警告框
QMessageBox.warning(self, '框名', '内容', 按钮s, 默认按钮) 
# 危险框
QMessageBox.ctitical(self, '框名', '内容', 按钮s, 默认按钮)
# 关于框
QMessageBox.about(self, '框名', '内容') 

实例:

from PyQt5.QtWidgets import QMessageBox

# 退出确定框
reply = QMessageBox.question(self, '退出', '确定退出?', QMessageBox.Yes | QMessageBox.No | QMessageBox.Cancel, QMessageBox.Cancel)
if reply == QMessageBox.Yes:
    print('退出')
else:
    print('不退出')

自定义消息框

# 创建一个问答框,注意是Question
self.box = QMessageBox(QMessageBox.Question, '退出', '确定退出?')

# 添加按钮,可用中文
yes = self.box.addButton('确定', QMessageBox.YesRole)
no = self.box.addButton('取消', QMessageBox.NoRole)

# 设置消息框中内容前面的图标
self.box.setIcon(1)

# 设置消息框的位置,大小无法设置
self.box.setGeometry(500, 500, 0, 0)

# 显示该问答框
self.box.show()

if self.box.clickedButton() == yes:
    print('退出')
else:
    print('不退出')

参考文章:

设置超链接

一般都是在label组件上设置,在设计的时候正常填写文字即可,然后需要做如下设置:

self.label_getapi.setText("<a href='https://www.remove.bg/api'>点我获取APIKEY:</a>") # 设置超文本文字
self.label_getapi.setOpenExternalLinks(True) # 允许默认浏览器访问超链接

复选框调用同一个函数检查状态

在我的程序设计中,默认是必须要生成没有背景的颜色的图片,其次才能选择其他背景颜色

那么怎样获取要转换的颜色有哪些呢?可以使用如下方法实现:

        self.bg_color_chose_l = []  # 需要转换的颜色有哪些
        self.checkBox_white.stateChanged.connect(self.checkstate)
        self.checkBox_blue.stateChanged.connect(self.checkstate)
        self.checkBox_red.stateChanged.connect(self.checkstate)
        self.pushButton_begin.clicked.connect(self.begin)
    def checkstate(self, state):
        # 用来检测有哪些转换颜色的选项被勾选上了
        # 获取发送信号的checkbox
        which_checkbox = self.sender()
        if state == QtCore.Qt.Unchecked:
            self.insert_msg_to_disp(
                "用户不要{}色背景的图片了".format(which_checkbox.text()))
            self.bg_color_chose_l.remove(which_checkbox.text())
        if state == QtCore.Qt.Checked:
            self.insert_msg_to_disp(
                "用户想要{}色背景的图片".format(which_checkbox.text()))
            self.bg_color_chose_l.append(which_checkbox.text())
        if len(self.bg_color_chose_l) == 0:
            self.insert_msg_to_disp("现在未选择任何背景!")
        else:
            self.insert_msg_to_disp(
                "现在用户想要的背景颜色有:{}".format(self.bg_color_chose_l)

效果如下:

参考文章:PyQt5笔记 - CheckBox

刷新页面

在程序可能会卡顿的地方尤其是for循环的第一句话添加这一行命令:

QtWidgets.QApplication.processEvents()

最终效果

注意,在实际使用时发现当图片的背景过于复杂时不能成功清除背景

会在error.log中报如下错:

ERROR:root:Unable to save C:\Users\soapffz\Desktop\xdx.jpg_no_bg.png due to could not identify foreground in image. for details and recommendations see https://www.remove.bg/supported-images.

所以,不要选择过于复杂的图片来实验,尽量就选择背景不那么复杂的人像

单个文件转换最终效果如下:

多个文件转换最终效果如下:

本文完。(熬夜爆肝到2点半)


成品下载链接(以后更新会放在这里):

(2019-07-24凌晨2点半):https://www.lanzous.com/i54q96f

最后编辑于: 2019 年 07 月 24 日
添加新评论

已有 2 条评论
  1. 木杉 木杉

    你好,我下载下来试用的时候发生了错误,Failed to execute script main. 请问应该如何解决呢?

    1. @木杉我调试后发现是Qt5Core.dll这个文件缺失的问题,而且这个文件无法打包到exe中。你可以参考这里https://soapffz.com/311.html#menu_index_7去下载Qt5Core.dll文件并把它的目录添加到环境变量中就可解决。