Porównaj commity

...

3 Commity

Autor SHA1 Wiadomość Data
Alan 98a335f04f
Update README.md 2023-10-15 21:59:51 +01:00
Alan f482085299
Update README.md 2023-10-15 21:32:59 +01:00
Alan ee2fe600e9
Update ESP32cam-demo.ino 2023-10-15 21:08:24 +01:00
2 zmienionych plików z 77 dodań i 16 usunięć

Wyświetl plik

@ -59,7 +59,7 @@
#include <Arduino.h> #include <Arduino.h>
// forward declarations // forward declarations
bool initialiseCamera(int); bool initialiseCamera(bool);
bool cameraImageSettings(); bool cameraImageSettings();
void changeResolution(framesize_t); void changeResolution(framesize_t);
String localTime(); String localTime();
@ -80,6 +80,7 @@
void setupFlashPWM(); void setupFlashPWM();
void handleData(); void handleData();
void readGreyscaleImage(); void readGreyscaleImage();
void resize_esp32cam_image_buffer(uint8_t*, int, int, uint8_t*, int, int);
// --------------------------------------------------------------- // ---------------------------------------------------------------
@ -407,8 +408,9 @@ void loop() {
// reset - if set to 1 all settings are reconfigured // reset - if set to 1 all settings are reconfigured
// if set to zero you can change the settings and call this procedure to apply them // if set to zero you can change the settings and call this procedure to apply them
bool initialiseCamera(int reset) { bool initialiseCamera(bool reset) {
// set the camera parameters in 'config'
if (reset) { if (reset) {
config.ledc_channel = LEDC_CHANNEL_0; config.ledc_channel = LEDC_CHANNEL_0;
config.ledc_timer = LEDC_TIMER_0; config.ledc_timer = LEDC_TIMER_0;
@ -435,6 +437,7 @@ if (reset) {
// 1600x1200 (UXGA) // 1600x1200 (UXGA)
config.jpeg_quality = 12; // 0-63 lower number means higher quality (can cause failed image capture if set too low at higher resolutions) config.jpeg_quality = 12; // 0-63 lower number means higher quality (can cause failed image capture if set too low at higher resolutions)
config.fb_count = 1; // if more than one, i2s runs in continuous mode. Use only with JPEG config.fb_count = 1; // if more than one, i2s runs in continuous mode. Use only with JPEG
}
// check the esp32cam board has a psram chip installed (extra memory used for storing captured images) // check the esp32cam board has a psram chip installed (extra memory used for storing captured images)
// Note: if not using "AI thinker esp32 cam" in the Arduino IDE, SPIFFS must be enabled // Note: if not using "AI thinker esp32 cam" in the Arduino IDE, SPIFFS must be enabled
@ -442,7 +445,6 @@ if (reset) {
if (serialDebug) Serial.println("Warning: No PSRam found so defaulting to image size 'CIF'"); if (serialDebug) Serial.println("Warning: No PSRam found so defaulting to image size 'CIF'");
config.frame_size = FRAMESIZE_CIF; config.frame_size = FRAMESIZE_CIF;
} }
}
//#if defined(CAMERA_MODEL_ESP_EYE) //#if defined(CAMERA_MODEL_ESP_EYE)
// pinMode(13, INPUT_PULLUP); // pinMode(13, INPUT_PULLUP);
@ -454,7 +456,7 @@ if (reset) {
if (serialDebug) Serial.printf("ERROR: Camera init failed with error 0x%x", camerr); if (serialDebug) Serial.printf("ERROR: Camera init failed with error 0x%x", camerr);
} }
cameraImageSettings(); // apply custom camera image settings cameraImageSettings(); // apply the camera image settings
return (camerr == ESP_OK); // return boolean result of camera initialisation return (camerr == ESP_OK); // return boolean result of camera initialisation
} }
@ -506,15 +508,15 @@ bool cameraImageSettings() {
// // more info on settings here: https://randomnerdtutorials.com/esp32-cam-ov2640-camera-settings/ // // more info on settings here: https://randomnerdtutorials.com/esp32-cam-ov2640-camera-settings/
// s->set_gain_ctrl(s, 0); // auto gain off (1 or 0) // s->set_gain_ctrl(s, 0); // auto gain off (1 or 0)
// s->set_exposure_ctrl(s, 0); // auto exposure off (1 or 0) // s->set_exposure_ctrl(s, 0); // auto exposure off (1 or 0)
// s->set_agc_gain(s, cameraImageGain); // set gain manually (0 - 30) // s->set_agc_gain(s, 1); // set gain manually (0 - 30)
// s->set_aec_value(s, cameraImageExposure); // set exposure manually (0-1200) // s->set_aec_value(s, 1); // set exposure manually (0-1200)
// s->set_vflip(s, cameraImageInvert); // Invert image (0 or 1) // s->set_vflip(s, 1); // Invert image (0 or 1)
// s->set_quality(s, 10); // (0 - 63) // s->set_quality(s, 10); // (0 - 63)
// s->set_gainceiling(s, GAINCEILING_32X); // Image gain (GAINCEILING_x2, x4, x8, x16, x32, x64 or x128) // s->set_gainceiling(s, GAINCEILING_32X); // Image gain (GAINCEILING_x2, x4, x8, x16, x32, x64 or x128)
// s->set_brightness(s, cameraImageBrightness); // (-2 to 2) - set brightness // s->set_brightness(s, 0); // (-2 to 2) - set brightness
// s->set_lenc(s, 1); // lens correction? (1 or 0) // s->set_lenc(s, 1); // lens correction? (1 or 0)
// s->set_saturation(s, 0); // (-2 to 2) // s->set_saturation(s, 0); // (-2 to 2)
// s->set_contrast(s, cameraImageContrast); // (-2 to 2) // s->set_contrast(s, 0); // (-2 to 2)
// s->set_sharpness(s, 0); // (-2 to 2) // s->set_sharpness(s, 0); // (-2 to 2)
// s->set_hmirror(s, 0); // (0 or 1) flip horizontally // s->set_hmirror(s, 0); // (0 or 1) flip horizontally
// s->set_colorbar(s, 0); // (0 or 1) - show a testcard // s->set_colorbar(s, 0); // (0 or 1) - show a testcard
@ -942,8 +944,8 @@ void handleRoot() {
client.write("<br><br>LINKS: \n"); client.write("<br><br>LINKS: \n");
client.write("<a href='/photo'>Capture an image</a> - \n"); client.write("<a href='/photo'>Capture an image</a> - \n");
client.write("<a href='/img'>View stored image</a> - \n"); client.write("<a href='/img'>View stored image</a> - \n");
client.write("<a href='/rgb'>Capture frame as RGB data</a> - \n"); client.write("<a href='/rgb'>Capture frame and display as RGB data</a> - \n");
client.write("<a href='/greydata'>Capture frame as data</a> - \n"); client.write("<a href='/greydata'>Capture Greyscale frame as data</a> - \n");
client.write("<a href='/stream'>Live stream</a> - \n"); client.write("<a href='/stream'>Live stream</a> - \n");
client.write("<a href='/test'>Test procedure</a>\n"); client.write("<a href='/test'>Test procedure</a>\n");
@ -953,7 +955,7 @@ void handleRoot() {
} }
// capture and show a jpg image // capture and show a jpg image
client.write("<br><a href='/jpg'>"); // make it a link client.write("<br><br><a href='/jpg'>"); // make it a link
client.write("<img id='image1' src='/jpg' width='320' height='240' /> </a>"); // show image from http://x.x.x.x/jpg client.write("<img id='image1' src='/jpg' width='320' height='240' /> </a>"); // show image from http://x.x.x.x/jpg
// javascript to refresh the image periodically // javascript to refresh the image periodically
@ -1533,6 +1535,38 @@ void handleJpeg() {
} // handleJpeg } // handleJpeg
// ----------------------------------------------------------------
// resize greyscale image
// ----------------------------------------------------------------
// src_buf: The source image buffer.
// src_width: The width of the source image buffer.
// src_height: The height of the source image buffer.
// dst_buf: The destination image buffer.
// dst_width: The width of the destination image buffer.
// dst_height: The height of the destination image buffer.
void resize_esp32cam_image_buffer(uint8_t* src_buf, int src_width, int src_height,
uint8_t* dst_buf, int dst_width, int dst_height) {
// Calculate the horizontal and vertical resize ratios.
float h_ratio = (float)src_width / dst_width;
float v_ratio = (float)src_height / dst_height;
// Iterate over the destination image buffer and write the resized pixels.
for (int y = 0; y < dst_height; y++) {
for (int x = 0; x < dst_width; x++) {
// Calculate the source pixel coordinates.
int src_x = (int)(x * h_ratio);
int src_y = (int)(y * v_ratio);
// Read the source pixel value.
uint8_t src_pixel = src_buf[src_y * src_width + src_x];
// Write the resized pixel value to the destination image buffer.
dst_buf[y * dst_width + x] = src_pixel;
}
}
}
// ---------------------------------------------------------------- // ----------------------------------------------------------------
// Capture greyscale image data // Capture greyscale image data
// ---------------------------------------------------------------- // ----------------------------------------------------------------
@ -1564,15 +1598,36 @@ void readGreyscaleImage() {
if (!fb) client.println("Error: Camera image capture failed"); if (!fb) client.println("Error: Camera image capture failed");
// read image data and calculate average pixel value (as demonstration of reading the image data) // read image data and calculate average pixel value (as demonstration of reading the image data)
// note: image x = i % WIDTH, image y = floor(i / WIDTH)
unsigned long dataSize = fb->width * fb->height; unsigned long dataSize = fb->width * fb->height;
unsigned long avrg = 0; unsigned long avrg = 0;
for (int i=0; i < dataSize; i++) { // Note: pixels x position = i % fb->width y position = floor(i / fb->width) for (int y=0; y < fb->height; y++) {
avrg += fb->buf[i]; for (int x=0; x < fb->width; x++) {
avrg += fb->buf[(y * fb->width) + x];
}
} }
client.println("<br>Greyscale Image: The average brightness of the " + String(dataSize) + " pixels is " + String(avrg / dataSize)); client.println("<br>Greyscale Image: The average brightness of the " + String(dataSize) + " pixels is " + String(avrg / dataSize));
client.write("<br><br><a href='/'>Return</a>\n"); // link back client.write("<br><br><a href='/'>Return</a>\n"); // link back
// resize image
int newWidth = 64; int newHeight = 32;
byte newBuf[newWidth * newHeight];
resize_esp32cam_image_buffer(fb->buf, fb->width, fb->height, newBuf, newWidth, newHeight);
// display image
char asciiArt[] = {'@','#','+','!',':','.',' '}; // dark to light characters
const int noAsciiChars = 7; // number of characters
client.write("<br><pre>");
for (int y=0; y < newHeight; y++) {
client.write("</pre><pre>");
for (int x=0; x < newWidth; x++) {
int tpos = map(newBuf[y*newWidth+x],0,255,0,noAsciiChars-1);
client.write(asciiArt[tpos]);
}
}
client.write("<br></pre>");
// close web page // close web page
sendFooter(client); sendFooter(client);
@ -1662,6 +1717,11 @@ void handleTest() {
</script>\n)====="); </script>\n)=====");
// // flip image horizontally
// sensor_t *s = esp_camera_sensor_get();
// s->set_hmirror(s, 1);
/* /*
// demo of how to request a web page // demo of how to request a web page
String page = "http://urlhere.com"; // url to request String page = "http://urlhere.com"; // url to request

Wyświetl plik

@ -47,6 +47,7 @@ I have tried to make the sketch as easy to follow/modify as possible with lots o
as I found it quiet confusing as an ameteur trying to do much with this module and difficult to find easy to understand as I found it quiet confusing as an ameteur trying to do much with this module and difficult to find easy to understand
examples/explanations of what I wanted to do, so I am publishing this sketch in the hope it will encourage/help others to have a examples/explanations of what I wanted to do, so I am publishing this sketch in the hope it will encourage/help others to have a
try with these powerful and VERY affordable modules. try with these powerful and VERY affordable modules.
The greyscale procedure I think is the most interesting as it shows how to switch camera modes and process the raw data very well.
BTW - For some examples of serving web pages with en ESP module you may like to have a look BTW - For some examples of serving web pages with en ESP module you may like to have a look
at: https://github.com/alanesq/BasicWebserver/blob/master/misc/VeryBasicWebserver.ino at: https://github.com/alanesq/BasicWebserver/blob/master/misc/VeryBasicWebserver.ino
@ -91,7 +92,7 @@ URLs:
<br>http://x.x.x.x/stream Show live streaming video <br>http://x.x.x.x/stream Show live streaming video
<br>http://x.x.x.x/img Show most recent image saved to sd card <br>http://x.x.x.x/img Show most recent image saved to sd card
<br>http://x.x.x.x/img?img=1 Show image number 1 on sd card <br>http://x.x.x.x/img?img=1 Show image number 1 on sd card
<br>http://x.x.x.x/rgb Show how to capture a greyscale image and look at the raw data <br>http://x.x.x.x/greyscale Show how to capture a greyscale image and look at the raw data
<br>http://x.x.x.x/rgb Captures an image and converts to RGB data (will not work with the highest <br>http://x.x.x.x/rgb Captures an image and converts to RGB data (will not work with the highest
resolution images as there is not enough memory) resolution images as there is not enough memory)