open-mmlab / mmpose

OpenMMLab Pose Estimation Toolbox and Benchmark.
https://mmpose.readthedocs.io/en/latest/
Apache License 2.0
5.91k stars 1.26k forks source link

使用c++推理rtmpose的tensorRT模型效果变差 #2690

Closed Haroldhy closed 1 year ago

Haroldhy commented 1 year ago

Prerequisite

Environment

我使用了mmdeploy/tools/depoly.py导出了rtmpose的.engine模型,并使用mmpose\projects\rtmpose\examples\RTMPose-Deploy\Windows\TensorRT\src\RTMPoseTensorRT文件夹下的c++代码进行推理。很奇怪的是,在部分情况下,我推理得到的结果比直接使用mmpose/demo/topdown_demo_with_mmdet.py推理pytorch模型的效果差。请问这是为什么呢? 此外,我修改了后处理的两行代码,才能够显示正确的keypoints,不然keypoint的横坐标和纵坐标会反过来,修改代码如下: //temp_point.x = (pose_x - offset[0]) img_w / (input_w - 2 offset[0]); //temp_point.y = (pose_y - offset[1]) img_h / (input_h - 2 offset[1]);

temp_point.x = pose_x * img_w / input_w;
temp_point.y = pose_y * img_h / input_h;

Reproduces the problem - code sample

std::vector TrtRTMPose::postprocess(std::vector simcc_x_result, std::vector simcc_y_result, int img_w, int img_h) { std::vector pose_result; for (int i = 0; i < num_points; ++i) { // find the maximum and maximum indexes in the value of each Extend_width length auto x_biggest_iter = std::max_element(simcc_x_result.begin() + i extend_width, simcc_x_result.begin() + i extend_width + extend_width); int max_x_pos = std::distance(simcc_x_result.begin() + i extend_width, x_biggest_iter); int pose_x = max_x_pos / 2; float score_x = x_biggest_iter;

    // find the maximum and maximum indexes in the value of each exten_height length
    auto y_biggest_iter = std::max_element(simcc_y_result.begin() + i * extend_height, simcc_y_result.begin() + i * extend_height + extend_height);
    int max_y_pos = std::distance(simcc_y_result.begin() + i * extend_height, y_biggest_iter);
    int pose_y = max_y_pos / 2;
    float score_y = *y_biggest_iter;

    // get point confidence
    float score = MAX(score_x, score_y);

    PosePoint temp_point;
    //temp_point.x = (pose_x - offset[0]) * img_w / (input_w - 2 * offset[0]);
    //temp_point.y = (pose_y - offset[1]) * img_h / (input_h - 2 * offset[1]);

temp_point.x = pose_x * img_w / input_w;
temp_point.y = pose_y * img_h / input_h;

    temp_point.score = score;
    pose_result.emplace_back(temp_point);
}

return pose_result;

}

Reproduces the problem - command or script

E:\hy\algorithm\workspace\mmpose\projects\rtmpose\examples\RTMPose-Deploy\Windows\TensorRT\src\RTMPoseTensorRT/main.cpp

Reproduces the problem - error message

tensorRT的运行结果与原来的结果有差距,就是原先pytorch模型可以预测准确的内容现在预测不准了,这一点让我感到非常奇怪。但在简单情况下,姿态的预测仍然准确,而在一些复杂任务中的表现会下降。

Additional information

No response

Tau-J commented 1 year ago

@Haroldhy 你好,pytorch 推理脚本默认开启了flip_test,这会为模型精度带来1 AP左右的提升,c++版本单次推理应该不带tta,因此效果会略有差异。你可以关闭pytorch的flip_test再对比一下推理结果能否对齐,以此来判断c++代码有无问题。

Haroldhy commented 1 year ago

感谢回答,我关闭了flip_test,但是还是和我c++推理的结果很不一样。当在复杂情况下(也不是特别复杂的情况,仅仅是人侧身或者躺下之类的情况),c++代码推理的结果就比原来的结果差非常多,部分姿态点会乱跳。您还有什么建议吗? 我在原来代码的前后处理基础上修改了下列代码:

    //前处理中
//std::tuple<cv::Mat, int, int> resized = resize(image, input_w, input_h);
//cv::Mat resized_image = std::get<0>(resized);

    cv::resize(image, resized_image, cv::Size(input_w, input_h));//我认为是opencv版本的问题

    //后处理中
    //temp_point.x = (pose_x - offset[0]) * img_w / (input_w - 2 * offset[0]);
    //temp_point.y = (pose_y - offset[1]) * img_h / (input_h - 2 * offset[1]);

temp_point.x = pose_x * img_w / input_w;
temp_point.y = pose_y * img_h / input_h;//用原来的代码出来的结果x和y会反过来

我仅在原来的c++代码上修改了如上代码以及加载tensorRT模型的相关代码,但我认为这些代码不应当影响预测结果

Tau-J commented 1 year ago

我无法定位你的问题,但是这份代码据我了解是跟pytorch版本结果可以对齐的。我想请问你的输入图片是否有使用det模型进行检测和裁剪,因为RTMPose 是一个topdown算法,如果单独将未检测的图片送入Pose模型,会导致性能大幅度下降,这是我想到的一种常见的误用。

Haroldhy commented 1 year ago

我是用rtmdet检测然后裁剪了图片,然后再用rtmpose推理的。这是我导出onnx和engine的代码,请问有什么明显的问题吗?python .\tools\deploy.py .\configs\mmpose\pose-detection_simcc_tensorrt_dynamic-256x192.py ..\mmpose\projects\rtmpose\rtmpose\body_2d_keypoint\rtmpose-m_8xb256-420e_coco-256x192.py .\weights\rtmpose-m_simcc-aic-coco_pt-aic-coco_420e-256x192-63eb25f7_20230126.pth .\demo\resources\human-pose.jpg --work-dir rtmpose-trt/rtmpose-m --device cuda:0 --show --dump-info c++加载engine文件推理图片的所有输出我都进行了打印,导出的模型的输出为(keypoint_number个)输入宽度和高度两倍的数组,其中每个元素为该关键点出现在该(横/纵)坐标下的概率。分别在横纵坐标取出最大值即为最后的结果(keypoint所在的坐标)。如果问我的上述逻辑没有问题的话,则c++代码没有问题。那么问题只能是出现在onnx和engine文件的导出上。

Haroldhy commented 1 year ago

另外,我没有看懂RTMpose页面下的用python的API调用tensorRT的推理,我不知道要如何进行推理。我将这个其放到mmploy文件夹下,并运行 python .\test_tensorRT.py cuda:0 .\rtmpose-trt\rtmpose-m\end2end.engine .\demo\resources\human-pose.jpg,结果报错:

loading mmdeploy_trt_net.dll ... loading mmdeploy_ort_net.dll ... [2023-09-14 19:00:04.958] [mmdeploy] [info] [zip_model_impl.cpp:38] Failed to open zip file .\rtmpose-trt\rtmpose-m\end2end.engine, ret 19 [2023-09-14 19:00:04.958] [mmdeploy] [error] [model.cpp:40] Failed to load model: ".\rtmpose-trt\rtmpose-m\end2end.engine", implementations tried: [("DirectoryModel", 0), ("ZipModel", 0)] [2023-09-14 19:00:04.959] [mmdeploy] [error] [model.cpp:16] Failed to load model ".\rtmpose-trt\rtmpose-m\end2end.engine" [2023-09-14 19:00:04.960] [mmdeploy] [error] [model.cpp:21] failed to create model: not supported (2) Traceback (most recent call last): File ".\test_tensorRT.py", line 51, in main() File ".\test_tensorRT.py", line 30, in main detector = PoseDetector( RuntimeError: failed to create pose_detector

您可以帮我看一下是什么问题吗?或者您有什么其他建议的推理RTMPose的tensorRT模型的python代码吗?这样我就可以根据python代码检查我的c++代码了

Tau-J commented 1 year ago

请仔细阅读文档和示例中的注释,输入是文件夹,不是.engine文件

liangzhenghao2000 commented 1 year ago

解决问题了吗,我这边测试wholebody的trt模型效果也变差了很多

Haroldhy commented 1 year ago

我的问题是因为库中提供的c++推理代码的前处理使得输入图像变形了,前处理的时候不要让它变形就好了。如果是自己写的代码应该不会有这个问题。

liangzhenghao2000 commented 1 year ago

我的问题是因为库中提供的c++推理代码的前处理使得输入图像变形了,前处理的时候不要让它变形就好了。如果是自己写的代码应该不会有这个问题。

库中的代码是mmpose这边提供的那个吗?我这边看好像还挺正常的。

Haroldhy commented 1 year ago

https://github.com/open-mmlab/mmpose/tree/main/projects/rtmpose/examples/RTMPose-Deploy/Windows/TensorRT 我记得当时看的是这里的代码

liangzhenghao2000 commented 1 year ago

https://github.com/open-mmlab/mmpose/tree/main/projects/rtmpose/examples/RTMPose-Deploy/Windows/TensorRT 我记得当时看的是这里的代码

嗯,代码我看了,前处理那部分让输入图像变形了吗?我看到只是缩放了然后置中放进输入里了

Haroldhy commented 1 year ago

我觉得问题就在于直接缩放,导致了人被拉长或者压扁了。我测试出来是对效果有影响的,将前处理改为填充黑边再缩放,测试效果就正常了。

liangzhenghao2000 commented 1 year ago

我觉得问题就在于直接缩放,导致了人被拉长或者压扁了。我测试出来是对效果有影响的,将前处理改为填充黑边再缩放,测试效果就正常了。

你那个问题可能是一路引用修改到原图了,这个问题我之前解决了,那看来我们遇到的不是一个问题

FunnyWii commented 8 months ago

请问这个RTMPose是只能用C++ TensorRT在Windows下面部署吗