From 5f5eea3ba4de5e1de46cb52787fd8177c5b711b2 Mon Sep 17 00:00:00 2001 From: Ye Hang Yang Date: Thu, 29 Jul 2021 20:48:55 +0800 Subject: [PATCH] :sparkles: Camera with Terminal --- examples/camera_terminal/README.rst | 5 + examples/camera_terminal/README_cn.rst | 32 ++++ examples/camera_terminal/README_zh_CN.md | 96 ---------- .../img/menuconfig_dl_config.png | Bin 29973 -> 0 bytes examples/camera_terminal/main/CMakeLists.txt | 2 +- .../camera_terminal/main/Kconfig.projbuild | 178 ------------------ examples/camera_terminal/main/app_camera.cpp | 82 -------- examples/camera_terminal/main/app_dl.cpp | 140 +++++++------- examples/camera_terminal/main/app_main.cpp | 28 +-- .../camera_terminal/main/include/app_camera.h | 175 ----------------- .../camera_terminal/main/include/app_dl.h | 16 ++ .../camera_terminal/main/include/app_dl.hpp | 7 - examples/camera_terminal/sdkconfig.defaults | 17 ++ .../camera_terminal/sdkconfig.defaults.esp32 | 4 + .../sdkconfig.defaults.esp32s2 | 2 + .../sdkconfig.defaults.esp32s3 | 6 + 16 files changed, 161 insertions(+), 629 deletions(-) create mode 100644 examples/camera_terminal/README.rst create mode 100644 examples/camera_terminal/README_cn.rst delete mode 100644 examples/camera_terminal/README_zh_CN.md delete mode 100644 examples/camera_terminal/img/menuconfig_dl_config.png delete mode 100755 examples/camera_terminal/main/Kconfig.projbuild delete mode 100644 examples/camera_terminal/main/app_camera.cpp delete mode 100644 examples/camera_terminal/main/include/app_camera.h create mode 100644 examples/camera_terminal/main/include/app_dl.h delete mode 100644 examples/camera_terminal/main/include/app_dl.hpp create mode 100644 examples/camera_terminal/sdkconfig.defaults create mode 100644 examples/camera_terminal/sdkconfig.defaults.esp32 create mode 100644 examples/camera_terminal/sdkconfig.defaults.esp32s2 create mode 100644 examples/camera_terminal/sdkconfig.defaults.esp32s3 diff --git a/examples/camera_terminal/README.rst b/examples/camera_terminal/README.rst new file mode 100644 index 0000000..0c979f5 --- /dev/null +++ b/examples/camera_terminal/README.rst @@ -0,0 +1,5 @@ +################################################################################################################################ +Camera with Terminal `[中文] <./README_cn.rst>`_ +################################################################################################################################ + + diff --git a/examples/camera_terminal/README_cn.rst b/examples/camera_terminal/README_cn.rst new file mode 100644 index 0000000..9a278c3 --- /dev/null +++ b/examples/camera_terminal/README_cn.rst @@ -0,0 +1,32 @@ +################################################################################################################################ +Camera with Terminal `[English] <./README.rst>`_ +################################################################################################################################ + +该示例的输入图片来自摄像头,输出结果打印在终端。该示例演示了以下模型接口在实际项目中的使用情况。 + ++ `HumanFaceDetectMSR01 `_ + ++ `HumanFaceDetectMNP01 `_ + ++ `CatFaceDetectMN03 `_ + + + +运行示例 +************************************************************************************************ +1. 参考首页的 `说明文档 <../../>`_ 配置示例。 + +2. 烧录程序,运行 IDF 监视器获取实时结果: + + .. code:: shell + + idf.py flash monitor + + 以选择模型 ``HumanFaceDetectMSR01`` 为例,当人脸凑近摄像头约 50cm 左右,终端打印结果如下所示: + + .. figure:: ./img/result_on_terminal.png + :align: center + + .. + + 打印结果中包括时间消耗和检测的框选坐标。 diff --git a/examples/camera_terminal/README_zh_CN.md b/examples/camera_terminal/README_zh_CN.md deleted file mode 100644 index 3429191..0000000 --- a/examples/camera_terminal/README_zh_CN.md +++ /dev/null @@ -1,96 +0,0 @@ -# Camera Terminal[[English](./README.md)] - -该示例的输入图片来自摄像头,输出结果打印在终端。该示例演示了以下模型接口在实际项目中的使用情况。 - -- [HumanFaceDetectMSR01](https://github.com/espressif/esp-dl/blob/master/include/model_zoo/human_face_detect_msr01.hpp) -- [HumanFaceDetectMNP01](https://github.com/espressif/esp-dl/blob/master/include/model_zoo/human_face_detect_mnp01.hpp) -- [CatFaceDetectMN03](https://github.com/espressif/esp-dl/blob/master/include/model_zoo/cat_face_detect_mn03.hpp) - - - -## 硬件要求: - -芯片: ESP32,ESP32-S2,ESP32-S3 - -摄像头: OV2640,OV3660 - -对于新手,我们为您推荐开发套件:[ESP-EYE](https://www.espressif.com/zh-hans/products/devkits/esp-eye/overview),ESP-S3-EYE,[ESP32-WROVER-KIT](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/hw-reference/esp32/get-started-wrover-kit-v3.html) - - - -## 示例演示: - -如果您完成了硬件准备并已正确安装好摄像头,那我们可以开始软件演示了。 - -1. 打开终端,并进入当前示例所在目录路经: - - ```shell - cd ~/esp-who/examples/camera_terminal - ``` - - - -2. 设定目标芯片: - - ```shell - idf.py set-target [SoC] - ``` - - 将 [SoC] 替换为您的目标芯片,如 esp32、 esp32s2、esp32s3。 - - - -3. 打开 menuconfig,设置参数: - - ```shell - idf.py menuconfig - ``` - - 1. 选用自定义分区: - - ![](../../img/menuconfig_custom_partition_table.png) - - - - 2. 选择正确的摄像头管脚配置,下图以 ESP-EYE 为例: - - ![](../../img/menuconfig_select_camera_pinout.png) - - 如果您使用的是非官方支持的开发组件,请在 Custom Camera Pinout 中配置正确管脚信息。 - - - - 3. 选择您想要运行的模型接口: - - ![](./img/menuconfig_dl_config.png) - - - - 4. 打开外部 RAM: - - ![](../../img/menuconfig_support_external_ram.png) - - - - 注意: - - - 每次设定芯片之后,都需要重新设定以上参数。 - - - 除了以上参数,用户也可以根据应用场景配置 CPU、Flash等的其他参数。 - - - -4. 烧录程序,运行 IDF 监视器获取实时结果: - - ```shell - idf.py flash monitor - ``` - - 以步骤 3 中的模型选择为例,打印结果如下所示: - - ![](./img/result_on_terminal.png) - - 打印结果中包括时间消耗和检测结果。 - - - diff --git a/examples/camera_terminal/img/menuconfig_dl_config.png b/examples/camera_terminal/img/menuconfig_dl_config.png deleted file mode 100644 index 5f72f79388b3eb9f6504f462a0c122d150b86b52..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 29973 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 diff --git a/examples/camera_terminal/main/CMakeLists.txt b/examples/camera_terminal/main/CMakeLists.txt index c74b716..72caa92 100644 --- a/examples/camera_terminal/main/CMakeLists.txt +++ b/examples/camera_terminal/main/CMakeLists.txt @@ -1,7 +1,6 @@ set(COMPONENT_SRCS app_main.cpp app_dl.cpp - app_camera.cpp ) set(COMPONENT_ADD_INCLUDEDIRS @@ -11,6 +10,7 @@ set(COMPONENT_ADD_INCLUDEDIRS set(COMPONENT_REQUIRES esp32-camera esp-dl + common ) register_component() diff --git a/examples/camera_terminal/main/Kconfig.projbuild b/examples/camera_terminal/main/Kconfig.projbuild deleted file mode 100755 index 121f75a..0000000 --- a/examples/camera_terminal/main/Kconfig.projbuild +++ /dev/null @@ -1,178 +0,0 @@ -menu "Camera Terminal" - menu "Camera Pins" - choice CAMERA_MODEL - bool "Select Camera Pinout" - default CAMERA_MODEL_WROVER_KIT - help - Select Camera Pinout. - - config CAMERA_MODEL_WROVER_KIT - bool "WROVER-KIT With OV2640 Module" - config CAMERA_MODEL_ESP_EYE - bool "ESP_EYE DevKit" - config CAMERA_MODEL_M5STACK_PSRAM - bool "M5Stack Camera With PSRAM" - config CAMERA_MODEL_M5STACK_WIDE - bool "M5Stack Camera F (Wide)" - config CAMERA_MODEL_AI_THINKER - bool "ESP32-CAM by AI-Thinker" - config CAMERA_MODEL_CUSTOM - bool "Custom Camera Pinout" - endchoice - - config CAMERA_PIN_PWDN - depends on CAMERA_MODEL_CUSTOM - int "Power Down pin" - range -1 33 - default -1 - help - Select Power Down pin or -1 for unmanaged. - - config CAMERA_PIN_RESET - depends on CAMERA_MODEL_CUSTOM - int "Reset pin" - range -1 33 - default -1 - help - Select Camera Reset pin or -1 for software reset. - - config CAMERA_PIN_XCLK - depends on CAMERA_MODEL_CUSTOM - int "XCLK pin" - range 0 33 - default 21 - help - Select Camera XCLK pin. - - config CAMERA_PIN_SIOD - depends on CAMERA_MODEL_CUSTOM - int "SIOD pin" - range 0 33 - default 26 - help - Select Camera SIOD pin. - - config CAMERA_PIN_SIOC - depends on CAMERA_MODEL_CUSTOM - int "SIOC pin" - range 0 33 - default 27 - help - Select Camera SIOC pin. - - config CAMERA_PIN_VSYNC - depends on CAMERA_MODEL_CUSTOM - int "VSYNC pin" - range 0 39 - default 25 - help - Select Camera VSYNC pin. - - config CAMERA_PIN_HREF - depends on CAMERA_MODEL_CUSTOM - int "HREF pin" - range 0 39 - default 23 - help - Select Camera HREF pin. - - config CAMERA_PIN_PCLK - depends on CAMERA_MODEL_CUSTOM - int "PCLK pin" - range 0 39 - default 25 - help - Select Camera PCLK pin. - - config CAMERA_PIN_Y2 - depends on CAMERA_MODEL_CUSTOM - int "Y2 pin" - range 0 39 - default 4 - help - Select Camera Y2 pin. - - config CAMERA_PIN_Y3 - depends on CAMERA_MODEL_CUSTOM - int "Y3 pin" - range 0 39 - default 5 - help - Select Camera Y3 pin. - - config CAMERA_PIN_Y4 - depends on CAMERA_MODEL_CUSTOM - int "Y4 pin" - range 0 39 - default 18 - help - Select Camera Y4 pin. - - config CAMERA_PIN_Y5 - depends on CAMERA_MODEL_CUSTOM - int "Y5 pin" - range 0 39 - default 19 - help - Select Camera Y5 pin. - - config CAMERA_PIN_Y6 - depends on CAMERA_MODEL_CUSTOM - int "Y6 pin" - range 0 39 - default 36 - help - Select Camera Y6 pin. - - config CAMERA_PIN_Y7 - depends on CAMERA_MODEL_CUSTOM - int "Y7 pin" - range 0 39 - default 39 - help - Select Camera Y7 pin. - - config CAMERA_PIN_Y8 - depends on CAMERA_MODEL_CUSTOM - int "Y8 pin" - range 0 39 - default 34 - help - Select Camera Y8 pin. - - config CAMERA_PIN_Y9 - depends on CAMERA_MODEL_CUSTOM - int "Y9 pin" - range 0 39 - default 35 - help - Select Camera Y9 pin. - - endmenu - - - - menu "DL Configuration" - - choice DL_DETECT_TARGET - bool "Select Detection Model" - default DL_DETECT_HUMAN_FACE - - config DL_DETECT_HUMAN_FACE - bool "Human Face Detection Model" - config DL_DETECT_CAT_FACE - bool "Cat Face Detection Model" - endchoice - - config DL_DETECT_HUMAN_FACE_WITH_KEYPOINT - bool "Enable Human Face Keypoint Detection" - default n - depends on DL_DETECT_HUMAN_FACE - - config DL_RECOGNIZE_HUMAN_FACE - bool "Enable Human Face Recognition" - depends on DL_DETECT_HUMAN_FACE_WITH_KEYPOINT - default n - endmenu - -endmenu \ No newline at end of file diff --git a/examples/camera_terminal/main/app_camera.cpp b/examples/camera_terminal/main/app_camera.cpp deleted file mode 100644 index 81fc98a..0000000 --- a/examples/camera_terminal/main/app_camera.cpp +++ /dev/null @@ -1,82 +0,0 @@ -/* ESPRESSIF MIT License - * - * Copyright (c) 2018 - * - * Permission is hereby granted for use on all ESPRESSIF SYSTEMS products, in which case, - * it is free of charge, to any person obtaining a copy of this software and associated - * documentation files (the "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the Software is furnished - * to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all copies or - * substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS - * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR - * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -#include "app_camera.h" - -static const char *TAG = "app_camera"; - -void app_camera_init() -{ -#if CONFIG_CAMERA_MODEL_ESP_EYE - /* IO13, IO14 is designed for JTAG by default, - * to use it as generalized input, - * firstly declair it as pullup input */ - gpio_config_t conf; - conf.mode = GPIO_MODE_INPUT; - conf.pull_up_en = GPIO_PULLUP_ENABLE; - conf.pull_down_en = GPIO_PULLDOWN_DISABLE; - conf.intr_type = GPIO_INTR_DISABLE; - conf.pin_bit_mask = 1LL << 13; - gpio_config(&conf); - conf.pin_bit_mask = 1LL << 14; - gpio_config(&conf); -#endif - camera_config_t config; - config.ledc_channel = LEDC_CHANNEL_0; - config.ledc_timer = LEDC_TIMER_0; - config.pin_d0 = Y2_GPIO_NUM; - config.pin_d1 = Y3_GPIO_NUM; - config.pin_d2 = Y4_GPIO_NUM; - config.pin_d3 = Y5_GPIO_NUM; - config.pin_d4 = Y6_GPIO_NUM; - config.pin_d5 = Y7_GPIO_NUM; - config.pin_d6 = Y8_GPIO_NUM; - config.pin_d7 = Y9_GPIO_NUM; - config.pin_xclk = XCLK_GPIO_NUM; - config.pin_pclk = PCLK_GPIO_NUM; - config.pin_vsync = VSYNC_GPIO_NUM; - config.pin_href = HREF_GPIO_NUM; - config.pin_sscb_sda = SIOD_GPIO_NUM; - config.pin_sscb_scl = SIOC_GPIO_NUM; - config.pin_pwdn = PWDN_GPIO_NUM; - config.pin_reset = -1;//RESET_GPIO_NUM; - config.xclk_freq_hz = XCLK_FREQ; - config.pixel_format = CAMERA_PIXEL_FORMAT; - config.frame_size = CAMERA_FRAME_SIZE; - config.jpeg_quality = 10; - config.fb_count = 1; - - // camera init - esp_err_t err = esp_camera_init(&config); - if (err != ESP_OK) { - ESP_LOGE(TAG, "Camera init failed with error 0x%x", err); - return; - } - - sensor_t * s = esp_camera_sensor_get(); - s->set_vflip(s, 1);//flip it back - //initial sensors are flipped vertically and colors are a bit saturated - if (s->id.PID == OV3660_PID) { - s->set_brightness(s, 1);//up the blightness just a bit - s->set_saturation(s, -2);//lower the saturation - } -} diff --git a/examples/camera_terminal/main/app_dl.cpp b/examples/camera_terminal/main/app_dl.cpp index 2dc7343..41686c2 100644 --- a/examples/camera_terminal/main/app_dl.cpp +++ b/examples/camera_terminal/main/app_dl.cpp @@ -1,63 +1,74 @@ -#include "app_dl.hpp" +#include "app_dl.h" #include "esp_log.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "sdkconfig.h" -#include "app_camera.h" +#include "app_camera.hpp" #include #include "dl_tool.hpp" #include "dl_image.hpp" #include "dl_detect_define.hpp" +#include "app_common.hpp" -#if CONFIG_DL_DETECT_HUMAN_FACE +#if CONFIG_DL_HUMAN_FACE_DETECTION_S1_MSR01 #include "human_face_detect_msr01.hpp" #endif -#if CONFIG_DL_DETECT_HUMAN_FACE_WITH_KEYPOINT +#if CONFIG_DL_HUMAN_FACE_DETECTION_S2_MNP01 #include "human_face_detect_mnp01.hpp" #endif -#if CONFIG_DL_DETECT_CAT_FACE +#if CONFIG_DL_CAT_FACE_DETECTION_MN03 #include "cat_face_detect_mn03.hpp" #endif -#if CONFIG_DL_RECOGNIZE_HUMAN_FACE +#if CONFIG_DL_HUMAN_FACE_RECOGNITION_XXX // TODO: recognize human face #endif static const char *TAG = "app_dl"; + void task_dl(void *arg) { camera_fb_t *fb = NULL; - uint8_t *image_rgb888; + IMAGE_T *image_ptr; dl::tool::Latency latency_total(24); dl::tool::Latency latency_fetch; dl::tool::Latency latency_decode; dl::tool::Latency latency_detect; + dl::tool::Latency latency_recognize; /* 1. Load configuration for detection */ -#if CONFIG_DL_DETECT_HUMAN_FACE +#if CONFIG_DL_HUMAN_FACE +#if CONFIG_DL_HUMAN_FACE_DETECTION_S1_MSR01 HumanFaceDetectMSR01 detector(0.3F, 0.3F, 10, 0.3F); #endif -#if CONFIG_DL_DETECT_HUMAN_FACE_WITH_KEYPOINT +#if CONFIG_DL_HUMAN_FACE_DETECTION_S2_MNP01 HumanFaceDetectMNP01 detector2(0.4F, 0.3F, 10); #endif -#if CONFIG_DL_DETECT_CAT_FACE - CatFaceDetectMN03 detector(0.4F, 0.3F, 10, 0.3F); +#if CONFIG_DL_HUMAN_FACE_RECOGNITION_XXX +// TODO: recognize human face +#endif #endif -#if CONFIG_DL_RECOGNIZE_HUMAN_FACE - dl::tool::Latency latency_recognize; -// TODO: recognize human face +#if CONFIG_DL_CAT_FACE +#if CONFIG_DL_CAT_FACE_DETECTION_MN03 + CatFaceDetectMN03 detector(0.4F, 0.3F, 10, 0.3F); +#endif #endif while (true) { + latency_fetch.clear_period(); + latency_decode.clear_period(); + latency_detect.clear_period(); + latency_recognize.clear_period(); + latency_total.start(); /* 2. Get one image with camera */ @@ -70,81 +81,80 @@ void task_dl(void *arg) } latency_fetch.end(); +#if CONFIG_DL_ENABLED /* 3. Transform image to RGB */ latency_decode.start(); - image_rgb888 = (uint8_t *)dl::tool::malloc_aligned(fb->height * fb->width * 3, sizeof(uint8_t)); - bool res = fmt2rgb888(fb->buf, fb->len, fb->format, image_rgb888); - if (false == res) - { - ESP_LOGE(TAG, "fmt2rgb888 failed, fb: %d", fb->len); - dl::tool::free_aligned(image_rgb888); - continue; - } int image_height = fb->height; int image_width = fb->width; + if (app_camera_decode(fb, &image_ptr) == false) + { + esp_camera_fb_return(fb); + continue; + } +#if !CONFIG_CAMERA_PIXEL_FORMAT_RGB565 esp_camera_fb_return(fb); +#endif latency_decode.end(); /* 4. Do deep-learning processing */ +#if CONFIG_DL_HUMAN_FACE latency_detect.start(); -#if CONFIG_DL_DETECT_HUMAN_FACE_WITH_KEYPOINT - std::list &candidates = detector.infer((uint8_t *)image_rgb888, {image_height, image_width, 3}); - std::list &results = detector2.infer((uint8_t *)image_rgb888, {image_height, image_width, 3}, candidates); +#if CONFIG_DL_HUMAN_FACE_DETECTION_S2_ENABLED + std::list &detect_candidates = detector.infer((IMAGE_T *)image_ptr, {(int)image_height, (int)image_width, 3}); + std::list &detect_results = detector2.infer((IMAGE_T *)image_ptr, {(int)image_height, (int)image_width, 3}, detect_candidates); #else - std::list &results = detector.infer((uint8_t *)image_rgb888, {image_height, image_width, 3}); + std::list &detect_results = detector.infer((IMAGE_T *)image_ptr, {(int)image_height, (int)image_width, 3}); #endif latency_detect.end(); -#if CONFIG_DL_RECOGNIZE_HUMAN_FACE - latency_recognize.start(); -#endif - if (results.size() > 0) + if (detect_results.size() > 0) { - int i = 0; - for (std::list::iterator prediction = results.begin(); prediction != results.end(); prediction++, i++) - { -#if CONFIG_DL_DETECT_HUMAN_FACE_WITH_KEYPOINT - ESP_LOGI(TAG, "[%d]: (%3d, %3d, %3d, %3d) | left eye: (%3d, %3d), right eye: (%3d, %3d), nose: (%3d, %3d), mouth left: (%3d, %3d), mouth right: (%3d, %3d)", - i, - prediction->box[0], prediction->box[1], prediction->box[2], prediction->box[3], - prediction->keypoint[0], prediction->keypoint[1], // left eye - prediction->keypoint[6], prediction->keypoint[7], // right eye - prediction->keypoint[4], prediction->keypoint[5], // nose - prediction->keypoint[2], prediction->keypoint[3], // mouth left corner - prediction->keypoint[8], prediction->keypoint[9]); // mouth right corner -#else - ESP_LOGI(TAG, "[%d]: (%3d, %3d, %3d, %3d)", - i, - prediction->box[0], prediction->box[1], prediction->box[2], prediction->box[3]); -#endif - } + print_detection_result(detect_results); -#if CONFIG_DL_RECOGNIZE_HUMAN_FACE +#if CONFIG_DL_HUMAN_FACE_RECOGNITION_ENABLED latency_recognize.start(); + // TODO: recognize human face + latency_recognize.end(); #endif } -#if CONFIG_DL_RECOGNIZE_HUMAN_FACE - latency_recognize.end(); -#endif - dl::tool::free_aligned(image_rgb888); - latency_total.end(); +#endif // CONFIG_DL_HUMAN_FACE +#if CONFIG_DL_CAT_FACE + latency_detect.start(); + std::list &detect_results = detector.infer((IMAGE_T *)image_ptr, {(int)image_height, (int)image_width, 3}); + latency_detect.end(); + if (detect_results.size() > 0) + { + is_detected = true; + print_detection_result(image_ptr, fb->height, fb->width, detect_results); + } +#endif // CONFIG_DL_CAT_FACE + +#if CONFIG_DL_HUMAN_HAND + latency_detect.start(); + // TODO: + latency_detect.end(); +#endif // CONFIG_DL_HUMAN_HAND + +#if CONFIG_CAMERA_PIXEL_FORMAT_RGB565 + esp_camera_fb_return(fb); +#else + dl::tool::free_aligned(image_ptr); +#endif + +#else // not CONFIG_DL_ENABLED + esp_camera_fb_return(fb); +#endif // CONFIG_DL_ENABLED + + latency_total.end(); uint32_t frame_latency = latency_total.get_period() / 1000; uint32_t average_frame_latency = latency_total.get_average_period() / 1000; - ESP_LOGI(TAG, "Frame: %4ums (%.1ffps), Average: %4ums (%.1ffps) | fetch: %4ums, decode: %4ums, detect: %4ums" -#if CONFIG_DL_RECOGNIZE_HUMAN_FACE - ", recognize: %5ums" -#endif - , + ESP_LOGI(TAG, "Frame: %4ums (%2.1ffps), Average: %4ums (%2.1ffps) | fetch: %4ums, decode: %4ums, detect: %4ums, recognize: %5ums", frame_latency, 1000.0 / frame_latency, average_frame_latency, 1000.0 / average_frame_latency, latency_fetch.get_period() / 1000, latency_decode.get_period() / 1000, - latency_detect.get_period() / 1000 -#if CONFIG_DL_RECOGNIZE_HUMAN_FACE - , - latency_recognize.get_period() / 1000 -#endif - ); + latency_detect.get_period() / 1000, + latency_recognize.get_period() / 1000); } } diff --git a/examples/camera_terminal/main/app_main.cpp b/examples/camera_terminal/main/app_main.cpp index 37ad867..ad6016e 100644 --- a/examples/camera_terminal/main/app_main.cpp +++ b/examples/camera_terminal/main/app_main.cpp @@ -1,30 +1,8 @@ -/* ESPRESSIF MIT License - * - * Copyright (c) 2018 - * - * Permission is hereby granted for use on all ESPRESSIF SYSTEMS products, in which case, - * it is free of charge, to any person obtaining a copy of this software and associated - * documentation files (the "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the Software is furnished - * to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all copies or - * substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS - * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR - * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -#include "app_camera.h" -#include "app_dl.hpp" +#include "app_camera.hpp" +#include "app_dl.h" extern "C" void app_main() { - app_camera_init(); + app_camera_init(FRAMESIZE_QVGA, 12, 2); app_dl_init(); } diff --git a/examples/camera_terminal/main/include/app_camera.h b/examples/camera_terminal/main/include/app_camera.h deleted file mode 100644 index 53441e7..0000000 --- a/examples/camera_terminal/main/include/app_camera.h +++ /dev/null @@ -1,175 +0,0 @@ -/* - * ESPRESSIF MIT License - * - * Copyright (c) 2017 - * - * Permission is hereby granted for use on ESPRESSIF SYSTEMS products only, in which case, - * it is free of charge, to any person obtaining a copy of this software and associated - * documentation files (the "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the Software is furnished - * to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all copies or - * substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS - * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR - * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - */ -#ifndef _APP_CAMERA_H_ -#define _APP_CAMERA_H_ - -#include "esp_log.h" -#include "esp_system.h" -#include "esp_camera.h" - -/** - * PIXFORMAT_RGB565, // 2BPP/RGB565 - * PIXFORMAT_YUV422, // 2BPP/YUV422 - * PIXFORMAT_GRAYSCALE, // 1BPP/GRAYSCALE - * PIXFORMAT_JPEG, // JPEG/COMPRESSED - * PIXFORMAT_RGB888, // 3BPP/RGB888 - */ -#define CAMERA_PIXEL_FORMAT PIXFORMAT_JPEG - -/* - * FRAMESIZE_QQVGA, // 160x120 - * FRAMESIZE_QQVGA2, // 128x160 - * FRAMESIZE_QCIF, // 176x144 - * FRAMESIZE_HQVGA, // 240x176 - * FRAMESIZE_QVGA, // 320x240 - * FRAMESIZE_CIF, // 400x296 - * FRAMESIZE_VGA, // 640x480 - * FRAMESIZE_SVGA, // 800x600 - * FRAMESIZE_XGA, // 1024x768 - * FRAMESIZE_SXGA, // 1280x1024 - * FRAMESIZE_UXGA, // 1600x1200 - */ -#define CAMERA_FRAME_SIZE FRAMESIZE_QVGA - -#if CONFIG_CAMERA_MODEL_WROVER_KIT -#define PWDN_GPIO_NUM -1 -#define RESET_GPIO_NUM -1 -#define XCLK_GPIO_NUM 21 -#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 19 -#define Y4_GPIO_NUM 18 -#define Y3_GPIO_NUM 5 -#define Y2_GPIO_NUM 4 -#define VSYNC_GPIO_NUM 25 -#define HREF_GPIO_NUM 23 -#define PCLK_GPIO_NUM 22 - -#elif CONFIG_CAMERA_MODEL_ESP_EYE -#define PWDN_GPIO_NUM -1 -#define RESET_GPIO_NUM -1 -#define XCLK_GPIO_NUM 4 -#define SIOD_GPIO_NUM 18 -#define SIOC_GPIO_NUM 23 - -#define Y9_GPIO_NUM 36 -#define Y8_GPIO_NUM 37 -#define Y7_GPIO_NUM 38 -#define Y6_GPIO_NUM 39 -#define Y5_GPIO_NUM 35 -#define Y4_GPIO_NUM 14 -#define Y3_GPIO_NUM 13 -#define Y2_GPIO_NUM 34 -#define VSYNC_GPIO_NUM 5 -#define HREF_GPIO_NUM 27 -#define PCLK_GPIO_NUM 25 - -#elif CONFIG_CAMERA_MODEL_M5STACK_PSRAM -#define PWDN_GPIO_NUM -1 -#define RESET_GPIO_NUM 15 -#define XCLK_GPIO_NUM 27 -#define SIOD_GPIO_NUM 25 -#define SIOC_GPIO_NUM 23 - -#define Y9_GPIO_NUM 19 -#define Y8_GPIO_NUM 36 -#define Y7_GPIO_NUM 18 -#define Y6_GPIO_NUM 39 -#define Y5_GPIO_NUM 5 -#define Y4_GPIO_NUM 34 -#define Y3_GPIO_NUM 35 -#define Y2_GPIO_NUM 32 -#define VSYNC_GPIO_NUM 22 -#define HREF_GPIO_NUM 26 -#define PCLK_GPIO_NUM 21 - -#elif CONFIG_CAMERA_MODEL_M5STACK_WIDE -#define PWDN_GPIO_NUM -1 -#define RESET_GPIO_NUM 15 -#define XCLK_GPIO_NUM 27 -#define SIOD_GPIO_NUM 22 -#define SIOC_GPIO_NUM 23 - -#define Y9_GPIO_NUM 19 -#define Y8_GPIO_NUM 36 -#define Y7_GPIO_NUM 18 -#define Y6_GPIO_NUM 39 -#define Y5_GPIO_NUM 5 -#define Y4_GPIO_NUM 34 -#define Y3_GPIO_NUM 35 -#define Y2_GPIO_NUM 32 -#define VSYNC_GPIO_NUM 25 -#define HREF_GPIO_NUM 26 -#define PCLK_GPIO_NUM 21 - -#elif CONFIG_CAMERA_MODEL_AI_THINKER -#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 - - -#elif CONFIG_CAMERA_MODEL_CUSTOM -#define PWDN_GPIO_NUM CONFIG_CAMERA_PIN_PWDN -#define RESET_GPIO_NUM CONFIG_CAMERA_PIN_RESET -#define XCLK_GPIO_NUM CONFIG_CAMERA_PIN_XCLK -#define SIOD_GPIO_NUM CONFIG_CAMERA_PIN_SIOD -#define SIOC_GPIO_NUM CONFIG_CAMERA_PIN_SIOC - -#define Y9_GPIO_NUM CONFIG_CAMERA_PIN_Y9 -#define Y8_GPIO_NUM CONFIG_CAMERA_PIN_Y8 -#define Y7_GPIO_NUM CONFIG_CAMERA_PIN_Y7 -#define Y6_GPIO_NUM CONFIG_CAMERA_PIN_Y6 -#define Y5_GPIO_NUM CONFIG_CAMERA_PIN_Y5 -#define Y4_GPIO_NUM CONFIG_CAMERA_PIN_Y4 -#define Y3_GPIO_NUM CONFIG_CAMERA_PIN_Y3 -#define Y2_GPIO_NUM CONFIG_CAMERA_PIN_Y2 -#define VSYNC_GPIO_NUM CONFIG_CAMERA_PIN_VSYNC -#define HREF_GPIO_NUM CONFIG_CAMERA_PIN_HREF -#define PCLK_GPIO_NUM CONFIG_CAMERA_PIN_PCLK -#endif - -#define XCLK_FREQ 20000000 - -void app_camera_init(); - -#endif diff --git a/examples/camera_terminal/main/include/app_dl.h b/examples/camera_terminal/main/include/app_dl.h new file mode 100644 index 0000000..5a43576 --- /dev/null +++ b/examples/camera_terminal/main/include/app_dl.h @@ -0,0 +1,16 @@ +#pragma once + +#ifdef __cplusplus +extern "C" +{ +#endif + + /** + * @brief Initialize deep-learning application task. + * + */ + void app_dl_init(); + +#ifdef __cplusplus +} +#endif diff --git a/examples/camera_terminal/main/include/app_dl.hpp b/examples/camera_terminal/main/include/app_dl.hpp deleted file mode 100644 index 2d5d1fd..0000000 --- a/examples/camera_terminal/main/include/app_dl.hpp +++ /dev/null @@ -1,7 +0,0 @@ -#pragma once - -/** - * @brief Initialize deep-learning application task. - * - */ -void app_dl_init(); \ No newline at end of file diff --git a/examples/camera_terminal/sdkconfig.defaults b/examples/camera_terminal/sdkconfig.defaults new file mode 100644 index 0000000..15e61e3 --- /dev/null +++ b/examples/camera_terminal/sdkconfig.defaults @@ -0,0 +1,17 @@ +CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y + +CONFIG_ESPTOOLPY_FLASHFREQ_80M=y +CONFIG_ESPTOOLPY_FLASHMODE_QIO=y + +CONFIG_SPIRAM_SPEED_80M=y + +CONFIG_PARTITION_TABLE_CUSTOM=y +CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv" + +CONFIG_ESP_TASK_WDT=n + + +# Wait for esp-idf stable +CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_PERF=y +CONFIG_BOOTLOADER_LOG_LEVEL_NONE=y +CONFIG_SPIRAM_MEMTEST=n diff --git a/examples/camera_terminal/sdkconfig.defaults.esp32 b/examples/camera_terminal/sdkconfig.defaults.esp32 new file mode 100644 index 0000000..f50e6af --- /dev/null +++ b/examples/camera_terminal/sdkconfig.defaults.esp32 @@ -0,0 +1,4 @@ +CONFIG_ESP32_DEFAULT_CPU_FREQ_240=y +CONFIG_ESP32_SPIRAM_SUPPORT=y + +CONFIG_CAMERA_MODULE_ESP_EYE=y diff --git a/examples/camera_terminal/sdkconfig.defaults.esp32s2 b/examples/camera_terminal/sdkconfig.defaults.esp32s2 new file mode 100644 index 0000000..54c3aaa --- /dev/null +++ b/examples/camera_terminal/sdkconfig.defaults.esp32s2 @@ -0,0 +1,2 @@ +CONFIG_ESP32S2_DEFAULT_CPU_FREQ_240=y +CONFIG_ESP32S2_SPIRAM_SUPPORT=y diff --git a/examples/camera_terminal/sdkconfig.defaults.esp32s3 b/examples/camera_terminal/sdkconfig.defaults.esp32s3 new file mode 100644 index 0000000..0206705 --- /dev/null +++ b/examples/camera_terminal/sdkconfig.defaults.esp32s3 @@ -0,0 +1,6 @@ +CONFIG_ESP32S3_DEFAULT_CPU_FREQ_240=y +CONFIG_ESP32S3_SPIRAM_SUPPORT=y + +CONFIG_CAMERA_MODULE_ESP_S3_EYE=y +CONFIG_ESPTOOLPY_NO_STUB=y +CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG=y