02-更换证件背景
一、背景
生活中,有的时候我们需要不同颜色的背景图片,电子档或者打印出的图片。当我们手上正好有某一种背景颜色的图片,却又不想花钱去打印店拍摄照片时,我们就会通过ps等工具进行颜色背景的替换,然而对于手残党的我们却始终无法很好的抠图。此时,我们就会希望有一个好的工具替我们来完成背景替换操作,于是乎,小妖就来教大家一个怎么完成颜色背景和前景融合的方法。
二、说明
2.1. 接口调用说明
我们引入的是removebg的api接口,所以每月会有次数限制(remove.bg官网上写的是一个月50次,基本够我们使用),嫌麻烦的话可以直接去removebg的官网进行抠图替换背景,这里只是帮助大家一起了解一下如何通过python+opencv的程序来实现。
2.2 API key获取位置
三、实现代码
import os
import numpy as np
import cv2
from typing import List
from removebg import RemoveBg as RmBg"""
移除图片背景,并替换成纯色背景
"""class RemoveImgBg:# 换成自己的api key,每月有50次调用机会API_KEY = "xxxxx"def __init__(self, file_name, error_log_file="error.log"):# 传入的图片名self.src_img = file_name# 生成的图片名self.des_img = ""# 移除背景时,调用api报错self.error_log_file = error_log_filedef rm_bg(self):"""移除图片的背景:return:"""rmbg = RmBg(self.API_KEY, self.error_log_file)rmbg.remove_background_from_img_file(self.src_img)def rename_no_bg_img(self):"""重命名接口返回的图片名:return:"""src_img_name = f"{self.src_img}_no_bg.png"dest_img_name = f"{self.src_img.split('.')[0]}_no_bg.png"if os.path.exists(src_img_name):os.rename(src_img_name, dest_img_name)self.des_img = dest_img_nameelse:if os.path.exists(dest_img_name):self.des_img = dest_img_namedef change_bg_color(self, color: List[int], file_name: str):"""给图片的添加上纯色:param color::param file_name::return:"""# 读取png图片, -1代表获取alpha通道fore_image = cv2.imread(self.des_img, -1)# 拆分png的4个通道b, g, r, a = cv2.split(fore_image)# 图片的高, 宽rows = fore_image.shape[0]cols = fore_image.shape[1]# 得到PNG图像前景部分,在这个图片中就是除去 Alpha通道的部分foreground = cv2.merge((b, g, r))# 得到PNG图像的alpha通道,即alpha掩模alpha = cv2.merge((a, a, a))img = np.ones((rows, cols), dtype=np.uint8)# 新建一个图层,默认为单通道图层background = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR) # 将单通道转化成3通道Mat# 设置背景图层的颜色background[:, :, 0] = color[0]background[:, :, 1] = color[1]background[:, :, 2] = color[2]# 因为下面要进行乘法运算故将数据类型设为float,防止溢出foreground = foreground.astype(float)background = background.astype(float)# 将alpha的值归一化在0-1之间,作为加权系数alpha = alpha.astype(float) / 255# 将前景和背景进行加权,每个像素的加权系数即为alpha掩模对应位置像素的值,前景部分为1,背景部分为0# 采用了正片叠底的方法 即 任何像素与黑色相乘为黑色,与白色相乘不变# 公式: 混合色 * 基色 / 255foreground = cv2.multiply(alpha, foreground) # 此时即相当于原图的png,黑色背景,混合色为(0~1)background = cv2.multiply(1 - alpha, background) # 背景图去除前景的部分为黑色,其它部分为背景色偏暗out_image = foreground + background# """测试时, opencv的imshow函数在显示double,对其认为是0~1,而大于1的地方都为白色,所以需要除以255"""# cv2.imshow("outImage", out_image / 255)# cv2.waitKey(0)cv2.imwrite(file_name, out_image)def run(self):# self.rm_bg()self.rename_no_bg_img()# [255, 255, 255]为替换的纯色(rgb,每一个颜色值为0-255)# xxxx.jpg 为生成的图片名self.change_bg_color([0, 124, 255], "xxxx.jpg")if __name__ == '__main__':# 需要移除背景的图片remove_bg = RemoveImgBg("xxx.jpg")remove_bg.run()
四、生成的结果(动漫)
4.1 原图:
4.2 移除背景图
4.3 填充纯色图片
四、生成的结果(人像)
4.1 原图
4.2 移除背景图
4.3 填充纯色图片
五、补充说明
纯色填充的值为rgb,具体想要替换颜色值小伙伴们可以自行搜索,或者通过颜色提取工具提取