First working version of the OpenCV demo

- Getting the camera image
- Creating an OpenCV Mat object with it
- Creating an lv_img_dsc_t LVGL object
- Displaying it on the screen
This commit is contained in:
Joachim
2020-08-27 16:56:46 +02:00
parent 4b50a9055d
commit 5aa5363672

View File

@ -30,6 +30,67 @@ void app_main(void);
extern CEspLcd *tft; 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);
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);
}
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) {
// static variables because they must still be available when lv_task_handler() is called
static Mat imgCopy;
static lv_img_dsc_t my_img_dsc;
if(img.empty()) {
ESP_LOGW(TAG, "Can't display empty image");
return ESP_ERR_INVALID_ARG;
}
// convert image to bgr565 if needed
if(img.type() == CV_8UC1) { // grayscale image
cvtColor(img, imgCopy, COLOR_GRAY2BGR565, 1);
}
else if(img.type() == CV_8UC3) { // BGR888 image
cvtColor(img, imgCopy, COLOR_BGR2BGR565, 1);
}
else if(img.type() == CV_8UC2) { // BGR565 image
img.copyTo(imgCopy);
}
my_img_dsc.header.always_zero = 0;
my_img_dsc.header.w = imgCopy.cols;
my_img_dsc.header.h = imgCopy.rows;
my_img_dsc.header.cf = LV_IMG_CF_TRUE_COLOR;
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
/** /**
* Task doing the demo: Getting image from camera, processing it with opencv depending on the displayMode and * Task doing the demo: Getting image from camera, processing it with opencv depending on the displayMode and
* displaying it on the lcd * displaying it on the lcd
@ -40,6 +101,9 @@ void demo_task(void *arg) {
// Display memory infos // Display memory infos
disp_infos(); disp_infos();
tft->setRotation(2); // rotation needed if camera is on the back of the device
sensor_t *s = esp_camera_sensor_get();
while(true) { while(true) {
auto start = esp_timer_get_time(); auto start = esp_timer_get_time();
@ -48,50 +112,54 @@ void demo_task(void *arg) {
if (!fb) { if (!fb) {
ESP_LOGE(TAG, "Camera capture failed"); ESP_LOGE(TAG, "Camera capture failed");
} else { } else {
TFT_jpg_image(CENTER, CENTER, 0, -1, NULL, fb->buf, fb->len); if(s->pixformat == PIXFORMAT_JPEG) {
esp_camera_fb_return(fb); TFT_jpg_image(CENTER, CENTER, 0, -1, NULL, fb->buf, fb->len);
fb = NULL; esp_camera_fb_return(fb);
fb = NULL;
}
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) {
}
else if(currentDisplayMode == DisplayMode::GRAYSCALE) {
cvtColor(inputImage, inputImage, COLOR_BGR5652GRAY);
}
else if(currentDisplayMode == DisplayMode::BINARIZED) {
cvtColor(inputImage, inputImage, COLOR_BGR5652GRAY);
threshold(inputImage, inputImage, 128, 255, THRESH_BINARY);
}
else if(currentDisplayMode == DisplayMode::EDGES) {
cvtColor(inputImage, inputImage, COLOR_BGR5652GRAY);
// Reduce noise with a kernel 3x3
blur(inputImage, inputImage, Size(3, 3));
/** Apply the canny edges detector with:
* - low threshold = 50
* - high threshold = 4x low
* - sobel kernel size = 3x3
*/
int lowThresh = 40;
int kernSize = 3;
Canny(inputImage, inputImage, lowThresh, 4 * lowThresh, kernSize);
}
else {
ESP_LOGE(TAG, "Wrong display mode: %d", (int)currentDisplayMode);
}
// Diplay image on LCD
setImage(inputImage);
#endif
}
} }
ESP_LOGI(TAG, "time taken: %lld ms", (esp_timer_get_time() - start) / 1000); ESP_LOGI(TAG, "time taken: %lld ms", (esp_timer_get_time() - start) / 1000);
#if 0 // TODO: next step..
Mat inputImage(fb->height, fb->width, CV_8UC2, fb->buf); // rgb565 is 2 channels of 8-bit unsigned
Mat outputImage;
if(currentDisplayMode == DisplayMode::RGB) {
}
else if(currentDisplayMode == DisplayMode::GRAYSCALE) {
cvtColor(inputImage, inputImage, COLOR_BGR5652GRAY);
}
else if(currentDisplayMode == DisplayMode::BINARIZED) {
cvtColor(inputImage, inputImage, COLOR_BGR5652GRAY);
threshold(inputImage, inputImage, 128, 255, THRESH_BINARY);
}
else if(currentDisplayMode == DisplayMode::EDGES) {
cvtColor(inputImage, inputImage, COLOR_BGR5652GRAY);
// Reduce noise with a kernel 3x3
blur(inputImage, inputImage, Size(3, 3));
/** Apply the canny edges detector with:
* - low threshold = 50
* - high threshold = 4x low
* - sobel kernel size = 3x3
*/
int lowThresh = 40;
int kernSize = 3;
Canny(inputImage, inputImage, lowThresh, 4 * lowThresh, kernSize);
}
else {
ESP_LOGE(TAG, "Wrong display mode: %d", (int)currentDisplayMode);
}
// Diplay image on LCD
setImage(inputImage);
#endif
wait_msec(25); wait_msec(25);
lv_task_handler(); // tells LVGL to handle its tasks
} }
} }
@ -102,6 +170,11 @@ void app_main()
/* initializations */ /* initializations */
app_camera_init(); app_camera_init();
lvgl_init(); lvgl_init();
gui_init();
/* display boot screen */
gui_boot_screen();
wait_msec(1500);
/* Display memory infos */ /* Display memory infos */
disp_infos(); disp_infos();