python将红底证件照转成蓝底的实现方法
作者:Andy?Dennis 发布时间:2023-09-25 19:20:57
前言
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)
大概是这样:
然后利用这个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标注时挺费力,并且难以避免人与背景边缘会有残留红色像素的情况。
方法二: 阈值
该方法通过比较像素的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)
结果人与背景边缘仍会存在红色像素残留
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秒。
方法三: 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)
需要上传人的照片和背景照片, 如果名字和路径不一样则需要修改一下代码
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。
原论文可以实现发丝级效果
报错解决方案
can’t divided by 4 / can’t divided by 16
由于该骨干模型可能进行4倍或16倍下采样,因此如果您的证件照不是该倍数的话,有两种选择方案。一种是padding, 填充后再送入模型,然后出结果后再用clip函数裁剪。另一种方式是resize, 给resize到规定倍数的宽和高。
这两种方案需要的代码都可以从这篇博文找到: python图像填充与裁剪/resize
来源:https://blog.csdn.net/weixin_43850253/article/details/126376767


猜你喜欢
- Django的Form主要具有一下几大功能:生成HTML标签验证用户数据(显示错误信息)HTML Form提交保留上次提交数据初始化页面显示
- 在python类当中,经常会遇到@classmethod和@staticmethod这两个装饰器,那么到底它们的区别和作用是啥子呢?具体来看
- 1. 列表使用sum, 如下代码,对1维列表和二维列表,numpy.sum(a)都能将列表a中的所有元素求和并返回,a.sum()用法是非法
- axios封装请求axios封装常见操作axios请求时的常见或者说是常用的操作,需要对常规的axios封装做出改变根据不同条件写出不同的效
- 无限分类是实际开发中经常用到的一种数据结构,一般我们称之为树形结构。题设:类似淘宝的商品分类,可以在任意分类设置其子类。 一、创建
- 二元函数为y=x1^2+x2^2,x∈[-5,5]NIND=121; %初始种群的个数(Number of individual
- 1. raw,mhd 格式医学图像数据转换raw+mhd格式是常见的一种医学图像格式,每一个病人的数据包含一个mhd文件和一个同名的raw文
- JavaScript lastIndexOf 方法lastIndexOf 方法用于计算指定的字符串在整个字符串中最后一次出现的位置,并返回该
- Pygame 中提供了一个draw模块用来绘制一些简单的图形状,比如矩形、多边形、圆形、直线、弧线等。pygame.draw模块的常用方法如
- 什么是事务?事务是数据库管理系统执行过程中的一个逻辑单位,由一个有限的数据库操作序列构成。数据库事务通常包含了一个序列的对数据库的读/写操作
- 今天有碰到这种情况,数据库中有张表没办法通过migration来更改, migrate时报 django.db.utils.Operatio
- 在js中this的指向对于新手来说一定是个难题,但是如果你真正理解了的话,也就没什么问题啦,下面就来讲讲this吧。JS中,this的值取决
- 另:@会影响效率如:@mysql_connect() 可以导出错误,但会影响效率。mysql与mysqli的区别:
- A.截取从字符串左边开始N个字符 Declare @S1 varchar(100) Select @S1='http://www.x
- 经常会看到这种弹出层背景变暗的效果,感觉手痒于是自己写了一个基于jquery的弹出层类。我习惯先写好结构和样式,然后再写js交互效果。结构定
- 本文实例讲述了python实现自动更换ip的方法。分享给大家供大家参考。具体实现方法如下:#!/usr/bin/env python#-*-
- 要将xian80地理坐标系转换成投影坐标系:xian1980 = """GEOGCS["GCS_Xi
- 本次爬虫用到的网址是:http://www.netbian.com/index.htm: 彼岸桌面.里面有很多的好看壁纸,而且都是可以下载高
- 以住做B/S的系统都是以IE浏览器为主,基本上忽略其他的浏览器,这次决定来个大兼容,但在实现背景渐变上就是个 * 烦。本想用图片来实现的,但要
- 前言上一篇博客我们知道的Mysql事务的隔离机制和实现,以及锁的详细解析链接: MySQL脏读幻读不可重复读及事务的隔离级别和MVCC、LB