ONNX模型推理算法,Python转c++备忘

部署运行你感兴趣的模型镜像

一、保存Mat数据,使用UltraCompare比对,检测代码的正确性

Python:

np.array([img.shape[0], img.shape[1], img.shape[2]], dtype=np.int32).tofile("d:\\shape_py.bin")
img.tofile("d:\\data_py.bin")  # 按行优先保存

C++:

void save_mat(cv::Mat mat) {
    // 保存尺寸信息
    std::ofstream shape_file("d:\\shape_cpp.bin", std::ios::binary);
    int shape[3] = { mat.rows, mat.cols, mat.channels() };
    shape_file.write(reinterpret_cast<char*>(shape), 3 * sizeof(int));
    shape_file.close();

    // 保存数据(按行优先保存)
    std::ofstream data_file("d:\\data_cpp.bin", std::ios::binary);
    data_file.write(reinterpret_cast<char*>(mat.data), mat.total() * mat.elemSize());
    data_file.close();
}

二、打印Mat数据,直接比对

Python:

print(image)

C++:

void print_mat(cv::Mat mat)
{
    //设定后续以科学计数法表示浮点数
    cout.setf(ios::scientific);

    for (int i = 0; i < mat.rows; ++i) {
        for (int j = 0; j < mat.cols; ++j) {
            double value = mat.at<double>(i, j);
            std::cout << std::setprecision(8) << value << " ";
        }
        std::cout << std::endl;
    }
}

三、打印vector

Python:print(...)
C++

// 打印vector<float>
void printVector(const std::vector<float>& vec) {
    std::cout << "[";
    for (size_t i = 0; i < vec.size(); ++i) {
        std::cout << vec[i];
        if (i != vec.size() - 1) {
            std::cout << ", ";
        }
    }
    std::cout << "]" << std::endl;
}

// 打印vector<pair<float, float>>
void printVectorOfPairs(const std::vector<std::pair<float, float>>& vec) {
    std::cout << "[";
    for (size_t i = 0; i < vec.size(); ++i) {
        std::cout << "(" << vec[i].first << ", " << vec[i].second << ")";
        if (i != vec.size() - 1) {
            std::cout << ", ";
        }
    }
    std::cout << "]" << std::endl;
}

四、C++库

onnxruntime,opencv,cnpy

五、辅助工具

DeepSeek,豆包

六、cv::Mat注意点

cv::Mat 是 OpenCV 中用于存储图像和矩阵数据的核心类,它采用 引用计数(Reference Counting) 机制来管理内存,以提高性能并减少不必要的拷贝。

  1. cv::Mat 的引用计数机制

    • 当 cv::Mat 被赋值或传参时,默认是 浅拷贝(Shallow Copy),即只复制 头信息(header)(如尺寸、数据类型、指针等),而 不复制实际的像素数据

    • 多个 cv::Mat 对象可以共享同一块内存,OpenCV 通过引用计数(refcount)来跟踪内存的使用情况。

    • 当最后一个引用该内存的 cv::Mat 被销毁时,OpenCV 才会释放这块内存。

  2. 问题场景:返回局部变量的 cv::Mat

    • 在你的代码中,result 是一个局部变量:

      cv::Mat result; cv::warpPerspective(image, result, matrix, dst_size); return std::make_tuple(result, ...); // 返回浅拷贝

    • 当 perspective_transform() 函数结束时,局部变量 result 会被销毁,但由于 cv::Mat 的引用计数机制:

      • 如果 result 被浅拷贝到 tupletuple 中的 cv::Mat 仍然指向原数据。

      • 当 result 析构时,如果引用计数降为 0,内存会被释放。

      • 但外部代码尝试访问 tuple 中的 cv::Mat 时,可能访问到已释放的内存,导致 堆损坏(Heap Corruption) 或 断言失败(Debug Assertion)

  3. 为什么 .clone() 能解决问题?

    • .clone() 会执行 深拷贝(Deep Copy),即 分配新内存并复制所有像素数据,使返回的 cv::Mat 完全独立于原对象:

      return std::make_tuple(result.clone(), ...); // 返回深拷贝

    • 这样:

      • tuple 中的 cv::Mat 拥有自己的数据,不受局部变量 result 析构的影响。

      • 避免了引用计数归零导致的内存释放问题。

您可能感兴趣的与本文相关的镜像

Python3.11

Python3.11

Conda
Python

Python 是一种高级、解释型、通用的编程语言,以其简洁易读的语法而闻名,适用于广泛的应用,包括Web开发、数据分析、人工智能和自动化脚本

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值