引言

最近有需求需要进行如下步骤

  1. 透明背景转白色背景
  2. 白色背景和划痕底图混合模式进行滤色
  3. 白色背景转透明背景

代码

透明背景转白色背景

1
2
3
4
5
6
7
8
9
10
11
12
13
def transparent2white(img_path):
img = Image.open(img_path)
if img.mode != 'RGBA':
img = img.convert('RGBA')
width = img.width
height = img.height

# 生成一张白色图片
new_img = Image.new('RGB', size=(width, height), color=(255, 255, 255))
new_img.paste(img, (0, 0), mask=img) # 将原透明图片覆盖到白色图片上
# pillow为RGB格式,opencv为BGR格式。输出将RGB转为BGR的ndarray格式
img = cv2.cvtColor(np.asarray(new_img), cv2.COLOR_RGB2BGR)
return img

混合模式滤色

1
2
3
4
5
6
7
8
9
10
def screen(img1, img2):    # 滤色
"""
img1和img2均为opencv处理图片时的ndarray类型
"""
img1 = img1 / 255.0
img2 = img2 / 255.0
img = 1 - np.multiply((1 - img1), (1 - img2)) # 根据滤色算法矩阵相乘
img = (img*255).astype(np.uint8)
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) # 输出将BGR转RGB的ndarray格式
return img

白色背景转透明背景

1
2
3
4
5
6
7
8
9
10
def white2transparent(img_ndarray):
threshold = 100
dist = 5
img = Image.fromarray(img_ndarray).convert('RGBA')
arr = np.array(np.asarray(img))
r, g, b, a = np.rollaxis(arr, axis=-1)
mask = ((r>threshold) & (g>threshold) & (b>threshold) & (np.abs(r-g)<dist) & (np.abs(r-b)<dist) & (np.abs(g-b)<dist))
arr[mask, 3] = 0
img = Image.fromarray(arr, mode='RGBA')
return img

整体代码

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
41
42
43
44
45
46
47
48
import cv2
import numpy as np
from PIL import Image


def transparent2white(img_path):
img = Image.open(img_path)
if img.mode != 'RGBA':
img = img.convert('RGBA')
width = img.width
height = img.height

# 生成一张白色图片
new_img = Image.new('RGB', size=(width, height), color=(255, 255, 255))
new_img.paste(img, (0, 0), mask=img) # 将原透明图片覆盖到白色图片上
# pillow为RGB格式,opencv为BGR格式。输出将RGB转为BGR的ndarray格式
img = cv2.cvtColor(np.asarray(new_img), cv2.COLOR_RGB2BGR)
return img


def screen(img1, img2): # 滤色
"""
img1和img2均为opencv处理图片时的ndarray类型
"""
img1 = img1 / 255.0
img2 = img2 / 255.0
img = 1 - np.multiply((1 - img1), (1 - img2)) # 根据滤色算法矩阵相乘
img = (img*255).astype(np.uint8)
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) # 输出将BGR转RGB的ndarray格式
return img


def white2transparent(img_ndarray):
threshold = 100
dist = 5
img = Image.fromarray(img_ndarray).convert('RGBA')
arr = np.array(np.asarray(img))
r, g, b, a = np.rollaxis(arr, axis=-1)
mask = ((r>threshold) & (g>threshold) & (b>threshold) & (np.abs(r-g)<dist) & (np.abs(r-b)<dist) & (np.abs(g-b)<dist))
arr[mask, 3] = 0
img = Image.fromarray(arr, mode='RGBA')
return img


white_img = transparent2white('transparent.png')
basemap_img = cv2.imread('basemap.jpg')
colorfilter_img = screen(white_img, basemap_img)
white2transparent(colorfilter_img).save('final.png', format='PNG')