esp32 camera
ver v2.0.15
이 저장소는 이미지 센서 용 ESP32 시리즈 SOC 호환 드라이버를 호스팅합니다. 또한 캡처 된 프레임 데이터를보다 일반적인 BMP 및 JPEG 형식으로 변환 할 수있는 몇 가지 도구를 제공합니다.
모델 | 최대 해상도 | 색상 유형 | 출력 형식 | 렌 크기 |
---|---|---|---|---|
OV2640 | 1600 x 1200 | 색상 | yuv (422/420)/ycbcr422 RGB565/555 8 비트 압축 데이터 8/10 비트 원시 RGB 데이터 | 1/4 " |
OV3660 | 2048 x 1536 | 색상 | 원시 RGB 데이터 RGB565/555/444 CCIR656 YCBCR422 압축 | 1/5 " |
OV5640 | 2592 x 1944 | 색상 | 원시 RGB RGB565/555/444 CCIR656 YUV422/420 YCBCR422 압축 | 1/4 " |
OV7670 | 640 x 480 | 색상 | Raw Bayer RGB Bayer RGB 가공 YUV/YCBCR422 GRB422 RGB565/555 | 1/6 " |
OV7725 | 640 x 480 | 색상 | 원시 RGB GRB 422 RGB565/555/444 YCBCR 422 | 1/4 " |
NT99141 | 1280 x 720 | 색상 | YCBCR 422 RGB565/555/444 날것의 CCIR656 JPEG 압축 | 1/4 " |
GC032A | 640 x 480 | 색상 | YUV/YCBCR422 Raw Bayer RGB565 | 1/10 " |
GC0308 | 640 x 480 | 색상 | YUV/YCBCR422 Raw Bayer RGB565 그레이 스케일 | 1/6.5 " |
GC2145 | 1600 x 1200 | 색상 | YUV/YCBCR422 Raw Bayer RGB565 | 1/5 " |
BF3005 | 640 x 480 | 색상 | YUV/YCBCR422 Raw Bayer RGB565 | 1/4 " |
BF20A6 | 640 x 480 | 색상 | YUV/YCBCR422 Raw Bayer y만이 | 1/10 " |
sc101iot | 1280 x 720 | 색상 | YUV/YCBCR422 원시 RGB | 1/4.2 " |
sc030iot | 640 x 480 | 색상 | YUV/YCBCR422 Raw Bayer | 1/6.5 " |
SC031GS | 640 x 480 | 단색화 | 원시 모노 그레이 스케일 | 1/6 " |
fmt2rgb888
또는 fmt2bmp
/ frame2bmp
사용하여 RGB로 전환하는 것이 좋습니다.espressif/esp32-camera
구성 요소에 종속성을 추가하십시오. idf.py add-dependency " espressif/esp32-camera "
menuconfig
에서 psram 활성화 (또한 80MHz로 플래시 및 PSRAM 주파수를 설정)esp_camera.h
포함하십시오 이 지침은 framework=espidf
사용하는 경우 플랫폼에도 작동합니다.
Arduino IDE에서 Arduino-Esp32 코어를 사용하는 경우 설치가 필요하지 않습니다! ESP32-Camera를 즉시 사용할 수 있습니다.
쉬운 방법 - platformio.ini
의 env
섹션에서 다음을 추가하십시오.
[env]
lib_deps =
esp32-camera
이제 esp_camera.h
를 포함시킬 수 있습니다.
#include "esp_camera.h"
menuconfig
에서 psram을 활성화하거나 sdkconfig
에서 direclty를 입력하십시오. 자세한 내용은 공식 문서를 확인하십시오.
CONFIG_ESP32_SPIRAM_SUPPORT=y
이 구성 요소에는 카메라에서 프레임을 얻는 방법을 보여주는 기본 예제가 함께 제공됩니다. 다음 명령을 사용하여 예제를 시도 할 수 있습니다.
idf.py create-project-from-example "espressif/esp32-camera:camera_example"
이 명령은 예제를 camera_example
디렉토리로 다운로드합니다. 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 ;
}