ESP32 CAM - AI/ML APPLICATION
ESP32-CAM AI/ML Application: Object Detection with Edge Impulse

ESP32-CAM AI/ML Application: Object Detection with Edge Impulse


01 Overview

In this project, we are going to use the ESP32-CAM module. The ESP32-CAM is a microcontroller that integrates Wi-Fi and Bluetooth, and uniquely features a built-in camera module (typically the OV2640) and a microSD card slot best for saving and capturing images. With this device, you can detect objects, fruits, and people, based on the data you have entered or uploaded into it.

By following the stated materials and the instructions below, we will understand the basics of edge computing and how to use Edge Impulse with the ESP32-CAM to train and deploy your own object detection model using AI to identify any object of your choice.

Project Use Case

This project is for makers and students who want a low-cost, standalone smart camera that can classify or detect objects without relying on a cloud connection. It's suited for OJT/training builds and any application that needs on-device recognition, such as identifying fruits, objects, or people.

02 Hardware and Software Components

Gather everything below before you start. This is your checklist — names, models, and versions only.

Hardware Components

Component Description
ESP32-CAM module With built-in OV2640 camera
FTDI/USB-to-TTL programmer ESP32-CAM has no onboard USB, so this is required to upload code
Jumper wires (male) For wiring connections between modules
MicroSD card Optional, for local image storage
LM2596 DC-DC Step Down Power Supply Module Regulates and steps down voltage for stable power supply
0.96" OLED Display x1 Optional, displays on-device information

Software Tools

Software Version / Details
Edge Impulse Host PC/browser platform used to train and deploy the object detection model
Arduino IDE Used to write and upload the sketches to the ESP32-CAM

03 Application Discussion

Here is what each concept means and why it matters for this project.

Smart Devices and Local Processing

"AI on Edge" simply means making small electronics smart enough to think for themselves. Instead of sending pictures over the internet to a giant computer server, the ESP32-CAM takes a picture and uses its own brain to figure out what it is seeing. This allows the system to work instantly without needing a Wi-Fi connection to the outside world.

Preparing the Pictures for the Brain

An image straight from a camera has too much data for a tiny chip to understand. To fix this, the system shrinks and cleans the picture using a few steps:

  1. The image is resized down to a tiny square (96x96 pixels) so the chip can read it quickly.
  2. When collecting data, choose the right angles so you won't have a hard time labeling pictures and won't waste storage space.
  3. During setup, you draw square boxes around the object in your photos. This teaches the program exactly what features to look for while ignoring the background behind the object.

04 Hardware Setup

Wire the components to the board using the tables below. These are the breakdown of the wiring diagram shown above.

1. ESP32-CAM → FTDI Basic (USB programmer, used to upload code)

ESP32-CAM Pin FTDI Pin Wire Color
5V VCC Red
GND GND Black
RX TX Green
TX RX Blue
Note: There's also a small grey jumper wire between GPIO0 and GND. This puts the board into "flashing/upload mode." Remove it after the upload is successful, since it's only needed during programming — not for normal operation.

2. ESP32-CAM → OLED Display (128x64 screen)

ESP32-CAM Pin OLED Pin Wire Color
GND GND Black
VCC VCC Brown/Salmon
SCL SCL Yellow
SDA SDA Green

3. ESP32-CAM → Buzzer

Buzzer Leg Connects To Wire Color
Leg 1 GND Black
Leg 2 Signal pin Brown/Salmon

Assembly Notes

The FTDI Basic is only for uploading your code (via USB to your computer). The OLED shows information on screen, and the buzzer makes sound alerts. Once your code is uploaded successfully, disconnect the FTDI board and the GPIO0-to-GND jumper wire — after that, the ESP32-CAM runs on its own with just the OLED and buzzer connected.

05 Software Setup

Follow these steps in order. Do not skip any step.

Step 1 — Configure Wi-Fi Credentials

This code is used to collect data using the ESP32-CAM module. In this part, kindly enter your Wi-Fi hotspot name in WIFI_SSID and password in WIFI_PASS. According to CircuitDigest, the ESP32 is compatible only with the 2.4 GHz network.

Note: The ESP32 only connects to 2.4 GHz Wi-Fi networks — make sure your hotspot or router is broadcasting on that band.

Step 2 — Enable Debug Messages

Before uploading, set Tools > Core Debug Level = INFO in the Arduino IDE. This turns on the debug messages used to confirm that the camera, Wi-Fi, and image collection server initialized correctly.

Step 3 — Train Your Model in Edge Impulse

Once you've collected images with the image collection sketch (Step 4 below covers uploading it), head to edgeimpulse.com and follow these steps to turn your labeled photos into a working model:

  1. Create a project. Sign up or log in, then click Create new project and give it a name.
  2. Upload and label your data. Go to Data acquisition and upload the images saved from the ESP32-CAM's collection server (via the Upload data button, or the WebUSB "Connect a device" option if wiring a live capture session). Assign a label to each image based on the object, fruit, or person it shows.
  3. Split your dataset. Edge Impulse automatically splits data into train/test sets (roughly 80/20). Check the Data acquisition tab to confirm both classes have a reasonably even number of samples — a lopsided dataset will bias the model toward whichever class has more images.
  4. Create an Impulse. Open the Impulse design tab. Set the image width/height to 96x96 (matching the resize step in the image collection sketch), add an Image processing block, and add a Transfer Learning (Images) block for classification, or an Object Detection block if you need bounding boxes.
  5. Generate features. Click into the Image processing block, choose grayscale or RGB, then click Save parameters followed by Generate features. The feature explorer shows whether your classes cluster separately — heavy overlap usually means more or cleaner data is needed.
  6. Train the model. Click into the learning block (e.g. Transfer Learning or Object Detection), leave the default neural network settings for a first pass (or adjust training cycles/learning rate), and click Start training. Review the resulting accuracy and confusion matrix.
  7. Test before trusting it. Use the Model testing tab to run the held-out test set through the trained model. Very high accuracy on a small dataset is often a sign of overfitting rather than a genuinely robust model, so aim to validate with a few images the model hasn't seen at all.
  8. Deploy and export. Go to the Deployment tab, select Arduino library as the output, and click Build. This downloads a .zip file containing your trained model as an Arduino-compatible library.
  9. Import into Arduino IDE. In the Arduino IDE, go to Sketch > Include Library > Add .ZIP Library and select the downloaded file. Then update the inferencing sketch's model header include (e.g. TRAINING0707_inferencing.h) to match the library name Edge Impulse generated for your project.
Note: If you retrain the model later with more data, re-export and re-import the library, and update the header include again — the file name changes each time you rename or re-export a project.

Step 4 — Upload the Code

  1. Open the image collection sketch in the Arduino IDE and upload it first to gather training images.
  2. Once your dataset is ready, train and export your model in Edge Impulse (see Step 3 above), then replace the model header in the inferencing sketch.
  3. Click Upload to flash the inferencing sketch to the ESP32-CAM.

06 Code

Copy each file below into the correct location as described in the Software Setup section. Read the Code Breakdown section to understand what each part does.

Image Collection Sketch

This code collects images using the ESP32-CAM module so they can be uploaded to Edge Impulse and labeled for training.

Arduino / C++
/**
 * Collect images for Edge Impulse image
 * classification / object detection
 *
 * BE SURE TO SET "TOOLS > CORE DEBUG LEVEL = INFO"
 * to turn on debug messages
 */

// if you define WIFI_SSID and WIFI_PASS before importing the library, 
// you can call connect() instead of connect(ssid, pass)
//
// If you set HOSTNAME and your router supports mDNS, you can access
// the camera at http://{HOSTNAME}.local

#define WIFI_SSID "SSID"
#define WIFI_PASS "PASSWORD"
#define HOSTNAME "esp32cam"

#include <eloquent_esp32cam.h>
#include <eloquent_esp32cam/extra/esp32/wifi/sta.h>
#include <eloquent_esp32cam/viz/image_collection.h>

using eloq::camera;
using eloq::wifi;
using eloq::viz::collectionServer;

void setup() {
    delay(3000);
    Serial.begin(115200);
    Serial.println("___IMAGE COLLECTION SERVER___");

    // camera settings
    // replace with your own model!
    camera.pinout.wroom_s3();
    camera.brownout.disable();
    // Edge Impulse models work on square images
    // face resolution is 240x240
    camera.resolution.face();
    camera.quality.high();

    // init camera
    while (!camera.begin().isOk())
        Serial.println(camera.exception.toString());

    // connect to WiFi
    while (!wifi.connect().isOk())
      Serial.println(wifi.exception.toString());

    // init face detection http server
    while (!collectionServer.begin().isOk())
        Serial.println(collectionServer.exception.toString());

    Serial.println("Camera OK");
    Serial.println("WiFi OK");
    Serial.println("Image Collection Server OK");
    Serial.println(collectionServer.address());
}

void loop() {
    // server runs in a separate thread, no need to do anything here
}

Object Detection Inferencing Sketch

This code runs real-time AI object detection directly on the camera board using your trained Edge Impulse machine learning model.

Arduino / C++
/* Edge Impulse Arduino examples
 * Copyright (c) 2022 EdgeImpulse Inc.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

// These sketches are tested with 2.0.4 ESP32 Arduino Core
// https://github.com/espressif/arduino-esp32/releases/tag/2.0.4

/* Includes ---------------------------------------------------------------- */
#include <TRAINING0707_inferencing.h>
#include "edge-impulse-sdk/dsp/image/image.hpp"

#include "esp_camera.h"

// Select camera model - find more camera models in camera_pins.h file here
// https://github.com/espressif/arduino-esp32/blob/master/libraries/ESP32/examples/Camera/CameraWebServer/camera_pins.h

#define CAMERA_MODEL_ESP_EYE // Has PSRAM
//#define CAMERA_MODEL_AI_THINKER // Has PSRAM

#if defined(CAMERA_MODEL_ESP_EYE)
#define PWDN_GPIO_NUM    -1
#define RESET_GPIO_NUM   -1
#define XCLK_GPIO_NUM    4
#define SIOD_GPIO_NUM    18
#define SIOC_GPIO_NUM    23

#define Y9_GPIO_NUM      36
#define Y8_GPIO_NUM      37
#define Y7_GPIO_NUM      38
#define Y6_GPIO_NUM      39
#define Y5_GPIO_NUM      35
#define Y4_GPIO_NUM      14
#define Y3_GPIO_NUM      13
#define Y2_GPIO_NUM      34
#define VSYNC_GPIO_NUM   5
#define HREF_GPIO_NUM    27
#define PCLK_GPIO_NUM    25

#elif defined(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

#else
#error "Camera model not selected"
#endif

/* Constant defines -------------------------------------------------------- */
#define EI_CAMERA_RAW_FRAME_BUFFER_COLS           320
#define EI_CAMERA_RAW_FRAME_BUFFER_ROWS           240
#define EI_CAMERA_FRAME_BYTE_SIZE                 3

/* Private variables ------------------------------------------------------- */
static bool debug_nn = false; // Set this to true to see e.g. features generated from the raw signal
static bool is_initialised = false;
uint8_t *snapshot_buf; //points to the output of the capture

static camera_config_t camera_config = {
    .pin_pwdn = PWDN_GPIO_NUM,
    .pin_reset = RESET_GPIO_NUM,
    .pin_xclk = XCLK_GPIO_NUM,
    .pin_sscb_sda = SIOD_GPIO_NUM,
    .pin_sscb_scl = SIOC_GPIO_NUM,

    .pin_d7 = Y9_GPIO_NUM,
    .pin_d6 = Y8_GPIO_NUM,
    .pin_d5 = Y7_GPIO_NUM,
    .pin_d4 = Y6_GPIO_NUM,
    .pin_d3 = Y5_GPIO_NUM,
    .pin_d2 = Y4_GPIO_NUM,
    .pin_d1 = Y3_GPIO_NUM,
    .pin_d0 = Y2_GPIO_NUM,
    .pin_vsync = VSYNC_GPIO_NUM,
    .pin_href = HREF_GPIO_NUM,
    .pin_pclk = PCLK_GPIO_NUM,

    //XCLK 20MHz or 10MHz for OV2640 double FPS (Experimental)
    .xclk_freq_hz = 20000000,
    .ledc_timer = LEDC_TIMER_0,
    .ledc_channel = LEDC_CHANNEL_0,

    .pixel_format = PIXFORMAT_JPEG, //YUV422,GRAYSCALE,RGB565,JPEG
    .frame_size = FRAMESIZE_QVGA,    //QQVGA-UXGA Do not use sizes above QVGA when not JPEG

    .jpeg_quality = 12, //0-63 lower number means higher quality
    .fb_count = 1,       //if more than one, i2s runs in continuous mode. Use only with JPEG
    .fb_location = CAMERA_FB_IN_PSRAM,
    .grab_mode = CAMERA_GRAB_WHEN_EMPTY,
};

/* Function definitions ------------------------------------------------------- */
bool ei_camera_init(void);
void ei_camera_deinit(void);
bool ei_camera_capture(uint32_t img_width, uint32_t img_height, uint8_t *out_buf) ;

/**
* @brief      Arduino setup function
*/
void setup()
{
    // put your setup code here, to run once:
    Serial.begin(115200);
    //comment out the below line to start inference immediately after upload
    while (!Serial);
    Serial.println("Edge Impulse Inferencing Demo");
    if (ei_camera_init() == false) {
        ei_printf("Failed to initialize Camera!\r\n");
    }
    else {
        ei_printf("Camera initialized\r\n");
    }

    ei_printf("\nStarting continious inference in 2 seconds...\n");
    ei_sleep(2000);
}

/**
* @brief      Get data and run inferencing
*
* @param[in]  debug  Get debug info if true
*/
void loop()
{

    // instead of wait_ms, we'll wait on the signal, this allows threads to cancel us...
    if (ei_sleep(5) != EI_IMPULSE_OK) {
        return;
    }

    snapshot_buf = (uint8_t*)malloc(EI_CAMERA_RAW_FRAME_BUFFER_COLS * EI_CAMERA_RAW_FRAME_BUFFER_ROWS * EI_CAMERA_FRAME_BYTE_SIZE);

    // check if allocation was successful
    if(snapshot_buf == nullptr) {
        ei_printf("ERR: Failed to allocate snapshot buffer!\n");
        return;
    }

    ei::signal_t signal;
    signal.total_length = EI_CLASSIFIER_INPUT_WIDTH * EI_CLASSIFIER_INPUT_HEIGHT;
    signal.get_data = &ei_camera_get_data;

    if (ei_camera_capture((size_t)EI_CLASSIFIER_INPUT_WIDTH, (size_t)EI_CLASSIFIER_INPUT_HEIGHT, snapshot_buf) == false) {
        ei_printf("Failed to capture image\r\n");
        free(snapshot_buf);
        return;
    }

    // Run the classifier
    ei_impulse_result_t result = { 0 };

    EI_IMPULSE_ERROR err = run_classifier(&signal, &result, debug_nn);
    if (err != EI_IMPULSE_OK) {
        ei_printf("ERR: Failed to run classifier (%d)\n", err);
        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);

#if EI_CLASSIFIER_OBJECT_DETECTION == 1
    ei_printf("Object detection bounding boxes:\r\n");
    for (uint32_t i = 0; i < result.bounding_boxes_count; i++) {
        ei_impulse_result_bounding_box_t bb = result.bounding_boxes[i];
        if (bb.value == 0) {
            continue;
        }
        ei_printf("  %s (%f) [ x: %u, y: %u, width: %u, height: %u ]\r\n",
                bb.label,
                bb.value,
                bb.x,
                bb.y,
                bb.width,
                bb.height);
    }

    // Print the prediction results (classification)
#else
    ei_printf("Predictions:\r\n");
    for (uint16_t i = 0; i < EI_CLASSIFIER_LABEL_COUNT; i++) {
        ei_printf("  %s: ", ei_classifier_inferencing_categories[i]);
        ei_printf("%.5f\r\n", result.classification[i].value);
    }
#endif

    // Print anomaly result (if it exists)
#if EI_CLASSIFIER_HAS_ANOMALY
    ei_printf("Anomaly prediction: %.3f\r\n", result.anomaly);
#endif

#if EI_CLASSIFIER_HAS_VISUAL_ANOMALY
    ei_printf("Visual anomalies:\r\n");
    for (uint32_t i = 0; i < result.visual_ad_count; i++) {
        ei_impulse_result_bounding_box_t bb = result.visual_ad_grid_cells[i];
        if (bb.value == 0) {
            continue;
        }
        ei_printf("  %s (%f) [ x: %u, y: %u, width: %u, height: %u ]\r\n",
                bb.label,
                bb.value,
                bb.x,
                bb.y,
                bb.width,
                bb.height);
    }
#endif

    free(snapshot_buf);

}

/**
 * @brief   Setup image sensor & start streaming
 *
 * @retval  false if initialisation failed
 */
bool ei_camera_init(void) {

    if (is_initialised) return true;

#if defined(CAMERA_MODEL_ESP_EYE)
  pinMode(13, INPUT_PULLUP);
  pinMode(14, INPUT_PULLUP);
#endif

    //initialize the camera
    esp_err_t err = esp_camera_init(&camera_config);
    if (err != ESP_OK) {
      Serial.printf("Camera init failed with error 0x%x\n", err);
      return false;
    }

    sensor_t * s = esp_camera_sensor_get();
    // initial sensors are flipped vertically and colors are a bit saturated
    if (s->id.PID == OV3660_PID) {
      s->set_vflip(s, 1); // flip it back
      s->set_brightness(s, 1); // up the brightness just a bit
      s->set_saturation(s, 0); // lower the saturation
    }

#if defined(CAMERA_MODEL_M5STACK_WIDE)
    s->set_vflip(s, 1);
    s->set_hmirror(s, 1);
#elif defined(CAMERA_MODEL_ESP_EYE)
    s->set_vflip(s, 1);
    s->set_hmirror(s, 1);
    s->set_awb_gain(s, 1);
#endif

    is_initialised = true;
    return true;
}

/**
 * @brief      Stop streaming of sensor data
 */
void ei_camera_deinit(void) {

    //deinitialize the camera
    esp_err_t err = esp_camera_deinit();

    if (err != ESP_OK)
    {
        ei_printf("Camera deinit failed\n");
        return;
    }

    is_initialised = false;
    return;
}

/**
 * @brief      Capture, rescale and crop image
 *
 * @param[in]  img_width     width of output image
 * @param[in]  img_height    height of output image
 * @param[in]  out_buf       pointer to store output image, NULL may be used
 *                           if ei_camera_frame_buffer is to be used for capture and resize/cropping.
 *
 * @retval     false if not initialised, image captured, rescaled or cropped failed
 *
 */
bool ei_camera_capture(uint32_t img_width, uint32_t img_height, uint8_t *out_buf) {
    bool do_resize = false;

    if (!is_initialised) {
        ei_printf("ERR: Camera is not initialized\r\n");
        return false;
    }

    camera_fb_t *fb = esp_camera_fb_get();

    if (!fb) {
        ei_printf("Camera capture failed\n");
        return false;
    }

   bool converted = fmt2rgb888(fb->buf, fb->len, PIXFORMAT_JPEG, snapshot_buf);

   esp_camera_fb_return(fb);

   if(!converted){
       ei_printf("Conversion failed\n");
       return false;
   }

    if ((img_width != EI_CAMERA_RAW_FRAME_BUFFER_COLS)
        || (img_height != EI_CAMERA_RAW_FRAME_BUFFER_ROWS)) {
        do_resize = true;
    }

    if (do_resize) {
        ei::image::processing::crop_and_interpolate_rgb888(
        out_buf,
        EI_CAMERA_RAW_FRAME_BUFFER_COLS,
        EI_CAMERA_RAW_FRAME_BUFFER_ROWS,
        out_buf,
        img_width,
        img_height);
    }

    return true;
}

static int ei_camera_get_data(size_t offset, size_t length, float *out_ptr)
{
    // we already have a RGB888 buffer, so recalculate offset into pixel index
    size_t pixel_ix = offset * 3;
    size_t pixels_left = length;
    size_t out_ptr_ix = 0;

    while (pixels_left != 0) {
        // Swap BGR to RGB here
        // due to https://github.com/espressif/esp32-camera/issues/379
        out_ptr[out_ptr_ix] = (snapshot_buf[pixel_ix + 2] << 16) + (snapshot_buf[pixel_ix + 1] << 8) + snapshot_buf[pixel_ix];

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

#if !defined(EI_CLASSIFIER_SENSOR) || EI_CLASSIFIER_SENSOR != EI_CLASSIFIER_SENSOR_CAMERA
#error "Invalid model for current sensor"
#endif

07 Code Breakdown

Here is what each part of the code does. Read this after uploading.

Libraries

Library Purpose
eloquent_esp32cam.h Simplifies camera setup, Wi-Fi connection, and HTTP server creation for image collection
eloquent_esp32cam/extra/esp32/wifi/sta.h Handles Wi-Fi station connection
eloquent_esp32cam/viz/image_collection.h Runs the browser-based image collection server used for gathering training data
TRAINING0707_inferencing.h Auto-generated Edge Impulse header containing the exported, trained ML model
edge-impulse-sdk/dsp/image/image.hpp Image processing utilities used to resize and crop captured frames to the model's input size
esp_camera.h Low-level ESP32 camera driver used to initialize and capture frames from the OV2640 sensor

Key Functions

camera.begin() / wifi.connect() / collectionServer.begin()

Used in the image collection sketch to initialize the camera, connect to Wi-Fi, and start the browser-based server used for capturing and labeling training images.

ei_camera_init()

Initializes the camera sensor for the inferencing sketch, applying flip/mirror settings depending on the selected camera model.

ei_camera_capture()

Captures a frame from the camera, converts it to RGB888 format, and resizes or crops it to match the input size expected by the trained model.

run_classifier()

Feeds the captured image signal into the Edge Impulse trained model and returns the classification or object detection results.

ei_camera_get_data()

Converts the raw captured pixel buffer into the signal format the Edge Impulse classifier expects, swapping BGR to RGB in the process.

General Program Workflow

  1. Flash the image collection sketch and use the browser-based server to capture and label training images.
  2. Upload the labeled images to Edge Impulse and train an object detection or classification model.
  3. Export the trained model as an Arduino library and add it to the inferencing sketch.
  4. Flash the inferencing sketch so the ESP32-CAM captures frames and classifies them locally, printing predictions (and bounding boxes, if using object detection) over Serial.

Video Demonstration

Note: this clip shows the hardware build and live demo. Step-by-step Edge Impulse training instructions are covered in writing under Section 05, Step 3.

08 Conclusion

This project successfully shows how to build a cheap, smart camera system using the ESP32-CAM and Edge Impulse. By shrinking image frames down to a tiny 96x96 pixel matrix, we proved that a small microcontroller can easily run complex machine learning models right on the device without needing an active connection to an expensive cloud server.

09 References

  • Circuit Digest Article: circuitdigest.com
  • Edge Impulse Guides: edgeimpulse.com
ESP32-CAM AI/ML Application – CreateLabz

#esp32-cam#ftdi/usb-to-ttl programmer#lm2596#oled display

Leave a comment

All comments are moderated before being published