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

C语言TensorFlow推理中图像转输入张量的异常问题排查

TensorFlow C语言推理应用:图像加载与张量构建问题

背景

我正在用TensorFlow开发C语言推理应用,已完成模型首尾层代码编写,且用模拟矩阵验证过应用逻辑。此前用固定值生成输入张量的代码运行正常:

// Specify input tensor dimensions
int ndims = 4; // Number of dimensions of the input tensor
int64_t dims[] = {1, 224, 224, 3}; // Dimensions of the input tensor (batch_size x height x width x channels)

// Generate sample data for input tensor
float data[1 * 224 * 224 * 3];
for (int i = 0; i < (1 * 224 * 224 * 3); i++) {
    data[i] = 1.00;
}
int ndata = sizeof(float) * 1 * 224 * 224 * 3;

改用stb_image库加载图像生成输入张量后,推理输出的softmax结果不符合预期(模型在Python中用相同权重验证准确率达97%)。需要确认当前图像加载方式的合理性,并找出代码中的不一致问题。


代码问题分析

第一版图像加载代码的核心问题

// Load image
const char* filename = "image.png"; 
int width, height, channels;
unsigned char *img = stbi_load(filename, &width, &height, &channels, 0); 
if (img == NULL) {
    printf("Error in loading the image\n");
    return 1;
}
// Specify input tensor dimensions
int ndims = 4; // Number of dimensions of the input tensor
int64_t dims[] = {1, 224, 224, 3}; // Dimensions of the input tensor (batch_size x height x width x channels)

// Aloca dinamicamente memória para armazenar os valores dos pixels da imagem
float *data = (float *)malloc(sizeof(float) * height * width * channels);
if (data == NULL) {
    printf("Error in allocating memory\n");
    return 1;
}

// Populates the 'data' array with the values of the image's pixels
for (int y = 0; y < height; y++) {
    for (int x = 0; x < width; x++) {
        for (int c = 0; c < channels; c++) {
            data[(y * width + x) * channels + c] = img[(y * width + x) * channels + c] / 255.0f; // Normaliza os valores dos pixels para o intervalo [0, 1]
        }
    }
}
int ndata = sizeof(float) * 1 * 224 * 224 * 3;

// Create input tensor
TF_Tensor* input_tensor = TF_NewTensor(TF_FLOAT, dims, ndims, data, ndata, &NoOpDeallocator, 0);
if (input_tensor != NULL) {
    printf("TF_NewTensor is OK\n");
} else {
    printf("ERROR: Failed TF_NewTensor\n");
}
  • 数据尺寸不匹配:data按加载图像的原始尺寸分配内存,但ndata却用固定的224*224*3计算。若加载图像不是224x224x3,会导致张量数据长度与实际内存不匹配,触发越界或数据缺失。
  • 未处理图像尺寸适配:直接假设加载图像与模型输入尺寸一致,未做resize处理,输入维度不符必然导致推理结果错误。

第二版修改后的代码问题

// Allocate data for inputs & outputs
TF_Tensor** InputValues = (TF_Tensor**)malloc(sizeof(TF_Tensor*) * NumInputs);
TF_Tensor** OutputValues = (TF_Tensor**)malloc(sizeof(TF_Tensor*) * NumOutputs);

// Specify input tensor dimensions
int ndims = 4; // Number of dimensions of the input tensor
int64_t dims[] = {1, 224, 224, 3}; // Dimensions of the input tensor (batch_size x height x width x channels)

// Load the image using stb_image.h
int width, height, channels;
unsigned char *image_data = stbi_load("play_accept_call1.png", &width, &height, &channels, 0);

// Check if the image was loaded successfully
if (!image_data) {
    printf("Error loading the image.\n");
    return 1;
}

// Allocate memory to store pixel values as float
float *data = (float *)malloc(sizeof(float) * dims[1] * dims[2] * dims[3]);

// Convert pixel values from unsigned char to float and normalize to the range [0, 1]
for (int i = 0; i < dims[1] * dims[2] * dims[3]; i++) {
    data[i] = (float)image_data[i] / 255.0;
}

// Free the memory allocated for the image data
stbi_image_free(image_data);

// Use the image data as needed

// Free the memory allocated for the float array
free(data);

// Calculate the total size of the data
int ndata = sizeof(float) * 1 * 224 * 224 * 3;

// Create input tensor
TF_Tensor* input_tensor = TF_AllocateTensor(TF_FLOAT, dims, ndims, ndata);
  • 提前释放关键内存:创建张量前就free(data),导致张量指向无效内存,推理时读取垃圾数据。
  • 张量未初始化数据:TF_AllocateTensor仅分配内存,未将data中的图像值拷贝进去,张量内部为未初始化的垃圾值。
  • 图像越界读取风险:直接按模型输入尺寸遍历读取image_data,若加载图像不是224x224x3,会触发数组越界读取。

修正建议

  1. 添加图像resize步骤:使用stb_image_resize库将加载的图像统一缩放到224x224x3尺寸,确保输入维度与模型要求一致。
  2. 修正内存管理逻辑:
    • 方式一:用TF_NewTensor并指定释放器,让TensorFlow自动管理内存:
      // 假设已将图像resize到224x224x3,数据存在resized_img中
      float *data = (float *)malloc(sizeof(float) * 224*224*3);
      // 转换并归一化数据...
      // 创建张量,指定free为释放器
      TF_Tensor* input_tensor = TF_NewTensor(TF_FLOAT, dims, ndims, data, ndata, &free, NULL);
      
    • 方式二:用TF_AllocateTensor后手动拷贝数据:
      TF_Tensor* input_tensor = TF_AllocateTensor(TF_FLOAT, dims, ndims, ndata);
      if (input_tensor) {
          float* tensor_data = TF_TensorData(input_tensor);
          memcpy(tensor_data, data, ndata);
      }
      free(data); // 数据已拷贝,可安全释放
      
  3. 统一数据尺寸计算:所有数据长度均基于模型要求的224x224x3计算,避免混用图像原始尺寸与模型输入尺寸。
  4. 检查图像通道数:确保加载图像为3通道(RGB),若为灰度图需转换为3通道后再输入模型。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 15:45:11