广告位联系
返回顶部
分享到

python将红底证件照转成蓝底的实现方法

python 来源:互联网 作者:佚名 发布时间:2022-09-03 06:59:00 人浏览
摘要

前言 emmm9月1日开学季,手头只有红底证件照,但是学院要求要蓝底,这可咋办呢。懒得下ps了。自己撸起来吧。 方法一: lableme lableme标注完后。得到一个json文件,然后将这种json文件转

前言

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

方法一: lableme

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

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

# 代码来自 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生成图片

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

# 参考自: 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

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

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

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

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。

然后生成一个背景图片。

1

2

3

4

5

6

7

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)

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

1

2

src = Image.open('src.png')

bgr = Image.open('bgr.png')

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

1

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

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

1

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

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

1

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到规定倍数的宽和高。


版权声明 : 本文内容来源于互联网或用户自行发布贡献,该文观点仅代表原作者本人。本站仅提供信息存储空间服务和不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权, 违法违规的内容, 请发送邮件至2530232025#qq.cn(#换@)举报,一经查实,本站将立刻删除。
原文链接 : https://blog.csdn.net/weixin_43850253/article/details/126376767
相关文章
  • Python Django教程之实现新闻应用程序

    Python Django教程之实现新闻应用程序
    Django是一个用Python编写的高级框架,它允许我们创建服务器端Web应用程序。在本文中,我们将了解如何使用Django创建新闻应用程序。 我们将
  • 书写Python代码的一种更优雅方式(推荐!)

    书写Python代码的一种更优雅方式(推荐!)
    一些比较熟悉pandas的读者朋友应该经常会使用query()、eval()、pipe()、assign()等pandas的常用方法,书写可读性很高的「链式」数据分析处理代码
  • Python灰度变换中伽马变换分析实现

    Python灰度变换中伽马变换分析实现
    1. 介绍 伽马变换主要目的是对比度拉伸,将图像灰度较低的部分进行修正 伽马变换针对的是对单个像素点的变换,也就是点对点的映射 形
  • 使用OpenCV实现迷宫解密的全过程

    使用OpenCV实现迷宫解密的全过程
    一、你能自己走出迷宫吗? 如下图所示,可以看到是一张较为复杂的迷宫图,相信也有人尝试过自己一点一点的找出口,但我们肉眼来解谜
  • Python中的数据精度问题的介绍

    Python中的数据精度问题的介绍
    一、python运算时精度问题 1.运行时精度问题 在Python中(其他语言中也存在这个问题,这是计算机采用二进制导致的),有时候由于二进制和
  • Python随机值生成的常用方法

    Python随机值生成的常用方法
    一、随机整数 1.包含上下限:[a, b] 1 2 3 4 import random #1、随机整数:包含上下限:[a, b] for i in range(10): print(random.randint(0,5),end= | ) 查看运行结
  • Python字典高级用法深入分析讲解
    一、 collections 中 defaultdict 的使用 1.字典的键映射多个值 将下面的列表转成字典 l = [(a,2),(b,3),(a,1),(b,4),(a,3),(a,1),(b,3)] 一个字典就是一个键对
  • Python浅析多态与鸭子类型使用实例
    什么多态:同一事物有多种形态 为何要有多态=》多态会带来什么样的特性,多态性 多态性指的是可以在不考虑对象具体类型的情况下而直
  • Python字典高级用法深入分析介绍
    一、 collections 中 defaultdict 的使用 1.字典的键映射多个值 将下面的列表转成字典 l = [(a,2),(b,3),(a,1),(b,4),(a,3),(a,1),(b,3)] 一个字典就是一个键对
  • Python淘宝或京东等秒杀抢购脚本实现(秒杀脚本

    Python淘宝或京东等秒杀抢购脚本实现(秒杀脚本
    我们的目标是秒杀淘宝或京东等的订单,这里面有几个关键点,首先需要登录淘宝或京东,其次你需要准备好订单,最后要在指定时间快速
  • 本站所有内容来源于互联网或用户自行发布,本站仅提供信息存储空间服务,不拥有版权,不承担法律责任。如有侵犯您的权益,请您联系站长处理!
  • Copyright © 2017-2022 F11.CN All Rights Reserved. F11站长开发者网 版权所有 | 苏ICP备2022031554号-1 | 51LA统计