ESP32-S3-N16R8: Failed to allocate persistent buffer of size 512, does not fit in tensor arena and reached EI_MAX_OVERFLOW_BUFFER_COUNT

Question/Issue:
I am trying to run an Edge Impulse image classification model (cat vs. dog) on an ESP32-S3 board using an RGB image stored in a .h file (not using the camera input). The image is manually resized and passed as RGB888 values to the resized_matrix->item, then classified using run_classifier().

However, during inference, I encounter the following error:
“Failed to allocate persistent buffer of size 512, does not fit in tensor arena and reached EI_MAX_OVERFLOW_BUFFER_COUNT”

To address this, I have:

  • Enabled OPI PSRAM in the board settings.
  • Selected the “Huge APP (3MB No OTA/1MB SPIFFS)” partition scheme.
  • Added #define EI_TENSOR_ARENA_LOCATION ".psram" in my sketch.
  • Tried manually increasing the tensor arena size by editing the following files:
    • In model_variables.h:
      #define EI_CLASSIFIER_TFLITE_ARENA_SIZE  (512 * 1024)
      
    • In model_metadata.h:
      #define EI_CLASSIFIER_TFLITE_LARGEST_ARENA_SIZE  (1024 * 1024)
      

Despite these adjustments, the error still persists. Is there any additional configuration needed to fully allocate the tensor arena in PSRAM or allow persistent buffer allocation to succeed?

Project ID:
743568

Context/Use case:
I am deploying an image classification model (cat vs. dog) trained on Edge Impulse and exported as an Arduino library. I use an ESP32-S3-N16R8 development board with Arduino IDE.

Instead of capturing live images from the ESP32-CAM, I import a test image stored as a .h file (converted from JPEG to RGB format) and assign its pixel data to resized_matrix.

Then, I run inference using run_classifier(), but I encountered a memory allocation error like:
Failed to allocate persistent buffer of size 1024, does not fit in tensor arena and reached EI_MAX_OVERFLOW_BUFFER_COUNT

I’ve enabled PSRAM and selected a large partition scheme (Huge APP 3MB), but the issue persists. This prevents me from running any inference.

Steps Taken:

  1. Trained a cat vs. dog image classification model on Edge Impulse Studio (web version).
  2. Exported the model as an Arduino library (.zip) and imported it into Arduino IDE 2.3.6.
  3. Converted a test JPEG image to .h format with RGB888 array using Python, and embedded it into the sketch.
  4. Used resized_matrix->item to store the pixel array and passed it to run_classifier().
  5. Enabled PSRAM (OPI PSRAM) and selected partition scheme: Huge APP (3MB No OTA/1MB SPIFFS).
  6. Encountered runtime error: Failed to allocate persistent buffer of size 1024, does not fit in tensor arena and reached EI_MAX_OVERFLOW_BUFFER_COUNT.

Expected Outcome:
[Describe what you expected to happen]

Actual Outcome:
[Describe what actually happened]

Reproducibility:

  • [╳ ] Always
  • [ ] Sometimes
  • [ ] Rarely

Environment:

  • Platform: [ESP32-S3-N16R8]
  • Build Environment Details: [ Arduino IDE 2.3.6]
  • OS Version: [Windows 10]
  • Edge Impulse Version (Firmware): [1.73.4]
  • To find out Edge Impulse Version:
  • if you have pre-compiled firmware: run edge-impulse-run-impulse --raw and type AT+INFO. Look for Edge Impulse version in the output.
  • if you have a library deployment: inside the unarchived deployment, open model-parameters/model_metadata.h and look for EI_STUDIO_VERSION_MAJOR, EI_STUDIO_VERSION_MINOR, EI_STUDIO_VERSION_PATCH
  • Edge Impulse CLI Version: Using Edge Impulse Studio Web
  • Project Version: Latest, exported as Arduino Library on July 2025
  • Custom Blocks / Impulse Configuration:
    • Image classification model
    • Input shape: 96x96x3 RGB
    • Uses image data from manually resized and embedded .h file
    • DSP: “Resize and Scale”
    • No anomaly detection
      Logs/Attachments:
      螢幕擷取畫面 2025-07-22 112816

Additional Information:
This is the main code of Arduino IDE, kindly check.

#define EI_CLASSIFIER_ALLOCATION_STATIC 1
#define EI_TENSOR_ARENA_LOCATION ".psram"
#include <esp32-cam-cat-dog_inferencing.h>
#include "cutecat.h"  // Your JPEG image file .h

#include "esp_heap_caps.h"

#include "img_converters.h"    // ESP32 Camera Library
#include "image_util.h"        // ESP32 Camera Library

dl_matrix3du_t *resized_matrix = NULL;

// Decode the JPEG array and resize it
bool jpeg_decode_and_resize() {
    Serial.println("Decoding JPEG...");
    dl_matrix3du_t *rgb888_matrix = dl_matrix3du_alloc(1, cutecat_width, cutecat_height, 3);
    if (!rgb888_matrix) {
        Serial.println("Allocate rgb888_matrix failed!");
        return false;
    }
    if (!fmt2rgb888((uint8_t*)cutecat, cutecat_len, PIXFORMAT_JPEG, rgb888_matrix->item)) {
        Serial.println("JPEG decode failed!");
        dl_matrix3du_free(rgb888_matrix);
        return false;
    }

    Serial.println("Resizing image...");
    resized_matrix = dl_matrix3du_alloc(1, EI_CLASSIFIER_INPUT_WIDTH, EI_CLASSIFIER_INPUT_HEIGHT, 3);
    if (!resized_matrix) {
        Serial.println("Allocate resized_matrix failed!");
        dl_matrix3du_free(rgb888_matrix);
        return false;
    }
    image_resize_linear(resized_matrix->item, rgb888_matrix->item, 
        EI_CLASSIFIER_INPUT_WIDTH, EI_CLASSIFIER_INPUT_HEIGHT, 3, 
        cutecat_width, cutecat_height);

    dl_matrix3du_free(rgb888_matrix);

    Serial.println("Image ready for inference!");
    return true;
}

// Convert to the input format required by the EI model

int raw_feature_get_data(size_t offset, size_t out_len, float *signal_ptr) {
    size_t pixel_ix = offset * 3;
    size_t bytes_left = out_len;
    size_t out_ptr_ix = 0;
    while (bytes_left != 0) {
        uint8_t r = resized_matrix->item[pixel_ix];
        uint8_t g = resized_matrix->item[pixel_ix + 1];
        uint8_t b = resized_matrix->item[pixel_ix + 2];
        float pixel_f = (r << 16) + (g << 8) + b;
        signal_ptr[out_ptr_ix] = pixel_f;
        out_ptr_ix++;
        pixel_ix += 3;
        bytes_left--;
    }
    return 0;
}

void setup() {
    Serial.begin(115200);
    Serial.println("=== Serial Begin ===");
    Serial.println("=== Edge Impulse JPEG image inference test ===");
    if (!psramFound()) {
    Serial.println("❌ PSRAM not detected. Please make sure it is enabled!");
    while (1);
    }


    if (!jpeg_decode_and_resize()) {
        Serial.println("Image prepare failed!");
        while (1);
    }
    //
    Serial.printf("Free internal heap (DRAM): %d bytes\n", heap_caps_get_free_size(MALLOC_CAP_INTERNAL));
    Serial.printf("Free PSRAM: %d bytes\n", heap_caps_get_free_size(MALLOC_CAP_SPIRAM));

    signal_t signal;
    signal.total_length = EI_CLASSIFIER_INPUT_WIDTH *
                        EI_CLASSIFIER_INPUT_HEIGHT *
                        EI_CLASSIFIER_INPUT_FRAMES;
    signal.get_data = &raw_feature_get_data;

    ei_impulse_result_t result = {};
    EI_IMPULSE_ERROR res = run_classifier(&signal, &result, false);

    if (res != EI_IMPULSE_OK) {
        Serial.print("❌ Inference failed!Error code: ");
        Serial.println(res);
        return;
    }

    float max_score = 0.0f;
    const char* predicted = "";
    for (size_t ix = 0; ix < EI_CLASSIFIER_LABEL_COUNT; ix++) {
        float score = result.classification[ix].value;
        const char* label = result.classification[ix].label;
        Serial.printf("  %s: %.3f\n", label, score);
        if (score > max_score) {
            max_score = score;
            predicted = label;
        }
    }
    Serial.printf("➡️ Prediction result: %s (%.2f%%)\n", predicted, max_score * 100);

#if EI_CLASSIFIER_HAS_ANOMALY == 1
    Serial.printf("Anomaly score: %.3f\n", result.anomaly);
#endif

    dl_matrix3du_free(resized_matrix);

    Serial.println("=== Inference completed ===");
}

void loop() {
    
}

螢幕擷取畫面 2025-07-22 110634
螢幕擷取畫面 2025-07-22 110614