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!
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
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