python 证件照换底、抠像 百度人体分析

思路

百度接口的申请就不赘述了。
主要用到了百度人体分析api和PIL库,主要实现三个功能:

  • 人像背景消除
  • 生成证件照,并可随意设置底色
  • 证件照图片格式转换

具体方法

  1. get_portrait():利用百度提供的人体分析模块将人像部分分离出来,以png格式保存备用
  2. get_background():生成合适大小的底色图,一般为红、蓝、白。
  3. main():将人像覆盖粘贴在底色图上,得到所需证件照。
  4. resize():按需调整证件照大小和底色。
  5. conversion():统一转换为jpg格式并适当压缩。
  6. 批量操作需要注意的便是命名规则,常用方法是根据时间戳命名,既能保证有序,也能避免重复。

具体实现

python3.8以上

from aip import AipBodyAnalysis
from PIL import Image
import base64
import requests
import os
import time

APP_ID = '****'
API_KEY = '****'
SECRET_KEY = '****'
client = AipBodyAnalysis(APP_ID, API_KEY, SECRET_KEY)


def create_dir(path):
    if not os.path.exists(path):
        os.mkdir(path)


class Zjz:
    def __init__(self):
        self.prefix_url = "https://aip.baidubce.com/rest/2.0/image-classify/v1/body_seg?access_token="
        self.host = f'https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&client_id={API_KEY}&client_secret={SECRET_KEY}'
        self.save_path = r'C:\Users\Administrator\Pictures\Camera Roll'
        self.pending_path = r'C:\Users\Administrator\Pictures\Temporary image'
        self.access_token = None
        self.original_image_path = None
        self.response = None
        self.foreground = None
        self.original_size = None
        self.bool_invalid = None
        self.images = []
        self.image_names = []
        self.background_colors = ['white', 'blue', 'red', 'green', 'pink', 'yellow', 'purple', 'black', 'snow']
        print('You must give the path of the image')

    def get_access_token(self):
        if response := requests.get(self.host):
            self.access_token = response.json()['access_token']

    def valid(self, image_path):
        try:
            (image := Image.open(image_path)).verify()
            self.bool_invalid = False
            if 0 in image.size:
                self.bool_invalid = True
                print(image.size)
        except Exception as e:
            print(e)
            self.bool_invalid = True

    def get_portrait(self):
        with open(self.original_image_path, 'rb') as fp:
            img = base64.b64encode(fp.read())
        headers = {'content-type': 'application/x-www-form-urlencoded'}
        params = {"image": img}
        filename = f'{self.pending_path}/{os.path.basename(os.path.splitext(self.original_image_path)[0])}.png'
        print('portrait: ', filename)
        self.valid(filename)
        if not os.path.exists(filename) or self.bool_invalid is True:
            self.get_access_token()
            self.response = requests.post(self.prefix_url + self.access_token, data=params, headers=headers)
            if self.response:
                with open(filename, 'wb') as fp:
                    fp.write(image_data := base64.b64decode(self.response.json()['foreground']))
                    try:
                        self.foreground = Image.open(image_data)
                    except Exception as e:
                        print(e)
        else:
            self.foreground = Image.open(filename)

    def get_background(self):
        self.original_size = Image.open(self.original_image_path).size
        print(self.original_size)
        for color in self.background_colors[:3]:
            self.images.append(Image.new('RGBA', self.original_size, color))

    def main(self):
        create_dir(self.pending_path)
        self.get_portrait()
        self.get_background()
        r, g, b, a = self.foreground.split()
        for i, image in enumerate(self.images):
            image.paste(self.foreground, (0, 0), mask=a)
            image.save(temp := f'{self.save_path}/ZJZ_{self.background_colors[i][:2].upper()}_'
                               f'{os.path.basename(os.path.splitext(self.original_image_path)[0])}_'
                               f'{time.strftime("%Y%m%d", time.localtime())}.png')
            self.image_names.append(temp)

    def resize(self, width=250, color='white'):
        ratio = self.original_size[1] / self.original_size[0]
        height = int(width * ratio)
        fore = self.foreground.resize((width, height))
        image = Image.new('RGBA', (width, height), color)
        image.paste(fore, (0, 0), mask=fore.split()[-1])
        image.save(temp := f'{self.save_path}/ZJZ_RESIZE_{time.strftime("%Y%m%d", time.localtime())}.png')
        self.image_names.append(temp)

    def conversion(self):
        for filename in self.image_names:
            image = Image.open(filename)
            output_file = os.path.splitext(filename)[0] + '.jpg'
            try:
                r, g, b, a = image.split()
                image = Image.merge("RGB", (r, g, b))
                image.convert("RGB").save(output_file, quality=50)
            except Exception as e:
                print("Format conversion failed", e)

    def delete_invalid_image(self):
        for file in os.listdir(self.save_path):
            file = os.path.join(self.save_path, file)
            self.valid(file)
            if self.bool_invalid and 'jpg' in file:
                enter = input(f'you want to delete the file "{file}"?\n')
                if enter in ('y', 'Y', 'yes'):
                    os.remove(file)


if __name__ == "__main__":
    photo = Zjz()
    photo.original_image_path = r'C:\Users\Administrator\Pictures\Saved Pictures\psc2.webp'
    photo.main()
    # photo.resize()
    photo.conversion()
    # photo.delete_invalid_image()

运行效果

python 证件照换底、抠像 百度人体分析_第1张图片

python 证件照换底、抠像 百度人体分析_第2张图片
声明:图片为网上随便下载的,侵删。

你可能感兴趣的:(python,工具,python,百度,图像识别)