通过Pybind11传递C++ cv::Mat到Python YOLO触发std::bad_alloc错误
解决C++ cv::Mat传递给Ultralytics YOLO触发std::bad_alloc的问题
以下是针对该问题的常见原因及对应解决方法:
1. 通道顺序不匹配
C++ cv::imread 默认读取BGR格式图像,但Ultralytics YOLO的Python接口处理时,会自动将cv2.imread的BGR输入转为RGB;而C++传递的Mat直接进入推理时,缺少这个转换步骤,导致模型内部内存计算错误。
修复代码:
cv::Mat img = cv::imread("your_image.jpg"); cv::cvtColor(img, img, cv::COLOR_BGR2RGB); // 转为YOLO期望的RGB格式
2. 内存连续性问题
Python的numpy数组是内存连续的,而C++的cv::Mat可能因读取或后续操作导致内存不连续,步长与numpy的预期不符,YOLO处理时会错误计算内存需求,触发std::bad_alloc。
修复代码:
if (!img.isContinuous()) { img = img.clone(); // 克隆生成内存连续的Mat }
3. Pybind11转换错误
若未正确使用Pybind11的OpenCV转换器,或返回的Mat生命周期管理不当,会导致Python端拿到无效内存地址。
修复要点:
- 必须包含头文件
<pybind11/opencv.h>,确保cv::Mat与numpy数组的自动转换 - 绑定函数返回
cv::Mat值(而非引用/指针),让Pybind11处理内存:
#include <pybind11/pybind11.h> #include <pybind11/opencv.h> namespace py = pybind11; py::Mat load_image(const std::string& path) { cv::Mat img = cv::imread(path); cv::cvtColor(img, img, cv::COLOR_BGR2RGB); if (!img.isContinuous()) img = img.clone(); return img; } PYBIND11_MODULE(yolo_cpp_bind, m) { m.def("load_image", &load_image, "Load image in C++ for YOLO inference"); }
4. 数据类型不匹配
YOLO默认要求输入为8位无符号三通道图像(CV_8UC3),若C++读取的Mat是灰度图、16位深度等格式,会触发内存分配错误。
修复代码:
// 强制读取为彩色图,再转为CV_8UC3格式 cv::Mat img = cv::imread(path, cv::IMREAD_COLOR); img.convertTo(img, CV_8UC3);
内容的提问来源于stack exchange,提问作者shipeng zeng
相关产品推荐
相关产品推荐

