banner
肥皂的小屋

肥皂的小屋

github
steam
bilibili
douban
tg_channel

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

載入中......
此文章數據所有權由區塊鏈加密技術和智能合約保障僅歸創作者所有。