Dieses Repository hostet die ESC -Kompatibilität für Bildsensoren der ESP32 -Serie. Darüber hinaus bietet es einige Tools, mit denen die erfassten Frame -Daten in die häufigeren BMP- und JPEG -Formate konvertiert werden können.
Modell | maximale Auflösung | Farbtyp | Ausgangsformat | Len -Größe |
---|---|---|---|---|
OV2640 | 1600 x 1200 | Farbe | YUV (422/420)/YCBCR422 RGB565/555 8-Bit-komprimierte Daten 8/10-Bit-Roh-RGB-Daten | 1/4 " |
OV3660 | 2048 x 1536 | Farbe | Roh -RGB -Daten RGB565/555/444 CCIR656 YCBCR422 Kompression | 1/5 " |
OV5640 | 2592 x 1944 | Farbe | Rohe RGB RGB565/555/444 CCIR656 YUV422/420 YCBCR422 Kompression | 1/4 " |
OV7670 | 640 x 480 | Farbe | Raw Bayer RGB Verarbeiteter Bayer RGB YUV/YCBCR422 Grb422 RGB565/555 | 1/6 " |
OV7725 | 640 x 480 | Farbe | Rohe RGB Grb 422 RGB565/555/444 YCBCR 422 | 1/4 " |
NT99141 | 1280 x 720 | Farbe | YCBCR 422 RGB565/555/444 Roh CCIR656 JPEG -Komprimierung | 1/4 " |
GC032A | 640 x 480 | Farbe | YUV/YCBCR422 Roh Bayer RGB565 | 1/10 " |
GC0308 | 640 x 480 | Farbe | YUV/YCBCR422 Roh Bayer RGB565 Graustufen | 1/6,5 " |
GC2145 | 1600 x 1200 | Farbe | YUV/YCBCR422 Roh Bayer RGB565 | 1/5 " |
BF3005 | 640 x 480 | Farbe | YUV/YCBCR422 Roh Bayer RGB565 | 1/4 " |
BF20A6 | 640 x 480 | Farbe | YUV/YCBCR422 Roh Bayer Nur y | 1/10 " |
SC101iot | 1280 x 720 | Farbe | YUV/YCBCR422 Rohe RGB | 1/4.2 " |
SC030iot | 640 x 480 | Farbe | YUV/YCBCR422 Roh Bayer | 1/6,5 " |
SC031GS | 640 x 480 | einfarbig | Rohmono Graustufen | 1/6 " |
fmt2rgb888
oder fmt2bmp
/ frame2bmp
in RGB umgewandelt wird.espressif/esp32-camera
Komponente hinzu: idf.py add-dependency " espressif/esp32-camera "
menuconfig
(setzen Sie auch Flash- und PSRAM -Frequenzen auf 80 MHz)esp_camera.h
in Ihren Code ein Diese Anweisungen funktionieren auch für Platformio, wenn Sie framework=espidf
verwenden.
Wenn Sie den Arduino-Esp32-Kern in Arduino IDE verwenden, ist keine Installation erforderlich! Sie können ESP32-Kamera sofort verwenden.
Der einfache Weg - Auf dem env
-Abschnitt von platformio.ini
fügen Sie Folgendes hinzu:
[env]
lib_deps =
esp32-camera
Jetzt ist die esp_camera.h
für die Aufnahme verfügbar:
#include "esp_camera.h"
Aktivieren Sie PSRAM auf menuconfig
oder geben Sie es auf sdkconfig
ein. Weitere Informationen finden Sie im offiziellen Dokument.
CONFIG_ESP32_SPIRAM_SUPPORT=y
Diese Komponente wird mit einem grundlegenden Beispiel geliefert, das zeigt, wie Frames von der Kamera abgerufen werden. Sie können das Beispiel mit dem folgenden Befehl ausprobieren:
idf.py create-project-from-example "espressif/esp32-camera:camera_example"
In diesem Befehl wird das Beispiel in das Verzeichnis camera_example
heruntergeladen. Es ist bereits vorkonfiguriert mit den richtigen Einstellungen in Menuconfig.
#include "esp_camera.h"
//WROVER-KIT PIN Map
#define CAM_PIN_PWDN -1 //power down is not used
#define CAM_PIN_RESET -1 //software reset will be performed
#define CAM_PIN_XCLK 21
#define CAM_PIN_SIOD 26
#define CAM_PIN_SIOC 27
#define CAM_PIN_D7 35
#define CAM_PIN_D6 34
#define CAM_PIN_D5 39
#define CAM_PIN_D4 36
#define CAM_PIN_D3 19
#define CAM_PIN_D2 18
#define CAM_PIN_D1 5
#define CAM_PIN_D0 4
#define CAM_PIN_VSYNC 25
#define CAM_PIN_HREF 23
#define CAM_PIN_PCLK 22
static camera_config_t camera_config = {
. pin_pwdn = CAM_PIN_PWDN ,
. pin_reset = CAM_PIN_RESET ,
. pin_xclk = CAM_PIN_XCLK ,
. pin_sccb_sda = CAM_PIN_SIOD ,
. pin_sccb_scl = CAM_PIN_SIOC ,
. pin_d7 = CAM_PIN_D7 ,
. pin_d6 = CAM_PIN_D6 ,
. pin_d5 = CAM_PIN_D5 ,
. pin_d4 = CAM_PIN_D4 ,
. pin_d3 = CAM_PIN_D3 ,
. pin_d2 = CAM_PIN_D2 ,
. pin_d1 = CAM_PIN_D1 ,
. pin_d0 = CAM_PIN_D0 ,
. pin_vsync = CAM_PIN_VSYNC ,
. pin_href = CAM_PIN_HREF ,
. pin_pclk = CAM_PIN_PCLK ,
. xclk_freq_hz = 20000000 , //EXPERIMENTAL: Set to 16MHz on ESP32-S2 or ESP32-S3 to enable EDMA mode
. ledc_timer = LEDC_TIMER_0 ,
. ledc_channel = LEDC_CHANNEL_0 ,
. pixel_format = PIXFORMAT_JPEG , //YUV422,GRAYSCALE,RGB565,JPEG
. frame_size = FRAMESIZE_UXGA , //QQVGA-UXGA, For ESP32, do not use sizes above QVGA when not JPEG. The performance of the ESP32-S series has improved a lot, but JPEG mode always gives better frame rates.
. jpeg_quality = 12 , //0-63, for OV series camera sensors, lower number means higher quality
. fb_count = 1 , //When jpeg mode is used, if fb_count more than one, the driver will work in continuous mode.
. grab_mode = CAMERA_GRAB_WHEN_EMPTY //CAMERA_GRAB_LATEST. Sets when buffers should be filled
};
esp_err_t camera_init (){
//power up the camera if PWDN pin is defined
if ( CAM_PIN_PWDN != -1 ){
pinMode ( CAM_PIN_PWDN , OUTPUT );
digitalWrite ( CAM_PIN_PWDN , LOW );
}
//initialize the camera
esp_err_t err = esp_camera_init ( & camera_config );
if ( err != ESP_OK ) {
ESP_LOGE ( TAG , "Camera Init Failed" );
return err ;
}
return ESP_OK ;
}
esp_err_t camera_capture (){
//acquire a frame
camera_fb_t * fb = esp_camera_fb_get ();
if (! fb ) {
ESP_LOGE ( TAG , "Camera Capture Failed" );
return ESP_FAIL ;
}
//replace this with your own function
process_image ( fb -> width , fb -> height , fb -> format , fb -> buf , fb -> len );
//return the frame buffer back to the driver for reuse
esp_camera_fb_return ( fb );
return ESP_OK ;
}
#include "esp_camera.h"
#include "esp_http_server.h"
#include "esp_timer.h"
typedef struct {
httpd_req_t * req ;
size_t len ;
} jpg_chunking_t ;
static size_t jpg_encode_stream ( void * arg , size_t index , const void * data , size_t len ){
jpg_chunking_t * j = ( jpg_chunking_t * ) arg ;
if (! index ){
j -> len = 0 ;
}
if ( httpd_resp_send_chunk ( j -> req , ( const char * ) data , len ) != ESP_OK ){
return 0 ;
}
j -> len += len ;
return len ;
}
esp_err_t jpg_httpd_handler ( httpd_req_t * req ){
camera_fb_t * fb = NULL ;
esp_err_t res = ESP_OK ;
size_t fb_len = 0 ;
int64_t fr_start = esp_timer_get_time ();
fb = esp_camera_fb_get ();
if (! fb ) {
ESP_LOGE ( TAG , "Camera capture failed" );
httpd_resp_send_500 ( req );
return ESP_FAIL ;
}
res = httpd_resp_set_type ( req , "image/jpeg" );
if ( res == ESP_OK ){
res = httpd_resp_set_hdr ( req , "Content-Disposition" , "inline; filename=capture.jpg" );
}
if ( res == ESP_OK ){
if ( fb -> format == PIXFORMAT_JPEG ){
fb_len = fb -> len ;
res = httpd_resp_send ( req , ( const char * ) fb -> buf , fb -> len );
} else {
jpg_chunking_t jchunk = { req , 0 };
res = frame2jpg_cb ( fb , 80 , jpg_encode_stream , & jchunk )? ESP_OK : ESP_FAIL ;
httpd_resp_send_chunk ( req , NULL , 0 );
fb_len = jchunk . len ;
}
}
esp_camera_fb_return ( fb );
int64_t fr_end = esp_timer_get_time ();
ESP_LOGI ( TAG , "JPG: %uKB %ums" , ( uint32_t )( fb_len / 1024 ), ( uint32_t )(( fr_end - fr_start )/ 1000 ));
return res ;
}
#include "esp_camera.h"
#include "esp_http_server.h"
#include "esp_timer.h"
#define PART_BOUNDARY "123456789000000000000987654321"
static const char * _STREAM_CONTENT_TYPE = "multipart/x-mixed-replace;boundary=" PART_BOUNDARY ;
static const char * _STREAM_BOUNDARY = "rn--" PART_BOUNDARY "rn" ;
static const char * _STREAM_PART = "Content-Type: image/jpegrnContent-Length: %urnrn" ;
esp_err_t jpg_stream_httpd_handler ( httpd_req_t * req ){
camera_fb_t * fb = NULL ;
esp_err_t res = ESP_OK ;
size_t _jpg_buf_len ;
uint8_t * _jpg_buf ;
char * part_buf [ 64 ];
static int64_t last_frame = 0 ;
if (! last_frame ) {
last_frame = esp_timer_get_time ();
}
res = httpd_resp_set_type ( req , _STREAM_CONTENT_TYPE );
if ( res != ESP_OK ){
return res ;
}
while (true){
fb = esp_camera_fb_get ();
if (! fb ) {
ESP_LOGE ( TAG , "Camera capture failed" );
res = ESP_FAIL ;
break ;
}
if ( fb -> format != PIXFORMAT_JPEG ){
bool jpeg_converted = frame2jpg ( fb , 80 , & _jpg_buf , & _jpg_buf_len );
if (! jpeg_converted ){
ESP_LOGE ( TAG , "JPEG compression failed" );
esp_camera_fb_return ( fb );
res = ESP_FAIL ;
}
} else {
_jpg_buf_len = fb -> len ;
_jpg_buf = fb -> buf ;
}
if ( res == ESP_OK ){
res = httpd_resp_send_chunk ( req , _STREAM_BOUNDARY , strlen ( _STREAM_BOUNDARY ));
}
if ( res == ESP_OK ){
size_t hlen = snprintf (( char * ) part_buf , 64 , _STREAM_PART , _jpg_buf_len );
res = httpd_resp_send_chunk ( req , ( const char * ) part_buf , hlen );
}
if ( res == ESP_OK ){
res = httpd_resp_send_chunk ( req , ( const char * ) _jpg_buf , _jpg_buf_len );
}
if ( fb -> format != PIXFORMAT_JPEG ){
free ( _jpg_buf );
}
esp_camera_fb_return ( fb );
if ( res != ESP_OK ){
break ;
}
int64_t fr_end = esp_timer_get_time ();
int64_t frame_time = fr_end - last_frame ;
last_frame = fr_end ;
frame_time /= 1000 ;
ESP_LOGI ( TAG , "MJPG: %uKB %ums (%.1ffps)" ,
( uint32_t )( _jpg_buf_len / 1024 ),
( uint32_t ) frame_time , 1000.0 / ( uint32_t ) frame_time );
}
last_frame = 0 ;
return res ;
}
#include "esp_camera.h"
#include "esp_http_server.h"
#include "esp_timer.h"
esp_err_t bmp_httpd_handler ( httpd_req_t * req ){
camera_fb_t * fb = NULL ;
esp_err_t res = ESP_OK ;
int64_t fr_start = esp_timer_get_time ();
fb = esp_camera_fb_get ();
if (! fb ) {
ESP_LOGE ( TAG , "Camera capture failed" );
httpd_resp_send_500 ( req );
return ESP_FAIL ;
}
uint8_t * buf = NULL ;
size_t buf_len = 0 ;
bool converted = frame2bmp ( fb , & buf , & buf_len );
esp_camera_fb_return ( fb );
if (! converted ){
ESP_LOGE ( TAG , "BMP conversion failed" );
httpd_resp_send_500 ( req );
return ESP_FAIL ;
}
res = httpd_resp_set_type ( req , "image/x-windows-bmp" )
|| httpd_resp_set_hdr ( req , "Content-Disposition" , "inline; filename=capture.bmp" )
|| httpd_resp_send ( req , ( const char * ) buf , buf_len );
free ( buf );
int64_t fr_end = esp_timer_get_time ();
ESP_LOGI ( TAG , "BMP: %uKB %ums" , ( uint32_t )( buf_len / 1024 ), ( uint32_t )(( fr_end - fr_start )/ 1000 ));
return res ;
}