Skip to content

Commit d820513

Browse files
committed
support yolox-pose sdk
1 parent b7a69bc commit d820513

17 files changed

+307
-59
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
_base_ = ['./pose-detection_static.py', '../_base_/backends/sdk.py']
2+
3+
codebase_config = dict(model_type='sdk_yoloxpose')
4+
5+
backend_config = dict(pipeline=[
6+
dict(type='LoadImageFromFile'),
7+
dict(type='PoseToDetConverter'),
8+
dict(type='PackDetPoseInputs')
9+
])

csrc/mmdeploy/apis/c/mmdeploy/pose_detector.cpp

+14
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,8 @@ void mmdeploy_pose_detector_release_result(mmdeploy_pose_detection_t* results, i
6969
for (int i = 0; i < count; ++i) {
7070
delete[] results[i].point;
7171
delete[] results[i].score;
72+
delete[] results[i].bboxes;
73+
delete[] results[i].bbox_score;
7274
}
7375
delete[] results;
7476
}
@@ -156,16 +158,28 @@ int mmdeploy_pose_detector_get_result(mmdeploy_value_t output,
156158
for (const auto& bbox_result : detections) {
157159
auto& res = _results[result_idx++];
158160
auto size = bbox_result.key_points.size();
161+
auto num_bbox = bbox_result.detections.size();
159162

160163
res.point = new mmdeploy_point_t[size];
161164
res.score = new float[size];
162165
res.length = static_cast<int>(size);
166+
res.bboxes = new mmdeploy_rect_t[num_bbox];
167+
res.bbox_score = new float[num_bbox];
168+
res.num_bbox = static_cast<int>(num_bbox);
163169

164170
for (int k = 0; k < size; k++) {
165171
res.point[k].x = bbox_result.key_points[k].bbox[0];
166172
res.point[k].y = bbox_result.key_points[k].bbox[1];
167173
res.score[k] = bbox_result.key_points[k].score;
168174
}
175+
for (int k = 0; k < num_bbox; k++) {
176+
res.bboxes[k].left = bbox_result.detections[k].boundingbox[0];
177+
res.bboxes[k].top = bbox_result.detections[k].boundingbox[1];
178+
res.bboxes[k].right = bbox_result.detections[k].boundingbox[2];
179+
res.bboxes[k].bottom = bbox_result.detections[k].boundingbox[3];
180+
res.bbox_score[k] = bbox_result.detections[k].score;
181+
}
182+
169183
}
170184

171185
*results = _results.release();

csrc/mmdeploy/apis/c/mmdeploy/pose_detector.h

+4
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,10 @@ extern "C" {
1919
typedef struct mmdeploy_pose_detection_t {
2020
mmdeploy_point_t* point; ///< keypoint
2121
float* score; ///< keypoint score
22+
mmdeploy_rect_t* bboxes; ///< bboxes
23+
float* bbox_score; ///< bboxes score
2224
int length; ///< number of keypoint
25+
int num_bbox; ///< number of bboxes
2326
} mmdeploy_pose_detection_t;
2427

2528
typedef struct mmdeploy_pose_detector* mmdeploy_pose_detector_t;
@@ -76,6 +79,7 @@ MMDEPLOY_API int mmdeploy_pose_detector_apply(mmdeploy_pose_detector_t detector,
7679
* bboxes, must be release by \ref mmdeploy_pose_detector_release_result
7780
* @return status code of the operation
7881
*/
82+
7983
MMDEPLOY_API int mmdeploy_pose_detector_apply_bbox(mmdeploy_pose_detector_t detector,
8084
const mmdeploy_mat_t* mats, int mat_count,
8185
const mmdeploy_rect_t* bboxes,

csrc/mmdeploy/apis/python/pose_detector.cpp

+31-13
Original file line numberDiff line numberDiff line change
@@ -65,20 +65,38 @@ class PyPoseDetector {
6565

6666
auto output = py::list{};
6767
auto result = detection;
68+
6869
for (int i = 0; i < mats.size(); i++) {
69-
int n_point = result->length;
70-
auto pred = py::array_t<float>({bbox_count[i], n_point, 3});
71-
auto dst = pred.mutable_data();
72-
for (int j = 0; j < bbox_count[i]; j++) {
70+
int n_point_total = result->length;
71+
int n_bbox = result->num_bbox;
72+
int n_point = n_bbox > 0 ? n_point_total / n_bbox : 0;
73+
int pts_ind = 0;
74+
auto pred_pts = py::array_t<float>({n_bbox * n_point, 3});
75+
auto pred_bbox = py::array_t<float>({n_bbox, 5});
76+
auto dst_pts = pred_pts.mutable_data();
77+
auto dst_bbox = pred_bbox.mutable_data();
78+
79+
// printf("num_bbox %d num_pts %d\n", result->num_bbox, result->length);
80+
for (int j = 0; j < n_bbox; j++) {
7381
for (int k = 0; k < n_point; k++) {
74-
dst[0] = result->point[k].x;
75-
dst[1] = result->point[k].y;
76-
dst[2] = result->score[k];
77-
dst += 3;
82+
pts_ind = j * n_point + k;
83+
dst_pts[0] = result->point[pts_ind].x;
84+
dst_pts[1] = result->point[pts_ind].y;
85+
dst_pts[2] = result->score[pts_ind];
86+
dst_pts += 3;
87+
// printf("pts %f %f %f\n", dst_pts[0], dst_pts[1], dst_pts[2]);
88+
7889
}
79-
result++;
90+
dst_bbox[0] = result->bboxes[j].left;
91+
dst_bbox[1] = result->bboxes[j].top;
92+
dst_bbox[2] = result->bboxes[j].right;
93+
dst_bbox[3] = result->bboxes[j].bottom;
94+
dst_bbox[4] = result->bbox_score[j];
95+
// printf("box %f %f %f %f %f\n", dst_bbox[0], dst_bbox[1], dst_bbox[2], dst_bbox[3], dst_bbox[4]);
96+
dst_bbox += 5;
8097
}
81-
output.append(std::move(pred));
98+
result++;
99+
output.append(py::make_tuple(std::move(pred_bbox), std::move(pred_pts)));
82100
}
83101

84102
int total = std::accumulate(bbox_count.begin(), bbox_count.end(), 0);
@@ -101,12 +119,12 @@ static PythonBindingRegisterer register_pose_detector{[](py::module& m) {
101119
}),
102120
py::arg("model_path"), py::arg("device_name"), py::arg("device_id") = 0)
103121
.def("__call__",
104-
[](PyPoseDetector* self, const PyImage& img) -> py::array {
122+
[](PyPoseDetector* self, const PyImage& img) -> py::tuple {
105123
return self->Apply({img}, {})[0];
106124
})
107125
.def(
108126
"__call__",
109-
[](PyPoseDetector* self, const PyImage& img, const Rect& box) -> py::array {
127+
[](PyPoseDetector* self, const PyImage& img, const Rect& box) -> py::tuple {
110128
std::vector<std::vector<Rect>> bboxes;
111129
bboxes.push_back({box});
112130
return self->Apply({img}, bboxes)[0];
@@ -115,7 +133,7 @@ static PythonBindingRegisterer register_pose_detector{[](py::module& m) {
115133
.def(
116134
"__call__",
117135
[](PyPoseDetector* self, const PyImage& img,
118-
const std::vector<Rect>& bboxes) -> py::array {
136+
const std::vector<Rect>& bboxes) -> py::tuple {
119137
std::vector<std::vector<Rect>> _bboxes;
120138
_bboxes.push_back(bboxes);
121139
return self->Apply({img}, _bboxes)[0];

csrc/mmdeploy/codebase/mmpose/keypoints_from_heatmap.cpp

+5
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,9 @@ class TopdownHeatmapBaseHeadDecode : public MMPose {
5555
}
5656

5757
auto& img_metas = _data["img_metas"];
58+
if (img_metas.contains("bbox")) {
59+
from_value(img_metas["bbox"], bbox_);
60+
}
5861

5962
vector<float> center;
6063
vector<float> scale;
@@ -78,6 +81,7 @@ class TopdownHeatmapBaseHeadDecode : public MMPose {
7881
output.key_points.push_back({{x, y}, s});
7982
data += 3;
8083
}
84+
output.detections.push_back({{bbox_[0], bbox_[1], bbox_[2], bbox_[3]}, bbox_[4]});
8185
return to_value(std::move(output));
8286
}
8387

@@ -354,6 +358,7 @@ class TopdownHeatmapBaseHeadDecode : public MMPose {
354358
float valid_radius_factor_{0.0546875f};
355359
bool use_udp_{false};
356360
string target_type_{"GaussianHeatmap"};
361+
vector<float> bbox_{0, 0, 1, 1, 1};
357362
};
358363

359364
MMDEPLOY_REGISTER_CODEBASE_COMPONENT(MMPose, TopdownHeatmapBaseHeadDecode);

csrc/mmdeploy/codebase/mmpose/keypoints_from_regression.cpp

+6-1
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,9 @@ class DeepposeRegressionHeadDecode : public MMPose {
3636
}
3737

3838
auto& img_metas = _data["img_metas"];
39-
39+
if (img_metas.contains("bbox")) {
40+
from_value(img_metas["bbox"], bbox_);
41+
}
4042
vector<float> center;
4143
vector<float> scale;
4244
from_value(img_metas["center"], center);
@@ -60,6 +62,7 @@ class DeepposeRegressionHeadDecode : public MMPose {
6062
output.key_points.push_back({{x, y}, s});
6163
data += 3;
6264
}
65+
output.detections.push_back({{bbox_[0], bbox_[1], bbox_[2], bbox_[3]}, bbox_[4]});
6366
return to_value(std::move(output));
6467
}
6568

@@ -106,6 +109,8 @@ class DeepposeRegressionHeadDecode : public MMPose {
106109
*(data + 0) = *(data + 0) * scale_x + center[0] - scale[0] * 0.5;
107110
*(data + 1) = *(data + 1) * scale_y + center[1] - scale[1] * 0.5;
108111
}
112+
private:
113+
vector<float> bbox_{0, 0, 1, 1, 1};
109114
};
110115

111116
MMDEPLOY_REGISTER_CODEBASE_COMPONENT(MMPose, DeepposeRegressionHeadDecode);

csrc/mmdeploy/codebase/mmpose/mmpose.h

+8-1
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,17 @@ struct PoseDetectorOutput {
1717
float score;
1818
MMDEPLOY_ARCHIVE_MEMBERS(bbox, score);
1919
};
20+
struct BBox {
21+
std::array<float, 4> boundingbox; // x1,y1,x2,y2
22+
float score;
23+
MMDEPLOY_ARCHIVE_MEMBERS(boundingbox, score);
24+
};
2025
std::vector<KeyPoint> key_points;
21-
MMDEPLOY_ARCHIVE_MEMBERS(key_points);
26+
std::vector<BBox> detections;
27+
MMDEPLOY_ARCHIVE_MEMBERS(key_points, detections);
2228
};
2329

30+
2431
MMDEPLOY_DECLARE_CODEBASE(MMPose, mmpose);
2532

2633
} // namespace mmdeploy::mmpose

csrc/mmdeploy/codebase/mmpose/simcc_label.cpp

+6-2
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,9 @@ class SimCCLabelDecode : public MMPose {
4949
}
5050

5151
auto& img_metas = _data["img_metas"];
52-
52+
if (img_metas.contains("bbox")) {
53+
from_value(img_metas["bbox"], bbox_);
54+
}
5355
Tensor keypoints({Device{"cpu"}, DataType::kFLOAT, {simcc_x.shape(0), simcc_x.shape(1), 2}});
5456
Tensor scores({Device{"cpu"}, DataType::kFLOAT, {simcc_x.shape(0), simcc_x.shape(1), 1}});
5557
get_simcc_maximum(simcc_x, simcc_y, keypoints, scores);
@@ -73,6 +75,7 @@ class SimCCLabelDecode : public MMPose {
7375
keypoints_data += 2;
7476
scores_data += 1;
7577
}
78+
output.detections.push_back({{bbox_[0], bbox_[1], bbox_[2], bbox_[3]}, bbox_[4]});
7679
return to_value(output);
7780
}
7881

@@ -102,7 +105,8 @@ class SimCCLabelDecode : public MMPose {
102105
}
103106
}
104107

105-
private:
108+
private:
109+
vector<float> bbox_{0, 0, 1, 1, 1};
106110
bool flip_test_{false};
107111
bool shift_heatmap_{false};
108112
float simcc_split_ratio_{2.0};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
// Copyright (c) OpenMMLab. All rights reserved.
2+
3+
#include <cctype>
4+
#include <opencv2/imgproc.hpp>
5+
#include <iostream>
6+
#include <fstream>
7+
8+
#include "mmdeploy/core/device.h"
9+
#include "mmdeploy/core/registry.h"
10+
#include "mmdeploy/core/serialization.h"
11+
#include "mmdeploy/core/tensor.h"
12+
#include "mmdeploy/core/utils/device_utils.h"
13+
#include "mmdeploy/core/utils/formatter.h"
14+
#include "mmdeploy/core/value.h"
15+
#include "mmdeploy/experimental/module_adapter.h"
16+
#include "mmpose.h"
17+
#include "opencv_utils.h"
18+
19+
namespace mmdeploy::mmpose {
20+
21+
using std::string;
22+
using std::vector;
23+
24+
class YOLOXPose : public MMPose {
25+
public:
26+
explicit YOLOXPose(const Value& config) : MMPose(config) {
27+
if (config.contains("params")) {
28+
auto& params = config["params"];
29+
if (params.contains("score_thr")) {
30+
from_value(params["score_thr"], score_thr_);
31+
}
32+
}
33+
}
34+
35+
Result<Value> operator()(const Value& _data, const Value& _prob) {
36+
MMDEPLOY_DEBUG("preprocess_result: {}", _data);
37+
MMDEPLOY_DEBUG("inference_result: {}", _prob);
38+
39+
Device cpu_device{"cpu"};
40+
OUTCOME_TRY(auto dets,
41+
MakeAvailableOnDevice(_prob["dets"].get<Tensor>(), cpu_device, stream()));
42+
OUTCOME_TRY(auto keypoints,
43+
MakeAvailableOnDevice(_prob["keypoints"].get<Tensor>(), cpu_device, stream()));
44+
OUTCOME_TRY(stream().Wait());
45+
if (!(dets.shape().size() == 3 && dets.data_type() == DataType::kFLOAT)) {
46+
MMDEPLOY_ERROR("unsupported `dets` tensor, shape: {}, dtype: {}", dets.shape(),
47+
(int)dets.data_type());
48+
return Status(eNotSupported);
49+
}
50+
if (!(keypoints.shape().size() == 4 && keypoints.data_type() == DataType::kFLOAT)) {
51+
MMDEPLOY_ERROR("unsupported `keypoints` tensor, shape: {}, dtype: {}", keypoints.shape(),
52+
(int)keypoints.data_type());
53+
return Status(eNotSupported);
54+
}
55+
auto& img_metas = _data["img_metas"];
56+
vector<float> scale_factor;
57+
if (img_metas.contains("scale_factor")) {
58+
from_value(img_metas["scale_factor"], scale_factor);
59+
} else {
60+
scale_factor = {1.f, 1.f, 1.f, 1.f};
61+
}
62+
PoseDetectorOutput output;
63+
64+
float* keypoints_data = keypoints.data<float>();
65+
float* dets_data = dets.data<float>();
66+
int num_dets = dets.shape(1), num_pts = keypoints.shape(2);
67+
float s = 0, x1=0, y1=0, x2=0, y2=0;
68+
69+
// fprintf(stdout, "num_dets= %d num_pts = %d\n", num_dets, num_pts);
70+
for (int i = 0; i < dets.shape(0) * num_dets; i++){
71+
x1 = (*(dets_data++)) / scale_factor[0];
72+
y1 = (*(dets_data++)) / scale_factor[1];
73+
x2 = (*(dets_data++)) / scale_factor[2];
74+
y2 = (*(dets_data++)) / scale_factor[3];
75+
s = *(dets_data++);
76+
// fprintf(stdout, "box %.2f %.2f %.2f %.2f %.6f\n", i, x1,y1,x2,y2,s);
77+
78+
if (s <= score_thr_) {
79+
keypoints_data += num_pts * 3;
80+
continue;
81+
}
82+
output.detections.push_back({{x1, y1, x2, y2}, s});
83+
for (int k = 0; k < num_pts; k++) {
84+
x1 = (*(keypoints_data++)) / scale_factor[0];
85+
y1 = (*(keypoints_data++)) / scale_factor[1];
86+
s = *(keypoints_data++);
87+
// fprintf(stdout, "point %d, index %d, %.2f %.2f %.6f\n", k, x1, y1, s);
88+
output.key_points.push_back({{x1, y1}, s});
89+
}
90+
}
91+
return to_value(output);
92+
}
93+
94+
protected:
95+
float score_thr_ = 0.001;
96+
97+
};
98+
99+
MMDEPLOY_REGISTER_CODEBASE_COMPONENT(MMPose, YOLOXPose);
100+
101+
} // namespace mmdeploy::mmpose

csrc/mmdeploy/device/cpu/cpu_device.cpp

+4
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,10 @@ Result<void> CpuPlatformImpl::Copy(Buffer src, Buffer dst, size_t size, size_t s
161161
size_t dst_offset, Stream stream) {
162162
auto src_ptr = src.GetNative();
163163
auto dst_ptr = dst.GetNative();
164+
if (size == 0) {
165+
return success();
166+
}
167+
164168
if (!src_ptr || !dst_ptr) {
165169
return Status(eInvalidArgument);
166170
}

demo/csrc/CMakeLists.txt

+9-7
Original file line numberDiff line numberDiff line change
@@ -8,24 +8,25 @@ endif ()
88

99

1010
function(add_example task folder name)
11+
set(exec_name "${folder}.${name}")
1112
if ((NOT task) OR (task IN_LIST MMDEPLOY_TASKS))
1213
# Search for c/cpp sources
1314
file(GLOB _SRCS ${folder}/${name}.c*)
14-
add_executable(${name} ${_SRCS})
15+
add_executable(${exec_name} ${_SRCS})
1516
if (NOT (MSVC OR APPLE))
1617
# Disable new dtags so that executables can run even without LD_LIBRARY_PATH set
17-
target_link_libraries(${name} PRIVATE -Wl,--disable-new-dtags)
18+
target_link_libraries(${exec_name} PRIVATE -Wl,--disable-new-dtags)
1819
endif ()
1920
if (MMDEPLOY_BUILD_SDK_MONOLITHIC)
20-
target_link_libraries(${name} PRIVATE mmdeploy ${OpenCV_LIBS})
21+
target_link_libraries(${exec_name} PRIVATE mmdeploy ${OpenCV_LIBS})
2122
else ()
2223
# Load MMDeploy modules
23-
mmdeploy_load_static(${name} MMDeployStaticModules)
24-
mmdeploy_load_dynamic(${name} MMDeployDynamicModules)
24+
mmdeploy_load_static(${exec_name} MMDeployStaticModules)
25+
mmdeploy_load_dynamic(${exec_name} MMDeployDynamicModules)
2526
# Link to MMDeploy libraries
26-
target_link_libraries(${name} PRIVATE MMDeployLibs ${OpenCV_LIBS})
27+
target_link_libraries(${exec_name} PRIVATE MMDeployLibs ${OpenCV_LIBS})
2728
endif ()
28-
install(TARGETS ${name} RUNTIME DESTINATION bin)
29+
install(TARGETS ${exec_name} RUNTIME DESTINATION bin)
2930
endif ()
3031
endfunction()
3132

@@ -36,6 +37,7 @@ add_example(detector c batch_object_detection)
3637
add_example(segmentor c image_segmentation)
3738
add_example(restorer c image_restorer)
3839
add_example(text_detector c ocr)
40+
add_example(pose_detector c det_pose)
3941
add_example(pose_detector c pose_detection)
4042
add_example(rotated_detector c rotated_object_detection)
4143
add_example(video_recognizer c video_recognition)

0 commit comments

Comments
 (0)