ESP32 CAM Support

Hello @Bewegendbeeld,

Could you try to replace the ei_buf by the out_buf in the raw_feature_get_data function to see if it works? I do not have a ESP32 CAM with me at the moment so I cannot test.

int raw_feature_get_data(size_t offset, size_t length, float *signal_ptr)
{
    memcpy(signal_ptr, ei_buf + offset, length * sizeof(float));
    return 0;
}

And if you want the output image, you’ll also need to change ei_buf by out_buf here:

s = fmt2jpg_cb(ei_buf, ei_len, EI_CLASSIFIER_INPUT_WIDTH, EI_CLASSIFIER_INPUT_HEIGHT, PIXFORMAT_RGB888, 90, jpg_encode_stream, &jchunk);

From what I see in the logs, it seems that the request’s response is displayed more than once. I’ll have a deeper look at the code when I have access to an ESP32 CAM.

Regards,

Louis

Actually you could only replace

ei_buf = ei_matrix->item;

by

ei_buf = image_matrix->item;

here-> https://github.com/edgeimpulse/example-esp32-cam/blob/main/Advanced-Image-Classification/app_httpd.cpp#L300

It is a bit messy, I’ll clean the code to only display functions used by Edge Impulse instead of keeping the code from the base project like described in the the resources.

This would only work when you set the FRAMESIZE_96X96

1 Like

Hi @louis, thanks for all your suggestions.
I tried everything from your answers, but still get the same result every time.


I hoped to find a very basic Arduino-based workflow to bring ML to our STEM-classes but maybe at this moment, the ESP-32 cam is not the way to go for us…

But, on the EI-blog, I just read the TinyML-kit is supported now.
I think I’ll try to build a new model and see if this combination works better for us.
Regards,
Patrick

1 Like

hey guys,
I´ve been tinkering with the EI Platform for quite a while now and i have to say: great great product - no better way to learn and experiment!
However, I´ve been trying to build a small network that distinguishes between only two states based on a camera image to determine if a parking spot is occupied or unoccupied… so far so good. I recently discovered WAY better training results after I switched from transfer learning to classification, but I can’t get the thing to work on the ESP32CAM board(not enough memory “failed to allocate TFLite area…”). And now I´m having a hard time to find an answer to my questions:

  • Is it even possible in general to get the classification-version to work on the ESP32Cam? After training, I get no information about predicted Flash or RAM Usage(says only “retrain to eval” but that doesn’t change anything)
  • Is there a way to bring down the size of the Library? How would I do that?
  • Is it maybe already a stupid idea in general to rely on classification instead of transition?

Any help or comments are appreciated - thank you :pray:

Hello @vitruvo,

Could you share your project ID or your project name please so I can have a deeper look? I see that you have several on your account :slight_smile:

Regards,

Louis

Hey @louis,
thanks for looking into this!
This was actually about the “vitruvo-project-1” project. I created two others in the meantime where the performance prediction is displayed again…

1 Like

Hi @louis Louis, Thank you for the documentation for the esp32. I tried your code shared in the edge impulise official repository. But iam recieving the error given below. Can you help me, i dont know why iam recieving this error!

{"success": false,"timing": {"timing_dsp":0,"timing_classification":0,"timing_anomaly":0}}

Hi @suhailjr,

it could be that your model is too large for the target. The code was tested with 48x48 images and use the MobileNetV2 0.05.

Could you enable the debug flag in the run_classifier function? (change false to true)

EI_IMPULSE_ERROR res = run_classifier(&signal, &result, true /* debug */);

And then open a serial terminal to check if any error is being printed out.

@aurel thanks let me try it

I confirmed its using 48x48. This is the error iam getting in serial monitor!

Converting to RGB888...
Done in 162ms
Resizing the frame buffer...
Done in 20ms
Getting signal...
Run classifier...
ERR: failed to allocate tensor arena
Failed to allocate TFLite arena (error code 1)
run_classifier returned: -6
JPG: 1872B 241ms
{"success": false,"timing": {"timing_dsp":0,"timing_classification":0,"timing_anomaly":0}}
{"success": false,"timing": {"timing_dsp":0,"timing_classification":0,"timing_anomaly":0}}

This is a memory issue, could you try retraining your model with a 96x96 image and chosing a MobileNetV1 (they have a smaller footprint).

Regards,

Louis

@louis @aurel I tried both but iam getting the same error

I can see on your account that you have two projects.
One name test and another one call test2.

Your test2 model is too big (96x96 images with MobileNetv2 0.05) but your test project should be fine I think. Can you make sure you are using the right project?

Also can you make sure you selected the quantized version (int8) of the model on the deployment tab please?

Regards,

Louis

I am trying to detect a currency with Esp32-Cam. For this i follow the tutorial of EDGE IMPLUSE YouTube video which show how to detect something with Esp32-Cam.
First of take some picture and trained the as follows.
And get ACCURACY 100.0%
I can also classify all data in your website but not in my Esp-32 cam,
Then download the library and include it in my Arduino IDE. After that i use example code of your github by changing this

// Modify the following line according to your project name
// Do not forget to import the library using "Sketch">"Include Library">"Add .ZIP Library..."
#include <esp32Cam10taaka_inferencing.h>

I have this error in serial monitor

And in Edge Impulse on ESP32 Cam browser:

{
	"success": false,
	"timing": {
		"timing_dsp": 0,
		"timing_classification": 0,
		"timing_anomaly": 0
	}
}

What’s going wrong?

@muhit313 See the line that starts with ERR: - you’re running out of memory here. As @louis mentioned above try:

This is a memory issue, could you try retraining your model with a 96x96 image and chosing a MobileNetV1 (they have a smaller footprint).

2 Likes

I follow this again… But no luck !

Same result as before.

Is it caused for clone Esp32-Cam?
My device is not original Ai-thinker. May be its Chinese clone (Not Sure).

Hello @muhit313

So I took some time today to have a deeper look at the ESP recurring issues.

I adapted one arduino sketch from this link to include Edge Impulse inference: https://randomnerdtutorials.com/esp32-cam-take-photo-save-microsd-card/

Note that you can view the orginal file if you insert a fat32 formated SD Card in the ESP32 Cam.

Here is the code (I tried with your project model to make sure it worked):

You’ll need to modify the PIN definition for your esp camera model but I’m sure you’ll be able to find out :wink:

#include "esp_camera.h"
#include "esp_timer.h"
#include "Arduino.h"
#include "img_converters.h"
#include "image_util.h"
#include "FS.h"                // SD Card ESP32
#include "SD_MMC.h"            // SD Card ESP32
#include "soc/soc.h"           // Disable brownour problems
#include "soc/rtc_cntl_reg.h"  // Disable brownour problems
#include "driver/rtc_io.h"
#include <EEPROM.h>            // read and write from flash memory

// Modify the following line according to your project name
// Do not forget to import the library using "Sketch">"Include Library">"Add .ZIP Library..."
#include <esp32Cam10taaka_inferencing.h>

// define the number of bytes you want to access
#define EEPROM_SIZE 1

// Pin definition for CAMERA_MODEL_AI_THINKER
#define PWDN_GPIO_NUM     32
#define RESET_GPIO_NUM    -1
#define XCLK_GPIO_NUM      0
#define SIOD_GPIO_NUM     26
#define SIOC_GPIO_NUM     27

#define Y9_GPIO_NUM       35
#define Y8_GPIO_NUM       34
#define Y7_GPIO_NUM       39
#define Y6_GPIO_NUM       36
#define Y5_GPIO_NUM       21
#define Y4_GPIO_NUM       19
#define Y3_GPIO_NUM       18
#define Y2_GPIO_NUM        5
#define VSYNC_GPIO_NUM    25
#define HREF_GPIO_NUM     23
#define PCLK_GPIO_NUM     22

int pictureNumber = 0;

uint8_t *ei_buf;
ei_impulse_result_t result = {0};
bool sd_card = true;

void setup() {
  WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0); //disable brownout detector

  Serial.begin(115200);
  //Serial.setDebugOutput(true);
  //Serial.println();

  camera_config_t config;
  config.ledc_channel = LEDC_CHANNEL_0;
  config.ledc_timer = LEDC_TIMER_0;
  config.pin_d0 = Y2_GPIO_NUM;
  config.pin_d1 = Y3_GPIO_NUM;
  config.pin_d2 = Y4_GPIO_NUM;
  config.pin_d3 = Y5_GPIO_NUM;
  config.pin_d4 = Y6_GPIO_NUM;
  config.pin_d5 = Y7_GPIO_NUM;
  config.pin_d6 = Y8_GPIO_NUM;
  config.pin_d7 = Y9_GPIO_NUM;
  config.pin_xclk = XCLK_GPIO_NUM;
  config.pin_pclk = PCLK_GPIO_NUM;
  config.pin_vsync = VSYNC_GPIO_NUM;
  config.pin_href = HREF_GPIO_NUM;
  config.pin_sscb_sda = SIOD_GPIO_NUM;
  config.pin_sscb_scl = SIOC_GPIO_NUM;
  config.pin_pwdn = PWDN_GPIO_NUM;
  config.pin_reset = RESET_GPIO_NUM;
  config.xclk_freq_hz = 20000000;
  config.pixel_format = PIXFORMAT_JPEG;

  if (psramFound()) {
    config.frame_size = FRAMESIZE_QVGA; // FRAMESIZE_ + QVGA|CIF|VGA|SVGA|XGA|SXGA|UXGA
    config.jpeg_quality = 10;
    config.fb_count = 2;
  } else {
    config.frame_size = FRAMESIZE_QVGA;
    config.jpeg_quality = 12;
    config.fb_count = 1;
  }

  // Init Camera
  esp_err_t err = esp_camera_init(&config);
  if (err != ESP_OK) {
    Serial.printf("Camera init failed with error 0x%x", err);
    return;
  }

  //Serial.println("Starting SD Card");
  if (!SD_MMC.begin()) {
    Serial.println("SD Card Mount Failed");
    sd_card = false;
  }

  uint8_t cardType = SD_MMC.cardType();
  if (cardType == CARD_NONE) {
    Serial.println("No SD Card attached");
    sd_card = false;
  }

}

void take_picture()
{

  camera_fb_t * fb = NULL;
  uint8_t *rgb888_buf = NULL;
  size_t out_len;

  bool s;

  // Take Picture ----------------------------------

  int64_t time_start = esp_timer_get_time();
  fb = esp_camera_fb_get();
  if (!fb) {
    Serial.println("Camera capture failed");
    return;
  }
  int64_t time_end = esp_timer_get_time();
  Serial.printf("JPG: %uB %ums\n", (uint32_t)(fb->len), (uint32_t)((time_end - time_start) / 1000));



  //Save Orginal Picture ------------------
  if (sd_card) {
    // initialize EEPROM with predefined size
    EEPROM.begin(EEPROM_SIZE);
    pictureNumber = EEPROM.read(0) + 1;

    // Path where new picture will be saved in SD Card
    String path = "/original" + String(pictureNumber) + ".jpg";

    fs::FS &fs = SD_MMC;
    Serial.printf("Picture file name: %s\n", path.c_str());

    File file = fs.open(path.c_str(), FILE_WRITE);
    if (!file) {
      Serial.println("Failed to open file in writing mode");
    }
    else {
      file.write(fb->buf, fb->len); // payload (image), payload length
      Serial.printf("Saved file to path: %s\n", path.c_str());
      EEPROM.write(0, pictureNumber);
      EEPROM.commit();
    }
    file.close();
  }

  // Process the image before inferencing --------------------

  // Allocate ei_matrix buffer
  dl_matrix3du_t *rgb888_matrix = dl_matrix3du_alloc(1, fb->width, fb->height, 3);

  //Resize Image
  rgb888_buf = rgb888_matrix->item;
  out_len = EI_CLASSIFIER_INPUT_WIDTH * EI_CLASSIFIER_INPUT_HEIGHT * 3;

  // Convert frame to RGB888
  Serial.println("Converting to RGB888...");
  time_start = esp_timer_get_time();
  s = fmt2rgb888(fb->buf, fb->len, fb->format, rgb888_buf);
  if (!s)
  {
    dl_matrix3du_free(rgb888_matrix);
    Serial.println("to rgb888 failed");
    return;
  }
  time_end = esp_timer_get_time();
  Serial.printf("Done in %ums\n", (uint32_t)((time_end - time_start) / 1000));

  Serial.println("Resizing the frame buffer...");
  dl_matrix3du_t *resized_matrix = dl_matrix3du_alloc(1, EI_CLASSIFIER_INPUT_WIDTH, EI_CLASSIFIER_INPUT_HEIGHT, 3);

  ei_buf = resized_matrix->item;

  time_start = esp_timer_get_time();
  image_resize_linear(ei_buf, rgb888_buf, EI_CLASSIFIER_INPUT_WIDTH, EI_CLASSIFIER_INPUT_HEIGHT, 3, fb->width, fb->height);
  time_end = esp_timer_get_time();
  Serial.printf("Done in %ums\n", (uint32_t)((time_end - time_start) / 1000));

  dl_matrix3du_free(rgb888_matrix);
  dl_matrix3du_free(resized_matrix);
  esp_camera_fb_return(fb);

  // Run inference ---------------------
  classify();

  // Turns off the ESP32-CAM white on-board LED (flash) connected to GPIO 4
  pinMode(4, OUTPUT);
  digitalWrite(4, LOW);
  rtc_gpio_hold_en(GPIO_NUM_4);

  delay(2000);
  Serial.println("Going to sleep now");
  delay(2000);
  esp_deep_sleep_start();
  Serial.println("This will never be printed");
}

int raw_feature_get_data(size_t offset, size_t length, float *signal_ptr)
{
  memcpy(signal_ptr, ei_buf + offset, length * sizeof(float));
  return 0;
}

void classify()
{
  Serial.println("Getting signal...");
  // Set up pointer to look after data, crop it and convert it to RGB888
  signal_t signal;
  signal.total_length = EI_CLASSIFIER_INPUT_WIDTH * EI_CLASSIFIER_INPUT_WIDTH;
  signal.get_data = &raw_feature_get_data;

  Serial.println("Run classifier...");
  // Feed signal to the classifier
  EI_IMPULSE_ERROR res = run_classifier(&signal, &result, false /* debug */);

  // Returned error variable "res" while data object.array in "result"
  ei_printf("run_classifier returned: %d\n", res);
  if (res != 0)
    return;

  // print the predictions
  ei_printf("Predictions (DSP: %d ms., Classification: %d ms., Anomaly: %d ms.): \n",
            result.timing.dsp, result.timing.classification, result.timing.anomaly);
  for (size_t ix = 0; ix < EI_CLASSIFIER_LABEL_COUNT; ix++) {
    ei_printf("    %s: \t%f\r\n", result.classification[ix].label, result.classification[ix].value);
  }
#if EI_CLASSIFIER_HAS_ANOMALY == 1
  ei_printf("    anomaly score: %f\r\n", result.anomaly);
#endif
}

void loop() {
  take_picture();
}

And as a return in the serial console you should see something like this:

Picture file name: /original1.jpg
Saved file to path: /original1.jpg
Converting to RGB888...
Done in 100ms
Resizing the frame buffer...
Done in 55ms
Getting signal...
Run classifier...
run_classifier returned: 0
Predictions (DSP: 4 ms., Classification: 583 ms., Anomaly: 0 ms.): 
    10taka: 	0.367188
    unknown: 	0.632812
Going to sleep now

If this works for you I’ll update the Github repository to replace the basic example with this one.
Loading a web interface over wifi might be too greedy on ressources for some use cases.

Regards,

Louis

1 Like

First of all i wants to thank you @louis and your friend/team member @janjongboom .

Because you and your team have a good mentality to help other people like me who are not so much professional.

Also thanks for having a deeper look at the ESP recurring issues. :heart:

Yes, it is work. Means after upload the code i am able take picture and save it into SD. And give some result.

But the Predictions result is fixed for all picture.

10taka: 0.367188 unknown: 0.632812

But it should give me different Predictions value for deferent picture.
Am I right ?
If yes what is the problem now?

Note: As I am a beginner not a professional it may take to much time to find out the problem. But I try to my best.

If you have any idea please share with me.

So there was an issue with the raw_feature_get_data function. I also cleaned the code so it is easier to read and to understand even for non-professional :wink: And most important, I removed duplicated buffers and free the memory when needed to give as much space as possible for the edge-impulse models.

Here is the full code:

#include "esp_camera.h"
#include "esp_timer.h"
#include "Arduino.h"
#include "img_converters.h"
#include "image_util.h"
#include "FS.h"                // SD Card ESP32
#include "SD_MMC.h"            // SD Card ESP32
#include "soc/soc.h"           // Disable brownour problems
#include "soc/rtc_cntl_reg.h"  // Disable brownour problems
#include "driver/rtc_io.h"
#include <EEPROM.h>            // read and write from flash memory

/* Modify the following line according to your project name
   Do not forget to import the library using "Sketch">"Include Library">"Add .ZIP Library..."
*/
#include <Car_Detection_inferencing.h>

// define the number of bytes you want to access
#define EEPROM_SIZE 1

// Pin definition for CAMERA_MODEL_AI_THINKER
#define PWDN_GPIO_NUM     32
#define RESET_GPIO_NUM    -1
#define XCLK_GPIO_NUM      0
#define SIOD_GPIO_NUM     26
#define SIOC_GPIO_NUM     27

#define Y9_GPIO_NUM       35
#define Y8_GPIO_NUM       34
#define Y7_GPIO_NUM       39
#define Y6_GPIO_NUM       36
#define Y5_GPIO_NUM       21
#define Y4_GPIO_NUM       19
#define Y3_GPIO_NUM       18
#define Y2_GPIO_NUM        5
#define VSYNC_GPIO_NUM    25
#define HREF_GPIO_NUM     23
#define PCLK_GPIO_NUM     22

int pictureNumber = 0;

dl_matrix3du_t *resized_matrix = NULL;
//size_t ei_len = 0;
size_t out_len = EI_CLASSIFIER_INPUT_WIDTH * EI_CLASSIFIER_INPUT_HEIGHT;
ei_impulse_result_t result = {0};
bool sd_card = true;

void setup() {
  WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0); //disable brownout detector

  Serial.begin(115200);

  camera_config_t config;
  config.ledc_channel = LEDC_CHANNEL_0;
  config.ledc_timer = LEDC_TIMER_0;
  config.pin_d0 = Y2_GPIO_NUM;
  config.pin_d1 = Y3_GPIO_NUM;
  config.pin_d2 = Y4_GPIO_NUM;
  config.pin_d3 = Y5_GPIO_NUM;
  config.pin_d4 = Y6_GPIO_NUM;
  config.pin_d5 = Y7_GPIO_NUM;
  config.pin_d6 = Y8_GPIO_NUM;
  config.pin_d7 = Y9_GPIO_NUM;
  config.pin_xclk = XCLK_GPIO_NUM;
  config.pin_pclk = PCLK_GPIO_NUM;
  config.pin_vsync = VSYNC_GPIO_NUM;
  config.pin_href = HREF_GPIO_NUM;
  config.pin_sscb_sda = SIOD_GPIO_NUM;
  config.pin_sscb_scl = SIOC_GPIO_NUM;
  config.pin_pwdn = PWDN_GPIO_NUM;
  config.pin_reset = RESET_GPIO_NUM;
  config.xclk_freq_hz = 20000000;
  config.pixel_format = PIXFORMAT_JPEG;

  if (psramFound()) {
    config.frame_size = FRAMESIZE_QVGA; // FRAMESIZE_ + QVGA|CIF|VGA|SVGA|XGA|SXGA|UXGA
    config.jpeg_quality = 10;
    config.fb_count = 2;
  } else {
    config.frame_size = FRAMESIZE_QVGA;
    config.jpeg_quality = 12;
    config.fb_count = 1;
  }

  // Init Camera
  esp_err_t err = esp_camera_init(&config);
  if (err != ESP_OK) {
    Serial.printf("Camera init failed with error 0x%x", err);
    return;
  }

  //Serial.println("Starting SD Card");
  if (!SD_MMC.begin()) {
    Serial.println("SD Card Mount Failed");
    sd_card = false;
  }

  uint8_t cardType = SD_MMC.cardType();
  if (cardType == CARD_NONE) {
    Serial.println("No SD Card attached");
    sd_card = false;
  }

}

void take_picture()
{
  camera_fb_t * fb = NULL;
  bool s;

  // --- Taking picture ---

  int64_t time_start = esp_timer_get_time();
  fb = esp_camera_fb_get();
  if (!fb) {
    Serial.println("Camera capture failed");
    return;
  }
  int64_t time_end = esp_timer_get_time();
  Serial.printf("JPG: %uB %ums\n", (uint32_t)(fb->len), (uint32_t)((time_end - time_start) / 1000));

  // --- Save Orginal Picture ---

  if (sd_card) {
    // initialize EEPROM with predefined size
    EEPROM.begin(EEPROM_SIZE);
    pictureNumber = EEPROM.read(0) + 1;

    // Path where new picture will be saved in SD Card
    String path = "/" + String(pictureNumber) + "_original" + ".jpg";

    fs::FS &fs = SD_MMC;
    Serial.printf("Picture file name: %s\n", path.c_str());

    File file = fs.open(path.c_str(), FILE_WRITE);
    if (!file) {
      Serial.println("Failed to open file in writing mode");
    }
    else {
      file.write(fb->buf, fb->len); // payload (image), payload length
      Serial.printf("Saved file to path: %s\n", path.c_str());
      EEPROM.write(0, pictureNumber);
      EEPROM.commit();
    }
    file.close();
  }

  // --- Convert frame to RGB888  ---

  Serial.println("Converting to RGB888...");
  time_start = esp_timer_get_time();
  // Allocate rgb888_matrix buffer
  dl_matrix3du_t *rgb888_matrix = dl_matrix3du_alloc(1, fb->width, fb->height, 3);
  s = fmt2rgb888(fb->buf, fb->len, fb->format, rgb888_matrix->item);
  time_end = esp_timer_get_time();
  Serial.printf("Done in %ums\n", (uint32_t)((time_end - time_start) / 1000));

  // --- Resize the RGB888 frame to 96x96 in this example ---

  Serial.println("Resizing the frame buffer...");
  time_start = esp_timer_get_time();
  resized_matrix = dl_matrix3du_alloc(1, EI_CLASSIFIER_INPUT_WIDTH, EI_CLASSIFIER_INPUT_HEIGHT, 3);
  image_resize_linear(resized_matrix->item, rgb888_matrix->item, EI_CLASSIFIER_INPUT_WIDTH, EI_CLASSIFIER_INPUT_HEIGHT, 3, fb->width, fb->height);
  time_end = esp_timer_get_time();
  Serial.printf("Done in %ums\n", (uint32_t)((time_end - time_start) / 1000));

  // --- Free memory ---

  dl_matrix3du_free(rgb888_matrix);
  esp_camera_fb_return(fb);

  // --- Call classifier function ---

  classify();

  // --- Convert back the resized RGB888 frame to JPG to save on SD card ---

  Serial.println("Converting ei_buf to JPG...");
  time_start = esp_timer_get_time();
  // Allocate out_matrix buffer
  dl_matrix3du_t *jpg_out_matrix = dl_matrix3du_alloc(1, fb->width, fb->height, 3);
  s = fmt2jpg(resized_matrix->item, out_len, EI_CLASSIFIER_INPUT_WIDTH, EI_CLASSIFIER_INPUT_HEIGHT, PIXFORMAT_RGB888, 10, &jpg_out_matrix->item, &out_len);
  time_end = esp_timer_get_time();
  Serial.printf("Done in %ums\n", (uint32_t)((time_end - time_start) / 1000));

  // --- Free memory ---
  dl_matrix3du_free(resized_matrix);


  //--- Save resized Picture ---
  if (sd_card) {
    // Path where new picture will be saved in SD Card
    String path = "/" + String(pictureNumber) + "_resized" + ".jpg";

    fs::FS &fs = SD_MMC;
    Serial.printf("Picture file name: %s\n", path.c_str());

    File file = fs.open(path.c_str(), FILE_WRITE);
    if (!file) {
      Serial.println("Failed to open file in writing mode");
    }
    else {
      file.write(jpg_out_matrix->item, out_len); // payload (image), payload length
      Serial.printf("Saved file to path: %s\n", path.c_str());
    }
    file.close();
  }


  // --- Turns off the ESP32-CAM white on-board LED (flash) connected to GPIO 4 ---
  pinMode(4, OUTPUT);
  digitalWrite(4, LOW);
  rtc_gpio_hold_en(GPIO_NUM_4);
  delay(2000);


  // --- Deep sleep ---
  Serial.println("Going to sleep now");
  delay(2000);
  esp_deep_sleep_start();
  Serial.println("This will never be printed");
}

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;

  // read byte for byte
  while (bytes_left != 0) {
    // grab the values and convert to r/g/b
    uint8_t r, g, b;
    r = resized_matrix->item[pixel_ix];
    g = resized_matrix->item[pixel_ix + 1];
    b = resized_matrix->item[pixel_ix + 2];

    // then convert to out_ptr format
    float pixel_f = (r << 16) + (g << 8) + b;
    signal_ptr[out_ptr_ix] = pixel_f;

    // and go to the next pixel
    out_ptr_ix++;
    pixel_ix += 3;
    bytes_left--;
  }
  return 0;
}


void classify()
{
  Serial.println("Getting signal...");
  signal_t signal;
  signal.total_length = EI_CLASSIFIER_INPUT_WIDTH * EI_CLASSIFIER_INPUT_WIDTH;
  signal.get_data = &raw_feature_get_data;

  Serial.println("Run classifier...");
  // Feed signal to the classifier
  EI_IMPULSE_ERROR res = run_classifier(&signal, &result, false /* debug */);

  // Returned error variable "res" while data object.array in "result"
  ei_printf("run_classifier returned: %d\n", res);
  if (res != 0)
    return;

  // print the predictions
  ei_printf("Predictions (DSP: %d ms., Classification: %d ms., Anomaly: %d ms.): \n",
            result.timing.dsp, result.timing.classification, result.timing.anomaly);
  for (size_t ix = 0; ix < EI_CLASSIFIER_LABEL_COUNT; ix++) {
    ei_printf("    %s: \t%f\r\n", result.classification[ix].label, result.classification[ix].value);
  }
#if EI_CLASSIFIER_HAS_ANOMALY == 1
  ei_printf("    anomaly score: %f\r\n", result.anomaly);
#endif
}

void loop() {
  take_picture();
}

Let me know if it works.

Note that I tried on this project and it worked well: https://studio.edgeimpulse.com/public/28056/latest

Regards,

Louis

1 Like

Many thanks for your help. This one and also the previous one is working now. But I think I need to add huge data for more accuracy.

1 Like