banner
soapffz

soapffz

github
steam
bilibili
douban

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") # 图片位置

效果如下:

image

image

image

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

** 本文用到的这个核心库只有将背景图片背景移除的功能 ** ,填充为其他颜色使用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")

效果如下:

image

GUI 版本#

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

设计 GUI#

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

GUI 设计图如图所示:

image

文件选择#

参考文章: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('不退出')

image

自定义消息框#

# 创建一个问答框,注意是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('不退出')

image

参考文章:

设置超链接#

一般都是在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)

效果如下:

image

参考文章: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.

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

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

image

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

image

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


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

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

Loading...
Ownership of this post data is guaranteed by blockchain and smart contracts to the creator alone.