paddlepaddle人体属性识别onnx模型推断示例(python)

前言

首先非常感谢paddlepaddle对模型的开源。
本示例的onnx模型由paddleclas的PULC人体属性识别的推断模型官方下载通过paddle2onnx导出,同时去掉了hardsigmoid层从而方便部署到板端上,推断示例剥离了paddleclas的前后处理依赖,只使用opencv进行基础图像处理,使用onnxruntime进行模型推断,方便需要的朋友快速调试。
模型输入shape已静态化为(1,3,256,192)。
想尝试我转换的模型的朋友可以下载百度网盘
提取码222o。
如果想自己去除hardsigmoid层或者实现其他shape的,可以看我下一篇文章(不一定写)。
该人体属性识别可以通过一张图片识别行人性别、年龄、朝向、配饰、包、服装风格等,比如本示例就是对以下这张图片进行推断:
在这里插入图片描述
推断出的结果是:
[{‘attributes’: [‘Male’, ‘Age18-60’, ‘Back’, ‘Glasses: False’, ‘Hat: False’, ‘HoldObjectsInFront: False’, ‘Backpack’, ‘Upper: LongSleeve UpperPlaid’, ‘Lower: Trousers’, ‘No boots’], ‘output’: [0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1]}]
表示男性,年龄在18-60岁,站立为背向,没戴眼镜等等。

代码

import onnxruntime as ort
import numpy as np
import cv2
#outcome list
age_list = ['AgeLess18', 'Age18-60', 'AgeOver60']
direct_list = ['Front', 'Side', 'Back']
bag_list = ['HandBag', 'ShoulderBag', 'Backpack']
upper_list = ['UpperStride', 'UpperLogo', 'UpperPlaid', 'UpperSplice']
lower_list = ['LowerStripe', 'LowerPattern', 'LongCoat', 'Trousers', 'Shorts','Skirt&Dress']
#preprocess
def preproc(img, input_size):
    img = img[:, :, ::-1] #BGR to RGB
    img = cv2.resize(img, input_size,interpolation=1) #unified resize
    mean = [0.485, 0.456, 0.406]
    std = [0.229, 0.224, 0.225]
    mean = np.array(mean).reshape((1, 1, 3)).astype('float32') #broadcast
    std = np.array(std).reshape((1, 1, 3)).astype('float32')   #broadcast
    img = (img.astype('float32') * np.float32(1.0/255.0) - mean) / std #normalize scale:1.0/255.0
    img = img.transpose(2, 0, 1).astype('float32') #whc to chw
    return img
x = cv2.imread('090004.jpg') #input 53x163 jpg
x = preproc(x, (192,256)) #w,h
x = x.reshape(1,3,256,192) #batch1
#onnx inference
ort_sess = ort.InferenceSession('model.onnx')
outputs = ort_sess.run(None, {
    
    'x': x})
res = outputs[0][0]
print(res)
label = []
#postprocess threshold
threshold=0.5
glasses_threshold=0.3
hold_threshold=0.6
# gender 
gender = 'Female' if res[22] > threshold else 'Male'
label.append(gender)
# age
age = age_list[np.argmax(res[19:22])]
label.append(age)
# direction 
direction = direct_list[np.argmax(res[23:])]
label.append(direction)
# glasses
glasses = 'Glasses: '
if res[1] > glasses_threshold:
    glasses += 'True'
else:
    glasses += 'False'
label.append(glasses)
# hat
hat = 'Hat: '
if res[0] > threshold:
    hat += 'True'
else:
    hat += 'False'
label.append(hat)
# hold obj
hold_obj = 'HoldObjectsInFront: '
if res[18] > hold_threshold:
    hold_obj += 'True'
else:
    hold_obj += 'False'
label.append(hold_obj)
# bag
bag = bag_list[np.argmax(res[15:18])]
bag_score = res[15 + np.argmax(res[15:18])]
bag_label = bag if bag_score > threshold else 'No bag'
label.append(bag_label)
# upper
upper_res = res[4:8]
upper_label = 'Upper:'
sleeve = 'LongSleeve' if res[3] > res[2] else 'ShortSleeve'
upper_label += ' {}'.format(sleeve)
for i, r in enumerate(upper_res):
    if r > threshold:
        upper_label += ' {}'.format(upper_list[i])
label.append(upper_label)
# lower
lower_res = res[8:14]
lower_label = 'Lower: '
has_lower = False
for i, l in enumerate(lower_res):
    if l > threshold:
        lower_label += ' {}'.format(lower_list[i])
        has_lower = True
if not has_lower:
    lower_label += ' {}'.format(lower_list[np.argmax(lower_res)])

label.append(lower_label)
# shoe
shoe = 'Boots' if res[14] > threshold else 'No boots'
label.append(shoe)

threshold_list = [0.5] * len(res)
threshold_list[1] = glasses_threshold
threshold_list[18] = hold_threshold
pred_res = (np.array(res) > np.array(threshold_list)
            ).astype(np.int8).tolist()
batch_res = []
batch_res.append({
    
    "attributes": label, "output": pred_res})
print(batch_res)

总结

这一波尝试下来,感觉飞桨确实做的很好,算国产之光吧,不过框架本身安装麻烦,容易报错,而且还有没写明的负更新,本来想放一个飞桨框架的推断脚本的,但我windows上装了却没法正常推断,是网上查不到的dll错误,换到linux才能正常运行,所以这里就不放了。感觉一个框架集成度太高也不是好事,之前搜该模型有没有官方的onnx推断示例,结果都是集成化看不懂在做啥,要么就是推广自家的另一款产品,没办法满足我的需求。

猜你喜欢

转载自blog.csdn.net/weixin_43945848/article/details/128565601
今日推荐