Simple jpeg to bin

Hi,
I am working on a project that captures a simple picture on a esp32s cam. Simple means small printed digits like on a playing card. I would like to convert it inside my program to covert each picture in to black and white and then in binary code. Eventually the program will compare it with existing bin samples (of digit 0 to 9) and return best match.
So my question is can you please hint me how to covert a small picture to bin?
Thank you for your guidance!

|1|1|1|1|0|1|1|1|
|1|1|1|0|0|1|1|1|
|1|1|0|1|0|1|1|1|
|1|1|1|1|0|1|1|1|
|1|1|1|1|0|1|1|1|
|1|1|1|1|0|1|1|1|
|1|1|1|1|0|1|1|1|
|1|1|0|0|0|0|0|1|
image

Hi,
I have a demo sketch I created which shows how you can capture an image on an esp32cam and convert it to RGB data which may be of interest/help to you for this project?

Hi Alan,
Thank you for your suggestion. There are a lot of interesting codes in your program. Learning a lot from it! Got it to work. Unfortunately I am not at the level that I understand it all.
I like to take a picture (QQVGA 160 x 120), convert it to B/W and save it in an array (160x120) with zero's and ones. A Serial.print of the array somewhat shows the object of the picture. Any suggestion? Maybe I should post this in another topic?
Thanks! Oscar

Yes. Don't waste memory by using a 160 x 120 array to hold only either 0 or 1. Use the 8 bits in a byte instead and reduce the array size by a factor of 8

Don't do that. Post here to maintain continuity

Hi Bob,
Thank you for the hint. I am still struggling to get a picture in to bin format. Any thoughts?
Thanks!

I know next to nothing about the format of a jpeg

Can you provide a link to a specification of its layout and contents ?

Rather than capturing a JPG you could use "PIXFORMAT_GRAYSCALE" and then
it will already be in the format of one byte per pixel

You can see an example of this in "capture_still()" in my security camera sketch
here: CameraWifiMotion/motion.h at master · alanesq/CameraWifiMotion · GitHub

1 Like

Hi Alan,
Just realize that it is you! If have read your articles with great intrest! Actually I am using your code (see below). I manage to get 0 and 1 in the array. I can print the output in a raster W x H. The content is indeed changing by different light conditions. The issue now is that each line is the same. Looks like only one line is scanned. see example. Any thoughts? Thank you very much! Oscar


#define CAMERA_MODEL_AI_THINKER // Has PSRAM

#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

//#define PWDN_GPIO_NUM     -1
//#define RESET_GPIO_NUM    15
//#define XCLK_GPIO_NUM     27
//#define SIOD_GPIO_NUM     22
//#define SIOC_GPIO_NUM     23
//#define Y9_GPIO_NUM       19
//#define Y8_GPIO_NUM       36
//#define Y7_GPIO_NUM       18
//#define Y6_GPIO_NUM       39
//#define Y5_GPIO_NUM        5
//#define Y4_GPIO_NUM       34
//#define Y3_GPIO_NUM       35
//#define Y2_GPIO_NUM       32
//#define VSYNC_GPIO_NUM    25
//#define HREF_GPIO_NUM     26
//#define PCLK_GPIO_NUM     21

#define FRAME_SIZE FRAMESIZE_QQVGA
#define WIDTH 160
#define HEIGHT 120
#define BLOCK_SIZE 5  // was 5
#define W (WIDTH / BLOCK_SIZE)
#define H (HEIGHT / BLOCK_SIZE)
#define THRESHOLD 90   //127

double features[H * W] = { 0 };

void setup() {
  Serial.begin(115200);
  Serial.println(setup_camera(FRAME_SIZE) ? "OK" : "ERR INIT");
  delay(3000);
}

void loop() {
  if (!capture_still()) {
    Serial.println("Failed capture");
    delay(2000);
    return;
  }

  print_features();
  delay(3000);
}

bool setup_camera(framesize_t frameSize) {
  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_GRAYSCALE;
  config.frame_size = frameSize;
  config.jpeg_quality = 12;
  config.fb_count = 1;

  bool ok = esp_camera_init(&config) == ESP_OK;

  sensor_t *sensor = esp_camera_sensor_get();
  sensor->set_framesize(sensor, frameSize);

  return ok;
}

bool capture_still() {
  camera_fb_t *frame = esp_camera_fb_get();

  if (!frame)
    return false;

  // reset all the features
  for (size_t i = 0; i < H * W; i++)
    features[i] = 0;

  // for each pixel, compute the position in the downsampled image
  for (size_t i = 0; i < frame->len; i++) {
    const uint16_t x = i % WIDTH;
    const uint16_t y = floor(i / WIDTH);
    const uint8_t block_x = floor(x / BLOCK_SIZE);
    const uint8_t block_y = floor(y / BLOCK_SIZE);
    const uint16_t j = block_y * W + block_x;

    features[j] += frame->buf[i];
  }

  // apply threshold
  for (size_t i = 0; i < H * W; i++) {
    features[i] = (features[i] / (BLOCK_SIZE * BLOCK_SIZE) > THRESHOLD) ? 1 : 0;
  }

  return true;
}

void print_features() {
  for (size_t i = 0; i < H; i++) {
    for (size_t j = 0; j < W; j++) {
      if (features[j] == 0) {
        Serial.print("O");
      }
      else {
        Serial.print (" ");
      }
      if (i != H * W - 1)
        Serial.print(',');
    }
    Serial.println();
  }
  Serial.println();


  //void print_features() {
  //    for (size_t i = 0; i < H * W; i++) {
  //        Serial.print(features[i]);
  //
  //        if (i != H * W - 1)
  //          Serial.print(',');
  //    }
  //
  //    Serial.println();
}

Blockquote

type or paste code here

image

Hi,

I have just been having a play with this myself as it has been a while since I did anything like this

I have put a demo sketch here for you to have a play with