Skip to content

Commit d0f7348

Browse files
committed
add custom background.
1 parent ce3a976 commit d0f7348

5 files changed

Lines changed: 213 additions & 0 deletions

File tree

26cv/custom_background/__init__.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# -*- coding: utf-8 -*-
2+
"""
3+
@author:XuMing([email protected])
4+
@description:
5+
"""
6+
18 KB
Loading
75.6 KB
Loading
22.2 KB
Loading

26cv/custom_background/segmap.py

Lines changed: 207 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,207 @@
1+
# -*- coding: utf-8 -*-
2+
"""
3+
@author:XuMing([email protected])
4+
@description:
5+
"""
6+
7+
import cv2
8+
import matplotlib.pyplot as plt
9+
import numpy as np
10+
import torch
11+
import torchvision.transforms as T
12+
from PIL import Image
13+
from torchvision import models
14+
15+
16+
def decode_segmap(image, nc=21):
17+
"""
18+
函数:将 2D 分割图像转换为 RGB 图像,其中每一个标签被映射到对应的颜色.
19+
:param image:
20+
:param nc:
21+
:return:
22+
"""
23+
label_colors = np.array([(0, 0, 0), # 0=background
24+
# 1=aeroplane, 2=bicycle, 3=bird, 4=boat, 5=bottle
25+
(128, 0, 0), (0, 128, 0), (255, 255, 255), (0, 0, 128), (128, 0, 128),
26+
# 6=bus, 7=car, 8=cat, 9=chair, 10=cow
27+
(0, 128, 128), (128, 128, 128), (64, 0, 0), (192, 0, 0), (64, 128, 0),
28+
# 11=dining table, 12=dog, 13=horse, 14=motorbike, 15=person
29+
(192, 128, 0), (64, 0, 128), (192, 0, 128), (64, 128, 128), (255, 255, 255),
30+
# 16=potted plant, 17=sheep, 18=sofa, 19=train, 20=tv/monitor
31+
(0, 64, 0), (128, 64, 0), (0, 192, 0), (128, 192, 0), (0, 64, 128)])
32+
33+
r = np.zeros_like(image).astype(np.uint8)
34+
g = np.zeros_like(image).astype(np.uint8)
35+
b = np.zeros_like(image).astype(np.uint8)
36+
for l in range(0, nc):
37+
idx = image == l
38+
r[idx] = label_colors[l, 0]
39+
g[idx] = label_colors[l, 1]
40+
b[idx] = label_colors[l, 2]
41+
rgb = np.stack([r, g, b], axis=2)
42+
return rgb
43+
44+
45+
def segment(net, path, show_orig=True, device='cpu'):
46+
"""
47+
图像预处理
48+
:param net:
49+
:param path:
50+
:param show_orig:
51+
:param device:
52+
:return:
53+
"""
54+
img = Image.open(path)
55+
if show_orig:
56+
plt.imshow(img)
57+
plt.axis('off')
58+
plt.show()
59+
60+
# Comment the Resize and CenterCrop for better inference results
61+
trf = T.Compose([T.ToTensor(),
62+
T.Normalize(mean=[0.485, 0.456, 0.406],
63+
std=[0.229, 0.224, 0.225])])
64+
inp = trf(img).unsqueeze(0).to(device)
65+
out = net.to(device)(inp)['out']
66+
om = torch.argmax(out.squeeze(), dim=0).detach().cpu().numpy()
67+
rgb = decode_segmap(om)
68+
return rgb
69+
70+
71+
def change_background_image(foreground_img_file, background_img_file, rgb):
72+
# 背景融合(Alpha blending)实现
73+
# alpha blending to customize the background of the image
74+
75+
# Read the images
76+
foreground = cv2.imread(foreground_img_file)
77+
background = cv2.imread(background_img_file, cv2.IMREAD_COLOR)
78+
background = cv2.resize(background, (rgb.shape[1], rgb.shape[0]), interpolation=cv2.INTER_AREA)
79+
alpha = rgb # 2.3
80+
81+
# Convert uint8 to float
82+
foreground = foreground.astype(float)
83+
background = background.astype(float)
84+
# Normalize the alpha mask to keep intensity between 0 and 1
85+
alpha = alpha.astype(float) / 255
86+
# Multiply the foreground with the alpha matte
87+
foreground = cv2.multiply(alpha, foreground)
88+
# Multiply the background with ( 1 - alpha )
89+
background = cv2.multiply(1.0 - alpha, background)
90+
# Add the masked foreground and background.
91+
out = cv2.add(foreground, background)
92+
93+
# Save/download image
94+
cv2.imwrite('org_plus_cust_bkg_img.png', out)
95+
return out
96+
97+
98+
def whiten_background(foreground_img_file, rgb):
99+
img = cv2.imread(foreground_img_file)
100+
# whiten the background of the image
101+
mask_out = cv2.subtract(rgb, img)
102+
mask_out = cv2.subtract(rgb, mask_out)
103+
mask_out[rgb == 0] = 255
104+
105+
# Display the result
106+
numpy_horizontal_concat = np.concatenate((img, mask_out), axis=1)
107+
# Save/download the resulting image
108+
cv2.imwrite('org_plus_white_bkg_image.jpeg', numpy_horizontal_concat)
109+
return mask_out
110+
111+
112+
def remove_background(foreground_img_file, rgb):
113+
img = cv2.imread(foreground_img_file)
114+
# whiten the background of the image
115+
mask_out = cv2.subtract(rgb, img)
116+
mask_out = cv2.subtract(rgb, mask_out)
117+
mask_out[rgb == 0] = 255
118+
119+
b_channel, g_channel, r_channel = cv2.split(mask_out)
120+
alpha_channel = np.ones(b_channel.shape, dtype=b_channel.dtype) * 255
121+
# 最小值为0, alpha=0表示透明,不可见,仅png图片支持显示
122+
alpha_channel[np.where(b_channel == 255)] = 0
123+
out = cv2.merge((b_channel, g_channel, r_channel, alpha_channel))
124+
# Save/download the resulting image
125+
cv2.imwrite('rebg.png', out)
126+
return mask_out
127+
128+
129+
def blur_background(foreground_img_file, rgb):
130+
# Read the images
131+
foreground = cv2.imread(foreground_img_file)
132+
133+
# Create a Gaussian blur of kernel size 7 for the background image
134+
blurred_image = cv2.GaussianBlur(foreground, (7, 7), 0)
135+
# Convert uint8 to float
136+
foreground = foreground.astype(float)
137+
blurred_image = blurred_image.astype(float)
138+
139+
# Create a binary mask of the RGB output map using the threshold value 0
140+
th, alpha = cv2.threshold(np.array(rgb), 0, 255, cv2.THRESH_BINARY)
141+
142+
# Apply a slight blur to the mask to soften edges
143+
alpha = cv2.GaussianBlur(alpha, (7, 7), 0)
144+
# Normalize the alpha mask to keep intensity between 0 and 1
145+
alpha = alpha.astype(float) / 255
146+
# Multiply the foreground with the alpha matte
147+
foreground = cv2.multiply(alpha, foreground)
148+
# Multiply the background with ( 1 - alpha )
149+
background = cv2.multiply(1.0 - alpha, blurred_image)
150+
# Add the masked foreground and background
151+
out = cv2.add(foreground, background)
152+
153+
# Save/download the resulting image
154+
cv2.imwrite('res_blur.png', out)
155+
return out
156+
157+
158+
def grayscale_background(foreground_img_file, rgb):
159+
# Load the foreground input image
160+
foreground = cv2.imread(foreground_img_file)
161+
162+
# Resize image to match shape of R-band in RGB output map
163+
foreground = cv2.resize(foreground, (rgb.shape[1], rgb.shape[0]), interpolation=cv2.INTER_AREA)
164+
# Create a background image by copying foreground and converting into grayscale
165+
background = cv2.cvtColor(foreground, cv2.COLOR_BGR2GRAY)
166+
# convert single channel grayscale image to 3-channel grayscale image
167+
background = cv2.cvtColor(background, cv2.COLOR_GRAY2RGB)
168+
# Convert uint8 to float
169+
foreground = foreground.astype(float)
170+
background = background.astype(float)
171+
# Create a binary mask of the RGB output map using the threshold value 0
172+
th, alpha = cv2.threshold(np.array(rgb), 0, 255, cv2.THRESH_BINARY)
173+
# Apply a slight blur to the mask to soften edges
174+
alpha = cv2.GaussianBlur(alpha, (7, 7), 0)
175+
# Normalize the alpha mask to keep intensity between 0 and 1
176+
alpha = alpha.astype(float) / 255
177+
# Multiply the foreground with the alpha matte
178+
foreground = cv2.multiply(alpha, foreground)
179+
# Multiply the background with ( 1 - alpha )
180+
background = cv2.multiply(1.0 - alpha, background)
181+
# Add the masked foreground and background
182+
out = cv2.add(foreground, background)
183+
# Save image
184+
cv2.imwrite('res_gray.png', out)
185+
return out
186+
187+
188+
if __name__ == '__main__':
189+
# 加载 deeplabv3_resnet101 模型
190+
dlab = models.segmentation.deeplabv3_resnet101(pretrained=True).eval()
191+
192+
foreground_img_file = './data/bicycle-1.jpg'
193+
background_img_file = './data/field-1.jpg'
194+
rgb = segment(dlab, foreground_img_file, show_orig=False, device='cpu')
195+
## If there are multiple labeled objects in the image, use the below code to have only the target as the foreground
196+
rgb[rgb != 255] = 0
197+
198+
remove_background(foreground_img_file, rgb)
199+
200+
# replace background image
201+
change_background_image(foreground_img_file, background_img_file, rgb)
202+
203+
# whiten background image
204+
whiten_background(foreground_img_file, rgb)
205+
206+
blur_background(foreground_img_file, rgb)
207+
grayscale_background(foreground_img_file, rgb)

0 commit comments

Comments
 (0)