You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

无数据拷贝实现OpenCV Mat转Open3D Tensor的最高效方法

结论

可以实现零拷贝转换,只要你提到的「数据连续、格式一致」的前提成立,同时做好内存生命周期管理即可。

前置校验要求

转换前必须确认以下条件,否则会出现访问异常:

  • cv::Mat 必须是连续存储的,可通过 cv::Mat::isContinuous()(C++)或 numpy.ndarray.flags['C_CONTIGUOUS'](Python)校验
  • 两者数据类型严格匹配,比如CV_8UC3对应uint8类型、CV_32FC1对应float32类型,不能出现类型不匹配的情况
  • 原cv::Mat的内存释放时机必须晚于转换后的Open3D Tensor的使用时机,避免野指针访问

C++ 实现代码

Open3D的Tensor构造函数支持直接传入外部数据指针,通过copy=false参数指定不拷贝内存:

#include <opencv2/opencv.hpp>
#include <open3d/core/Tensor.h>

// 你的cv::Mat实例
cv::Mat img = cv::imread("test.png");
CV_Assert(img.isContinuous());

// 配置Tensor参数:OpenCV默认布局为(H, W, C),和Open3D默认布局匹配
open3d::core::SizeVector shape = {img.rows, img.cols, img.channels()};
// 此处根据你的Mat类型调整,示例为CV_8UC3对应的UInt8类型
open3d::core::Dtype dtype = open3d::core::Dtype::UInt8;
open3d::core::Device device("CPU:0"); // 如果是GPU数据对应改成"CUDA:0"

// 零拷贝构造,copy=false表示Tensor不持有内存所有权,内存仍由cv::Mat管理
open3d::core::Tensor o3d_tensor(img.data, shape, dtype, device, /*copy=*/false);

如果需要让Tensor自主管理内存生命周期,可以绑定自定义内存释放器:

// 用智能指针持有cv::Mat,延长其生命周期
auto mat_holder = std::make_shared<cv::Mat>(img);
auto deleter = [mat_holder](void* ptr) mutable {
    mat_holder.reset(); // 智能指针自动释放cv::Mat内存
};
open3d::core::Tensor o3d_tensor(img.data, shape, dtype, device, deleter);

Python 实现代码

Python接口下通过numpy数组做中间桥接,默认就是零拷贝:

import cv2
import open3d as o3d

img = cv2.imread("test.png")
# 校验数组连续性
assert img.flags['C_CONTIGUOUS']

# 零拷贝构造Tensor,copy=False表示不复制内存
o3d_tensor = o3d.core.Tensor(img, copy=False)

注意:Python环境下由引用计数自动管理内存,只要保留原img对象的引用不被回收,Tensor就可以正常访问。


额外说明

转换后的Tensor和原cv::Mat共享同一块内存,任意一方修改数据都会同步到另一方,如果需要避免互相影响,可将构造参数改为copy=true做内存拷贝。

内容的提问来源于stack exchange,提问作者Roland Deschain

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 04:45:05