mirror of
https://gitcode.com/gh_mirrors/es/esp32-opencv.git
synced 2025-08-14 01:57:43 +08:00
Final version of the demo
- Changing from RGB565 to Grayscale, Binarized and finally Canny edge
This commit is contained in:
2
esp32/examples/.gitignore
vendored
Normal file
2
esp32/examples/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
private/
|
||||
*.mp4
|
@ -1,6 +1,16 @@
|
||||
# TTGO demo
|
||||
|
||||
This demo purpose is to see the cross-compiled OpenCV library working on the esp32, using an OV2640 camera and an LCD.
|
||||
This demo purpose is to see the cross-compiled OpenCV library working on the TTGO module (see https://github.com/Xinyuan-LilyGo/esp32-camera-screen), using an OV2640 camera and an LCD.
|
||||
|
||||
The demo gets an image from the camera, then depending on the DisplayMode, applies a Grayscale, Binary or Canny filter on it and finally set it on the LCD.
|
||||
The demo gets an image from the camera, then depending on the DisplayMode (changing at regular interval), applies a Grayscale, Binary or Canny filter on it and finally displays it on the LCD.
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
The performances of the processing are approximately:
|
||||
|
||||
* 6 fps with RGB565 image
|
||||
* 6 fps with Grayscale image
|
||||
* 6 fps with Threshold transformation
|
||||
* 3 fps with Canny detection
|
BIN
esp32/examples/ttgo_demo/demo/ttgo_demo.gif
Normal file
BIN
esp32/examples/ttgo_demo/demo/ttgo_demo.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.6 MiB |
@ -12,6 +12,7 @@
|
||||
#include <freertos/task.h>
|
||||
#include <esp_freertos_hooks.h>
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
|
||||
#include "system.h"
|
||||
#include "app_screen.h"
|
||||
@ -33,23 +34,37 @@ extern CEspLcd *tft;
|
||||
static lv_obj_t *lvCameraImage; // Camera image object
|
||||
|
||||
void gui_boot_screen() {
|
||||
lv_obj_t *scr = lv_disp_get_scr_act(nullptr);
|
||||
static lv_style_t style;
|
||||
lv_style_init(&style);
|
||||
|
||||
lv_obj_t *label1 = lv_label_create(scr, nullptr);
|
||||
lv_label_set_text(label1, "Hello World!");
|
||||
lv_obj_align(label1, nullptr, LV_ALIGN_CENTER, 0, 0);
|
||||
lv_style_set_radius(&style, LV_STATE_DEFAULT, 2);
|
||||
lv_style_set_bg_opa(&style, LV_STATE_DEFAULT, LV_OPA_COVER);
|
||||
lv_style_set_bg_color(&style, LV_STATE_DEFAULT, LV_COLOR_MAKE(190, 190, 190));
|
||||
lv_style_set_border_width(&style, LV_STATE_DEFAULT, 2);
|
||||
lv_style_set_border_color(&style, LV_STATE_DEFAULT, LV_COLOR_MAKE(142, 142, 142));
|
||||
|
||||
lv_style_set_pad_top(&style, LV_STATE_DEFAULT, 60);
|
||||
lv_style_set_pad_bottom(&style, LV_STATE_DEFAULT, 60);
|
||||
lv_style_set_pad_left(&style, LV_STATE_DEFAULT, 60);
|
||||
lv_style_set_pad_right(&style, LV_STATE_DEFAULT, 60);
|
||||
|
||||
lv_style_set_text_color(&style, LV_STATE_DEFAULT, LV_COLOR_MAKE(102, 102, 102));
|
||||
lv_style_set_text_letter_space(&style, LV_STATE_DEFAULT, 5);
|
||||
lv_style_set_text_line_space(&style, LV_STATE_DEFAULT, 20);
|
||||
|
||||
/*Create an object with the new style*/
|
||||
lv_obj_t * obj = lv_label_create(lv_scr_act(), NULL);
|
||||
lv_obj_add_style(obj, LV_LABEL_PART_MAIN, &style);
|
||||
lv_label_set_text(obj, "TTGO\n"
|
||||
"demo!");
|
||||
lv_obj_align(obj, NULL, LV_ALIGN_CENTER, 0, 0);
|
||||
wait_msec(3000);
|
||||
}
|
||||
|
||||
void gui_init() {
|
||||
// Create screen
|
||||
lv_obj_t *scr = lv_obj_create(nullptr, nullptr);
|
||||
lv_scr_load(scr);
|
||||
|
||||
// Init camera image Lvgl object
|
||||
lvCameraImage = lv_img_create(lv_disp_get_scr_act(nullptr), nullptr);
|
||||
lv_obj_set_hidden(lvCameraImage, true);
|
||||
lv_obj_move_foreground(lvCameraImage);
|
||||
}
|
||||
|
||||
esp_err_t updateCameraImage(const cv::Mat &img) {
|
||||
@ -80,16 +95,26 @@ esp_err_t updateCameraImage(const cv::Mat &img) {
|
||||
my_img_dsc.data_size = imgCopy.size().width * imgCopy.size().height;
|
||||
my_img_dsc.data = imgCopy.ptr<uchar>(0);
|
||||
|
||||
if(lv_obj_get_hidden(lvCameraImage))
|
||||
lv_obj_set_hidden(lvCameraImage, false);
|
||||
lv_obj_move_foreground(lvCameraImage);
|
||||
|
||||
lv_img_set_src(lvCameraImage, &my_img_dsc); /* Set the created file as image */
|
||||
lv_obj_set_pos(lvCameraImage, -40, 0);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
//#endif
|
||||
|
||||
// mode of the demo
|
||||
enum class DisplayMode : uint8_t {RGB, GRAYSCALE, BINARIZED, EDGES, NUM_OF_MODES};
|
||||
static DisplayMode currentDisplayMode;
|
||||
|
||||
static const std::string displayModeToString(DisplayMode dispMode) {
|
||||
const std::map<DisplayMode, const std::string> DisplayModeStrings {
|
||||
{DisplayMode::RGB, "RGB"},
|
||||
{DisplayMode::GRAYSCALE, "GRAYSCALE"},
|
||||
{DisplayMode::BINARIZED, "BINARIZED"},
|
||||
{DisplayMode::EDGES, "EDGES"},
|
||||
};
|
||||
auto it = DisplayModeStrings.find(dispMode);
|
||||
return (it == DisplayModeStrings.end()) ? "Out of range" : it->second;
|
||||
}
|
||||
|
||||
/**
|
||||
* Task doing the demo: Getting image from camera, processing it with opencv depending on the displayMode and
|
||||
@ -104,6 +129,10 @@ void demo_task(void *arg) {
|
||||
tft->setRotation(2); // rotation needed if camera is on the back of the device
|
||||
sensor_t *s = esp_camera_sensor_get();
|
||||
|
||||
// Init camera image Lvgl object
|
||||
lvCameraImage = lv_img_create(lv_disp_get_scr_act(nullptr), nullptr);
|
||||
lv_obj_move_foreground(lvCameraImage);
|
||||
|
||||
while(true) {
|
||||
auto start = esp_timer_get_time();
|
||||
|
||||
@ -119,10 +148,6 @@ void demo_task(void *arg) {
|
||||
}
|
||||
else { // RGB565 pixformat
|
||||
Mat inputImage(fb->height, fb->width, CV_8UC2, fb->buf); // rgb565 is 2 channels of 8-bit unsigned
|
||||
updateCameraImage(inputImage);
|
||||
|
||||
#if 0 // TODO: next step..
|
||||
Mat outputImage;
|
||||
|
||||
if(currentDisplayMode == DisplayMode::RGB) {
|
||||
}
|
||||
@ -150,16 +175,22 @@ void demo_task(void *arg) {
|
||||
ESP_LOGE(TAG, "Wrong display mode: %d", (int)currentDisplayMode);
|
||||
}
|
||||
|
||||
// Diplay image on LCD
|
||||
setImage(inputImage);
|
||||
#endif
|
||||
// display image on lcd
|
||||
updateCameraImage(inputImage);
|
||||
}
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "time taken: %lld ms", (esp_timer_get_time() - start) / 1000);
|
||||
ESP_LOGI(TAG, "%s mode: around %f fps", displayModeToString(currentDisplayMode).c_str(), 1.0f/((esp_timer_get_time() - start) / 1000000.0f));
|
||||
}
|
||||
}
|
||||
|
||||
wait_msec(25);
|
||||
lv_task_handler(); // tells LVGL to handle its tasks
|
||||
/**
|
||||
* Task changing the current displayMode at regular interval
|
||||
*/
|
||||
void timer_task(void *arg) {
|
||||
while(true) {
|
||||
wait_msec(3000);
|
||||
currentDisplayMode = static_cast<DisplayMode>((static_cast<int>(currentDisplayMode) + 1) % static_cast<int>(DisplayMode::NUM_OF_MODES));
|
||||
}
|
||||
}
|
||||
|
||||
@ -174,7 +205,6 @@ void app_main()
|
||||
|
||||
/* display boot screen */
|
||||
gui_boot_screen();
|
||||
wait_msec(1500);
|
||||
|
||||
/* Display memory infos */
|
||||
disp_infos();
|
||||
@ -183,4 +213,5 @@ void app_main()
|
||||
|
||||
/* Start the tasks */
|
||||
xTaskCreatePinnedToCore(demo_task, "demo", 1024 * 9, nullptr, 24, nullptr, 0);
|
||||
xTaskCreatePinnedToCore(timer_task, "timer", 1024 * 1, nullptr, 24, nullptr, 0);
|
||||
}
|
Reference in New Issue
Block a user