In this short post I will show you how to use the EloquentArduino library to extract an RGB histogram from your ESP32-cam images for computer vision tasks.

RGB histogram from "Secure Content-Based Image Retrieval in the Cloud With Key Confidentiality"

An RGB histogram is actually composed of 3 distinct histograms, one for each color channel, that describe how many pixels in the image have a given value. So, on the x axis you have the possibile values (from 0 to 255), on the y axis you have the count of pixels that have that specific value.

Since differentiating each single value would give a quite "sparse" histogram, it is often desiderable to bin the values. Binning (or bucketing) means that instead of counting how many pixels have a given exact value, we count how many pixels fall in a certain range: in this way, pixels that have a value of 1 or 2, for example, are grouped together into the same bin.

The EloquentArduino library makes it a piece of cake to compute the RGB histogram of an ESP32-cam image. You only have to set the number of bins you want.

When choosing the number of bins, keep in mind that using a power of 2 (up to 64) *may* speed the things up, depending on FPU support
First you have to install the EloquentArduino library version 1.1.9 from the Arduino IDE Library Manager!
#define CAMERA_MODEL_M5STACK_WIDE
#define FRAME_SIZE FRAMESIZE_QVGA
#define NUM_BINS 32

#include <EloquentArduino.h>
#include <eloquentarduino/vision/camera/ESP32Camera.h>
#include <eloquentarduino/vision/processing/RGBHistogram.h>

Eloquent::Vision::Camera::ESP32Camera camera(PIXFORMAT_RGB565);
Eloquent::Vision::Processing::RGBHistogram<NUM_BINS> hist;

/**
 * Function prototype
 */
void printHistogram(uint16_t *hist, char bar = '|', uint8_t divisor = 10);

/**
 * 
 */
void setup() {
  Serial.begin(115200);
  camera.begin(FRAME_SIZE);
  delay(4000);
}

/**
 * 
 */
void loop() {
  camera_fb_t *frame = camera.capture();

  // actually compute histogram
  hist.update(frame->buf, frame->len);

  // the hist object has the attributes rHistogram, gHistrogram, bHistogram
  // that contain the calculated histograms
  printHistogram(hist.gHistogram);
  delay(4000);
}

/**
 * Print histogram on the serial monitor
 */
void printHistogram(uint16_t *hist, char bar, uint8_t divisor) {
  // for each bin
  for (uint8_t i = 0; i < NUM_BINS; i++) {
    Serial.printf("%-2d ", i);

    // print row proportional to its height
    for (uint16_t j = hist[i] / divisor; j > 0; j--) {
      Serial.print(bar);
    }

    Serial.println();
  }
}

The above code does very few things:

  1. it uses the ESP32Camera class to take a photo in RGB565 format from the camera
  2. it uses the RGBHistogram class to compute the R, G, B histograms from that photo
  3. it prints the histogram to the Serial monitor for debugging purposes

Color Histogram to Serial monitor

What you actually do with the histogram is really up to you: computer vision is a wide topic!


Check the full project code on Github and remember to star!

Help the blow grow