ที่เก็บนี้เป็นเจ้าภาพไดรเวอร์ที่ใช้งานร่วมกันได้ของ ESP32 SOCE SOC สำหรับเซ็นเซอร์ภาพ นอกจากนี้ยังมีเครื่องมือสองสามอย่างซึ่งอนุญาตให้แปลงข้อมูลเฟรมที่จับได้เป็นรูปแบบ BMP และ JPEG ทั่วไป
แบบอย่าง | ความละเอียดสูงสุด | ประเภทสี | รูปแบบเอาต์พุต | ขนาดเลน |
---|---|---|---|---|
OV2640 | 1600 x 1200 | สี | YUV (422/420)/YCBCR422 RGB565/555 ข้อมูลบีบอัด 8 บิต ข้อมูล RGB ดิบ 8/10 บิต | 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 | สี | RAD 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 ไบเออร์ดิบ RGB565 | 1/10 " |
GC0308 | 640 x 480 | สี | YUV/YCBCR422 ไบเออร์ดิบ RGB565 สีเทา | 1/6.5 " |
GC2145 | 1600 x 1200 | สี | YUV/YCBCR422 ไบเออร์ดิบ RGB565 | 1/5 " |
BF3005 | 640 x 480 | สี | YUV/YCBCR422 ไบเออร์ดิบ RGB565 | 1/4 " |
BF20A6 | 640 x 480 | สี | YUV/YCBCR422 ไบเออร์ดิบ y เท่านั้น | 1/10 " |
SC101iot | 1280 x 720 | สี | YUV/YCBCR422 RGB ดิบ | 1/4.2 " |
SC030IOT | 640 x 480 | สี | YUV/YCBCR422 ไบเออร์ดิบ | 1/6.5 " |
SC031GS | 640 x 480 | ขาวดำ | โมโนดิบ สีเทา | 1/6 " |
fmt2rgb888
หรือ fmt2bmp
/ frame2bmp
espressif/esp32-camera
: idf.py add-dependency " espressif/esp32-camera "
menuconfig
(ยังตั้งค่าแฟลชและ psram frequiencies เป็น 80MHz)esp_camera.h
ในรหัสของคุณ คำแนะนำเหล่านี้ยังใช้งานได้กับ Platformio หากคุณใช้ framework=espidf
หากคุณใช้ Arduino-ESP32 Core ใน Arduino IDE ไม่จำเป็นต้องติดตั้ง! คุณสามารถใช้กล้อง esp32 ได้ทันที
วิธีง่ายๆ - ในส่วน env
ของ platformio.ini
เพิ่มสิ่งต่อไปนี้:
[env]
lib_deps =
esp32-camera
ตอนนี้ esp_camera.h
พร้อมใช้งาน:
#include "esp_camera.h"
เปิดใช้งาน psram บน menuconfig
หรือพิมพ์ direclty บน sdkconfig
ตรวจสอบเอกสารอย่างเป็นทางการสำหรับข้อมูลเพิ่มเติม
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 ;
}