脚本之家,脚本语言编程技术及教程分享平台!
分类导航

Python|VBS|Ruby|Lua|perl|VBA|Golang|PowerShell|Erlang|autoit|Dos|bat|

服务器之家 - 脚本之家 - Python - python将红底证件照转成蓝底的实现方法(证件照换底色)

python将红底证件照转成蓝底的实现方法(证件照换底色)

2022-08-31 15:42Andy Dennis Python

这篇文章主要介绍了python将红底证件照转成蓝底,本文给大家分享四种方法通过示例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

前言

emmm…9月1日开学季,手头只有红底证件照,但是学院要求要蓝底,这可咋办呢。懒得下ps了。自己撸起来吧。

 

方法一: lableme

lableme标注完后。得到一个json文件,然后将这种json文件转成掩码图.

# 代码来自 https://blog.csdn.net/hello_dear_you/article/details/120130155
import json
import numpy as np
import cv2
# read json file
with open("origin_json/mypic.json", "r") as f:
    data = f.read()
 
# convert str to json objs
data = json.loads(data)
 
# get the points 
points = data["shapes"][0]["points"]
points = np.array(points, dtype=np.int32)   # tips: points location must be int32
 
# read image to get shape
image = cv2.imread("origin_png/person.jpg")
 
# create a blank image
mask = np.zeros_like(image, dtype=np.uint8)
 
# fill the contour with 255
cv2.fillPoly(mask, [points], (255, 255, 255))
 
# save the mask 
cv2.imwrite("mask/person_mask.png", mask)

大概是这样:

python将红底证件照转成蓝底的实现方法(证件照换底色)

然后利用这个mask生成图片

# 参考自: https://www.jianshu.com/p/1961aa0c02ee
import cv2
import numpy as np
origin_png = "origin_png/person.jpg"
# maskPath = "mask/person_mask.png"
maskPath = "mask/bmv2.png"
result_png = "result_png/result_png.png"
maskImg = cv2.imread(maskPath)
img = cv2.imread(origin_png)
assert maskImg.shape == img.shape, "maskImg.shape != origin_png.shape"

h, w = img.shape[0], img.shape[1]
print("图片宽度: {}, 高度: {}".format(h, w))

rgb = (19,122,171)
bgr = (rgb[2], rgb[1], rgb[0])
# (B, G, R)
for i in range(h):
    for j in range(w):
        if (maskImg[i, j] == 0).all():
            img[i, j] = bgr
cv2.imwrite(result_png, img)
print("图片写入 {} 成功".format(result_png))

由于人长得一般,就不放图了…

缺点:
lableme标注时挺费力,并且难以避免人与背景边缘会有残留红色像素的情况。

python将红底证件照转成蓝底的实现方法(证件照换底色)

 

方法二: 阈值

该方法通过比较像素的RGB与背景的RGB来区分是否为图像背景。

 

Opencv

import cv2
import numpy as np
def mean_square_loss(a_np, b_np):
    sl = np.square(a_np - b_np)
    return np.mean(sl)
def change_red2blue(origin_png, result_png):
    img = cv2.imread(origin_png)
    h, w = img.shape[0], img.shape[1]
    print("图片宽度: {}, 高度: {}".format(h, w))
    origin_rgb = (168,36,32)  # 可以用浏览器啥的控制台工具提取出背景的rgb值
    origin_bgr = (origin_rgb[2], origin_rgb[1], origin_rgb[0])
    target_rgb = (19,122,171) # 蓝底RBG
    target_bgr = (target_rgb[2], target_rgb[1], target_rgb[0])
    for i in range(h):
        for j in range(w):
            # (B, G, R)
            if mean_square_loss(img[i, j], origin_bgr) < 50:
                img[i, j] = target_bgr 
    cv2.imwrite(result_png, img)
    print("图片写入 {} 成功".format(result_png))
if __name__ == "__main__":
    # origin_png = "result_png/result_png.png"
    origin_png = "origin_png/person.jpg"
    result_png = "result_png/result_refine.png"
    change_red2blue(origin_png, result_png)

结果人与背景边缘仍会存在红色像素残留

python将红底证件照转成蓝底的实现方法(证件照换底色)

 

PIL

from torchvision.transforms.functional import to_tensor, to_pil_image
from PIL import Image
import torch
import time
def mean_square_loss(a_ts, b_ts):
    # print(a_ts.shape)
    # print(b_ts)
    sl = (a_ts - b_ts) ** 2
    return sl.sum()
def change_red2blue(origin_png, result_png):
    src = Image.open(origin_png)
    src = to_tensor(src)
    # print(src.shape)  # torch.Size([3, 800, 600])
    # channel: (R, G, B) / 255
    h, w = src.shape[1], src.shape[2]

    pha = torch.ones(h, w, 3)

    bg = torch.tensor([168,36,32]) / 255
    target_bg = torch.tensor([19,122,171]) / 255

    # C, H, W -> H, W, C
    src = src.permute(1, 2, 0)
    for i in range(h):
        for j in range(w):
            if mean_square_loss(src[i][j], bg) < 0.025: # 0.025是阈值,超参数
                pha[i][j] = torch.tensor([0.0, 0.0, 0.0])

    # H, W, C -> C, H, W
    src = src.permute(2, 0, 1)
    pha = pha.permute(2, 0, 1)
    com = pha * src + (1 - pha) * target_bg.view(3, 1, 1)
    to_pil_image(com).save(result_png)
if __name__ == "__main__":
    origin_png = "origin_png/person.jpg"
    result_png = "result_png/com.png"
    start_time = time.time()
    change_red2blue(origin_png, result_png)
    spend_time = round(time.time() - start_time, 2)
    print("生成成功,共花了 {} 秒".format(spend_time))

该方法质量较好,但一张图片大概需要12秒。

python将红底证件照转成蓝底的实现方法(证件照换底色)

 

方法三: Background MattingV2

Real-Time High-Resolution Background Matting
CVPR 2021 oral

论文:https://arxiv.org/abs/2012.07810
代码:https://github.com/PeterL1n/BackgroundMattingV2

github的readme.md有inference的colab链接,可以用那个跑

由于这篇论文是需要输入一张图片(例如有人存在的草地上)和背景图片的(如果草地啥的), 然后模型会把人抠出来。

于是这里我需要生成一个背景图片。
首先我先借助firefox的颜色拾取器(或者微信截图,或者一些在线工具,例如菜鸟工具),得到十六进制,再用在线转换工具转成rgb。

然后生成一个背景图片。

import cv2
import numpy as np
image = cv2.imread("origin_png/person.jpg")
origin_rgb = (168,36,32)  # 可以用浏览器啥的控制台工具提取出背景的rgb值
origin_bgr = (origin_rgb[2], origin_rgb[1], origin_rgb[0])
image[:, :] = origin_bgr
cv2.imwrite("mask/bg.png", image)

python将红底证件照转成蓝底的实现方法(证件照换底色)

需要上传人的照片和背景照片, 如果名字和路径不一样则需要修改一下代码

src = Image.open("src.png")
bgr = Image.open("bgr.png")

另外原论文是边绿底,要变蓝底,白底,红底则可以修改RGB值,举个例子,原来是这样的(绿底, RGB120, 255, 155)

com = pha * fgr + (1 - pha) * torch.tensor([120/255, 255/255, 155/255], device="cuda").view(1, 3, 1, 1)

那么加入我要换白底(255, 255, 255),就是

com = pha * fgr + (1 - pha) * torch.tensor([255/255, 255/255, 255/255], device="cuda").view(1, 3, 1, 1)

假如像我换蓝底(19,122,171)具体深浅可以调节一下RGB,就是

com = pha * fgr + (1 - pha) * torch.tensor([19/255, 122/255, 171/255], device="cuda").view(1, 3, 1, 1)

总结: 其实这种方法从 任何颜色的照片 都可以 换成任何颜色的底。只要换下RGB.

然后就输出图片了。可以看到效果相当好。不愧是oral。

python将红底证件照转成蓝底的实现方法(证件照换底色)

原论文可以实现发丝级效果

python将红底证件照转成蓝底的实现方法(证件照换底色)

报错解决方案
can’t divided by 4 / can’t divided by 16
由于该骨干模型可能进行4倍或16倍下采样,因此如果您的证件照不是该倍数的话,有两种选择方案。一种是padding, 填充后再送入模型,然后出结果后再用clip函数裁剪。另一种方式是resize, 给resize到规定倍数的宽和高。
这两种方案需要的代码都可以从这篇博文找到: python图像填充与裁剪/resize

到此这篇关于python将红底证件照转成蓝底的文章就介绍到这了,更多相关python证件照转换内容请搜索服务器之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持服务器之家!

原文地址:https://blog.csdn.net/weixin_43850253/article/details/126376767

延伸 · 阅读

精彩推荐
  • Pythonpython sort、sort_index方法代码实例

    python sort、sort_index方法代码实例

    这篇文章主要介绍了python sort、sort_index方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着...

    我不不不是宅男8642021-06-09
  • PythonPython设计模式之解释器模式原理与用法实例分析

    Python设计模式之解释器模式原理与用法实例分析

    这篇文章主要介绍了Python设计模式之解释器模式原理与用法,结合具体实例形式分析了解释器模式的概念、原理、定义及使用方法,需要的朋友可以参考下...

    Andy冉明11042021-05-14
  • PythonPython列表list操作符实例分析【标准类型操作符、切片、连接字符、列表解析、重复操作等】

    Python列表list操作符实例分析【标准类型操作符、切片、连接字符

    这篇文章主要介绍了Python列表list操作符,结合实例形式分析了标准类型操作符、切片、连接字符、列表解析、重复操作等使用技巧,需要的朋友可以参考下...

    坏蛋是我5122020-11-28
  • Python图文详解WinPE下安装Python

    图文详解WinPE下安装Python

    这篇文章主要以图文结合的方式详细介绍了WinPE下安装Python的具体实现步骤,感兴趣的小伙伴们可以参考一下 ...

    shinobiii6822020-08-23
  • Python利用numpy+matplotlib绘图的基本操作教程

    利用numpy+matplotlib绘图的基本操作教程

    这篇文章主要给大家介绍了利用numpy+matplotlib绘图的基本操作,文中介绍的非常详细,对大家学习matplotlib绘图具有一定的参考学习价值,需要的朋友们下面...

    Myths2702020-10-06
  • Pythonpython如何正确使用yield

    python如何正确使用yield

    在 Python 开发中,yield 关键字的使用其实较为频繁,例如大集合的生成,简化代码结构、协程与并发都会用到它。但是,你是否真正了解 yield 的运行过程呢...

    Magic Kaito6072021-11-10
  • PythonPandas搭配lambda组合使用详解

    Pandas搭配lambda组合使用详解

    大家好,在之前文章中,我们介绍了很多 Python 用法。喜欢的朋友可以看一下历史文章。今天我给大家讲讲lambda与pandas模块配合使用方法,熟练掌握可以极...

    Python学习与数据挖掘9852022-08-29
  • Pythonpython基础之爬虫入门

    python基础之爬虫入门

    这篇文章主要介绍了python基础之爬虫入门,文中有非常详细的代码示例,对正在学习python爬虫的小伙伴们有很好地帮助哟,需要的朋友可以参考下...

    佩瑞4902021-10-27