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

如何将分割归一化后的cv::Mat数组传入TensorFlow Lite输入张量?

问题:将54个归一化的60×60 cv::Mat传入TensorFlow Lite输入张量(维度{54,60,60,1})

图像分割与归一化代码

已将540×360图像分割为54个60×60的CV_32F归一化Mat,存入std::vector<cv::Mat> arrayimganorm:

for (int r = 0; r < src.rows; r += 60) // src.rows = 540
{
    for (int c = 0; c < src.cols; c += 60) // src.cols = 360
    {
        cv::Mat imga = src(cv::Range(r, (r + 60)), cv::Range(c, (c + 60))).clone();
        cv::Mat imga_normalize;
        imga.convertTo(imga_normalize, CV_32F, 1.0 / 255, 0); 
        arrayimganorm.push_back(imga_normalize);
    }
}

尝试的两种错误方法

方法1:无memcpy的错误尝试

std::vector<cv::Mat>* data = &arrayimganorm;
for(int w = 0; w < 54; w++)
{
    interpreter->typed_input_tensor<float>(0)[w] = *(data++);
}

错误原因:typed_input_tensor<float>(0)[w]是单个float值,无法直接赋值整个cv::Mat;且data++操作错误,指向的是vector本身的下一个内存地址而非vector内的元素。

方法2:含memcpy的错误尝试

for(int w = 0; w < 54; w++)
{
    memcpy(interpreter->typed_input_tensor<float>(0)[w], arrayimganorm[w].data , arrayimganorm[w].total() * arrayimganorm[w].elemSize());
}

错误原因:typed_input_tensor<float>(0)[w]是float值而非指针,memcpy第一个参数要求是void*类型,类型不兼容。

模型加载与张量调整代码

已将输入张量维度调整为{54,60,60,1}:

model = tflite::FlatBufferModel::BuildFromBuffer(ptr, sizeof(ptr));
if (model == nullptr)
{
    fprintf(stderr, "Failed to load model\n");
    exit(-1);
}

tflite::ops::builtin::BuiltinOpResolver resolver;
tflite::InterpreterBuilder(*model.get(), resolver)(&interpreter);

if (interpreter == nullptr)
{
    fprintf(stderr, "Failed to initiate the interpreter\n");
    exit(-1);
}

interpreter->ResizeInputTensor(0, { 54, 60, 60, 1 });
// 原模型输入为1×60×60×1,改为批量输入54个样本以提升效率
... 
auto valor = interpreter->tensor(0)->dims->data[0]; // 输出54
auto height = interpreter->tensor(0)->dims->data[1]; // 输出60
auto width = interpreter->tensor(0)->dims->data[2]; // 输出60
auto channels = interpreter->tensor(0)->dims->data[3]; // 输出1

正确实现方法

核心是理解typed_input_tensor<float>(0)返回的是指向输入张量连续内存区域的float指针,需将每个cv::Mat的float数据依次拷贝到对应位置:

// 获取输入张量的float指针
float* input_tensor = interpreter->typed_input_tensor<float>(0);
// 每个Mat包含的元素数量(60×60×1)
const int elem_per_mat = 60 * 60 * 1;

for (int idx = 0; idx < arrayimganorm.size(); ++idx) {
    // 计算当前Mat在张量中的起始地址
    float* dst_start = input_tensor + idx * elem_per_mat;
    // 获取当前Mat的float数据指针
    const float* src_data = arrayimganorm[idx].ptr<float>();
    // 拷贝整个Mat的数据到张量对应位置
    memcpy(dst_start, src_data, elem_per_mat * sizeof(float));
}

关键注意事项

  • 确保arrayimganorm中的每个cv::Mat是连续内存:clone生成的Mat默认是连续的,若存在非连续操作(如roi裁剪未clone),可先调用arrayimganorm[idx].isContinuous()检查,或用arrayimganorm[idx].clone()确保连续。
  • 确认输入张量类型为float32:与cv::Mat的CV_32F类型匹配,避免类型不兼容问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 18:45:58