当前位置 博文首页 > 似水流年:ESP32-CAM 使用 (二)

    似水流年:ESP32-CAM 使用 (二)

    作者:[db:作者] 时间:2021-09-08 13:40

    ?拿到这个板子之后,第一件事就是好奇这个板子还有几个引脚可以让我来使用?

    在这里插入图片描述
    在这里插入图片描述在这里插入图片描述
    在这里插入图片描述

    看看代码中定义了几个引脚:

    #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
    

    这里只定义了15个引脚。

    视频质量:

    const int resolution[][2] = {
        { 160, 120 }, /* QQVGA */
        { 128, 160 }, /* QQVGA2*/
        { 176, 144 }, /* QCIF  */
        { 240, 176 }, /* HQVGA */
        { 320, 240 }, /* QVGA  */
        { 400, 296 }, /* CIF   */
        { 640, 480 }, /* VGA   */
        { 800, 600 }, /* SVGA  */
        { 1024, 768 }, /* XGA  */
        { 1280, 1024 }, /* SXGA  */
        { 1600, 1200 }, /* UXGA  */
        { 2048, 1536 }, /* QXGA  */
    };
    

    摄像头OV2640的资料:https://wiki.ai-thinker.com/media/esp32/docs/ov2640_ds_1.8.pdf

    使用最小的QQVGA(160*120)–(2450Byte/25fps)大概100Byte每帧。

    MJPG: 2449B 41ms (24.4fps), AVG: 39ms (25.6fps), 0+0+0+0=0 0
    MJPG: 2456B 38ms (26.3fps), AVG: 39ms (25.6fps), 0+0+0+0=0 0
    MJPG: 2451B 39ms (25.6fps), AVG: 39ms (25.6fps), 0+0+0+0=0 0
    

    使用最大的UXGA(1600*1200)-- (84500Byte/4fps)大概21125Byte每帧。

    MJPG: 84369B 351ms (2.8fps), AVG: 263ms (3.8fps), 0+0+0+0=0 0
    MJPG: 84407B 259ms (3.9fps), AVG: 272ms (3.7fps), 0+0+0+0=0 0
    MJPG: 84208B 247ms (4.0fps), AVG: 262ms (3.8fps), 0+0+0+0=0 0
    

    效果图:
    在这里插入图片描述实现代码:

    #include <WiFi.h>
    #include "esp_http_server.h"
    #include "esp_camera.h"
    #include "esp_timer.h"
    #include "dl_lib.h"
    
    const char* ssid = "liefyuan";
    const char* password = "1234567890";
    
    #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 PART_BOUNDARY "123456789000000000000987654321"
    static const char* _STREAM_CONTENT_TYPE = "multipart/x-mixed-replace;boundary=" PART_BOUNDARY;
    static const char* _STREAM_BOUNDARY = "\r\n--" PART_BOUNDARY "\r\n";
    static const char* _STREAM_PART = "Content-Type: image/jpeg\r\nContent-Length: %u\r\n\r\n";
    
    typedef struct {
            size_t size; //number of values used for filtering
            size_t index; //current value index
            size_t count; //value count
            int sum;
            int * values; //array to be filled with values
    } ra_filter_t;
    
    httpd_handle_t stream_httpd = NULL;
    httpd_handle_t camera_httpd = NULL;
    static ra_filter_t ra_filter;
    
    static int ra_filter_run(ra_filter_t * filter, int value){
        if(!filter->values){
            return value;
        }
        filter->sum -= filter->values[filter->index];
        filter->values[filter->index] = value;
        filter->sum += filter->values[filter->index];
        filter->index++;
        filter->index = filter->index % filter->size;
        if (filter->count < filter->size) {
            filter->count++;
        }
        return filter->sum / filter->count;
    }
    
    static esp_err_t stream_handler(httpd_req_t *req){
        camera_fb_t * fb = NULL;
        esp_err_t res = ESP_OK;
        size_t _jpg_buf_len = 0;
        uint8_t * _jpg_buf = NULL;
        char * part_buf[64];
        dl_matrix3du_t *image_matrix = NULL;
        bool detected = false;
        int face_id = 0;
        int64_t fr_start = 0;
        int64_t fr_ready = 0;
        int64_t fr_face = 0;
        int64_t fr_recognize = 0;
        int64_t fr_encode = 0;
    
        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){
            detected = false;
            face_id = 0;
    
            sensor_t * s = esp_camera_sensor_get();
            s->set_vflip(s, 1);
            
            fb = esp_camera_fb_get();
            if (!fb) {
                Serial.println("Camera capture failed");
                res = ESP_FAIL;
            } else {
                fr_start = esp_timer_get_time();
    
                _jpg_buf_len = fb->len;
                _jpg_buf = fb->buf; 
            }
            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(res == ESP_OK){
                res = httpd_resp_send_chunk(req, _STREAM_BOUNDARY, strlen(_STREAM_BOUNDARY));
            }
            if(fb){
                esp_camera_fb_return(fb);
                fb = NULL;
                _jpg_buf = NULL;
            } else if(_jpg_buf){
                free(_jpg_buf);
                _jpg_buf = NULL;
            }
            if(res != ESP_OK){
                break;
            }
            int64_t fr_end = esp_timer_get_time();
    
            int64_t ready_time = (fr_ready - fr_start)/1000;
            int64_t face_time = (fr_face - fr_ready)/1000;
            int64_t recognize_time = (fr_recognize - fr_face)/1000