Skip to content

Commit 2183bab

Browse files
authored
Add files via upload
0 parents  commit 2183bab

23 files changed

+696
-0
lines changed

common.py

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
import sys
2+
import os
3+
import cv2 as cv
4+
5+
def add_argument(zoo, parser, name, help, required=False, default=None, type=None, action=None, nargs=None):
6+
if len(sys.argv) <= 1:
7+
return
8+
9+
modelName = sys.argv[1]
10+
11+
if os.path.isfile(zoo):
12+
fs = cv.FileStorage(zoo, cv.FILE_STORAGE_READ)
13+
node = fs.getNode(modelName)
14+
if not node.empty():
15+
value = node.getNode(name)
16+
if not value.empty():
17+
if value.isReal():
18+
default = value.real()
19+
elif value.isString():
20+
default = value.string()
21+
elif value.isInt():
22+
default = int(value.real())
23+
elif value.isSeq():
24+
default = []
25+
for i in range(value.size()):
26+
v = value.at(i)
27+
if v.isInt():
28+
default.append(int(v.real()))
29+
elif v.isReal():
30+
default.append(v.real())
31+
else:
32+
print('Unexpected value format')
33+
exit(0)
34+
else:
35+
print('Unexpected field format')
36+
exit(0)
37+
required = False
38+
39+
if action == 'store_true':
40+
default = 1 if default == 'true' else (0 if default == 'false' else default)
41+
assert(default is None or default == 0 or default == 1)
42+
parser.add_argument('--' + name, required=required, help=help, default=bool(default),
43+
action=action)
44+
else:
45+
parser.add_argument('--' + name, required=required, help=help, default=default,
46+
action=action, nargs=nargs, type=type)
47+
48+
def add_preproc_args(zoo, parser, sample):
49+
aliases = []
50+
if os.path.isfile(zoo):
51+
fs = cv.FileStorage(zoo, cv.FILE_STORAGE_READ)
52+
root = fs.root()
53+
for name in root.keys():
54+
model = root.getNode(name)
55+
if model.getNode('sample').string() == sample:
56+
aliases.append(name)
57+
58+
parser.add_argument('alias', nargs='?', choices=aliases,
59+
help='An alias name of model to extract preprocessing parameters from models.yml file.')
60+
add_argument(zoo, parser, 'model', required=True,
61+
help='Path to a binary file of model contains trained weights. '
62+
'It could be a file with extensions .caffemodel (Caffe), '
63+
'.pb (TensorFlow), .t7 or .net (Torch), .weights (Darknet), .bin (OpenVINO)')
64+
add_argument(zoo, parser, 'config',
65+
help='Path to a text file of model contains network configuration. '
66+
'It could be a file with extensions .prototxt (Caffe), .pbtxt or .config (TensorFlow), .cfg (Darknet), .xml (OpenVINO)')
67+
add_argument(zoo, parser, 'mean', nargs='+', type=float, default=[0, 0, 0],
68+
help='Preprocess input image by subtracting mean values. '
69+
'Mean values should be in BGR order.')
70+
add_argument(zoo, parser, 'scale', type=float, default=1.0,
71+
help='Preprocess input image by multiplying on a scale factor.')
72+
add_argument(zoo, parser, 'width', type=int,
73+
help='Preprocess input image by resizing to a specific width.')
74+
add_argument(zoo, parser, 'height', type=int,
75+
help='Preprocess input image by resizing to a specific height.')
76+
add_argument(zoo, parser, 'rgb', action='store_true',
77+
help='Indicate that model works with RGB input images instead BGR ones.')
78+
add_argument(zoo, parser, 'classes',
79+
help='Optional path to a text file with names of classes to label detected objects.')
80+
81+
def findFile(filename):
82+
if filename:
83+
if os.path.exists(filename):
84+
return filename
85+
86+
fpath = cv.samples.findFile(filename, False)
87+
if fpath:
88+
return fpath
89+
90+
samplesDataDir = os.path.join(os.path.dirname(os.path.abspath(__file__)),
91+
'..',
92+
'data',
93+
'dnn')
94+
if os.path.exists(os.path.join(samplesDataDir, filename)):
95+
return os.path.join(samplesDataDir, filename)
96+
97+
for path in ['OPENCV_DNN_TEST_DATA_PATH', 'OPENCV_TEST_DATA_PATH']:
98+
try:
99+
extraPath = os.environ[path]
100+
absPath = os.path.join(extraPath, 'dnn', filename)
101+
if os.path.exists(absPath):
102+
return absPath
103+
except KeyError:
104+
pass
105+
106+
print('File ' + filename + ' not found! Please specify a path to '
107+
'/opencv_extra/testdata in OPENCV_DNN_TEST_DATA_PATH environment '
108+
'variable or pass a full path to model.')
109+
exit(0)

human_parsing.py

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
import argparse
2+
import os.path
3+
import numpy as np
4+
import cv2 as cv
5+
6+
backends = (cv.dnn.DNN_BACKEND_DEFAULT, cv.dnn.DNN_BACKEND_INFERENCE_ENGINE, cv.dnn.DNN_BACKEND_OPENCV)
7+
targets = (cv.dnn.DNN_TARGET_CPU, cv.dnn.DNN_TARGET_OPENCL, cv.dnn.DNN_TARGET_OPENCL_FP16, cv.dnn.DNN_TARGET_MYRIAD, cv.dnn.DNN_TARGET_HDDL)
8+
def preprocess(image):
9+
"""
10+
Create 4-dimensional blob from image and flip image
11+
:param image: input image
12+
"""
13+
image_rev = np.flip(image, axis=1)
14+
input = cv.dnn.blobFromImages([image, image_rev], mean=(104.00698793, 116.66876762, 122.67891434))
15+
return input
16+
17+
def run_net(input, model_path, backend, target):
18+
"""
19+
Read network and infer model
20+
:param model_path: path to JPPNet model
21+
:param backend: computation backend
22+
:param target: computation device
23+
"""
24+
net = cv.dnn.readNet(model_path)
25+
net.setPreferableBackend(backend)
26+
net.setPreferableTarget(target)
27+
net.setInput(input)
28+
out = net.forward()
29+
return out
30+
31+
32+
def postprocess(out, input_shape):
33+
"""
34+
Create a grayscale human segmentation
35+
:param out: network output
36+
:param input_shape: input image width and height
37+
"""
38+
# LIP classes
39+
# 0 Background
40+
# 1 Hat
41+
# 2 Hair
42+
# 3 Glove
43+
# 4 Sunglasses
44+
# 5 UpperClothes
45+
# 6 Dress
46+
# 7 Coat
47+
# 8 Socks
48+
# 9 Pants
49+
# 10 Jumpsuits
50+
# 11 Scarf
51+
# 12 Skirt
52+
# 13 Face
53+
# 14 LeftArm
54+
# 15 RightArm
55+
# 16 LeftLeg
56+
# 17 RightLeg
57+
# 18 LeftShoe
58+
# 19 RightShoe
59+
head_output, tail_output = np.split(out, indices_or_sections=[1], axis=0)
60+
head_output = head_output.squeeze(0)
61+
tail_output = tail_output.squeeze(0)
62+
63+
head_output = np.stack([cv.resize(img, dsize=input_shape) for img in head_output[:, ...]])
64+
tail_output = np.stack([cv.resize(img, dsize=input_shape) for img in tail_output[:, ...]])
65+
66+
tail_list = np.split(tail_output, indices_or_sections=list(range(1, 20)), axis=0)
67+
tail_list = [arr.squeeze(0) for arr in tail_list]
68+
tail_list_rev = [tail_list[i] for i in range(14)]
69+
tail_list_rev.extend([tail_list[15], tail_list[14], tail_list[17], tail_list[16], tail_list[19], tail_list[18]])
70+
tail_output_rev = np.stack(tail_list_rev, axis=0)
71+
tail_output_rev = np.flip(tail_output_rev, axis=2)
72+
raw_output_all = np.mean(np.stack([head_output, tail_output_rev], axis=0), axis=0, keepdims=True)
73+
raw_output_all = np.argmax(raw_output_all, axis=1)
74+
raw_output_all = raw_output_all.transpose(1, 2, 0)
75+
return raw_output_all
76+
77+
78+
def decode_labels(gray_image):
79+
"""
80+
Colorize image according to labels
81+
:param gray_image: grayscale human segmentation result
82+
"""
83+
height, width, _ = gray_image.shape
84+
colors = [(0, 0, 0), (128, 0, 0), (255, 0, 0), (0, 85, 0), (170, 0, 51), (255, 85, 0),
85+
(0, 0, 85), (0, 119, 221), (85, 85, 0), (0, 85, 85), (85, 51, 0), (52, 86, 128),
86+
(0, 128, 0), (0, 0, 255), (51, 170, 221), (0, 255, 255),(85, 255, 170),
87+
(170, 255, 85), (255, 255, 0), (255, 170, 0)]
88+
89+
segm = np.stack([colors[idx] for idx in gray_image.flatten()])
90+
segm = segm.reshape(height, width, 3).astype(np.uint8)
91+
segm = cv.cvtColor(segm, cv.COLOR_BGR2RGB)
92+
return segm
93+
94+
95+
def parse_human(image, model_path, backend=cv.dnn.DNN_BACKEND_OPENCV, target=cv.dnn.DNN_TARGET_CPU):
96+
"""
97+
Prepare input for execution, run net and postprocess output to parse human.
98+
:param image: input image
99+
:param model_path: path to JPPNet model
100+
:param backend: name of computation backend
101+
:param target: name of computation target
102+
"""
103+
input = preprocess(image)
104+
input_h, input_w = input.shape[2:]
105+
output = run_net(input, model_path, backend, target)
106+
grayscale_out = postprocess(output, (input_w, input_h))
107+
segmentation = decode_labels(grayscale_out)
108+
return segmentation
109+
110+
if __name__ == '__main__':
111+
parser = argparse.ArgumentParser(description='Use this script to run human parsing using JPPNet', formatter_class=argparse.ArgumentDefaultsHelpFormatter)
112+
parser.add_argument('--input', '-i', required=True, help='Path to input image.')
113+
parser.add_argument('--model', '-m', default='lip_jppnet_384.pb', help='Path to pb model.')
114+
parser.add_argument('--backend', choices=backends, default=cv.dnn.DNN_BACKEND_DEFAULT, type=int,
115+
help="Choose one of computation backends: "
116+
"%d: automatically (by default), "
117+
"%d: Intel's Deep Learning Inference Engine (https://software.intel.com/openvino-toolkit), "
118+
"%d: OpenCV implementation" % backends)
119+
parser.add_argument('--target', choices=targets, default=cv.dnn.DNN_TARGET_CPU, type=int,
120+
help='Choose one of target computation devices: '
121+
'%d: CPU target (by default), '
122+
'%d: OpenCL, '
123+
'%d: OpenCL fp16 (half-float precision), '
124+
'%d: NCS2 VPU, '
125+
'%d: HDDL VPU' % targets)
126+
args, _ = parser.parse_known_args()
127+
128+
if not os.path.isfile(args.model):
129+
raise OSError("Model not exist")
130+
131+
image = cv.imread(args.input)
132+
output = parse_human(image, args.model, args.backend, args.target)
133+
winName = 'Deep learning human parsing in OpenCV'
134+
cv.namedWindow(winName, cv.WINDOW_AUTOSIZE)
135+
cv.imshow(winName, output)
136+
cv.waitKey()

0 commit comments

Comments
 (0)