mirror of
https://gitcode.com/gh_mirrors/es/esp32-opencv.git
synced 2025-08-06 18:24:38 +08:00
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:
@ -30,6 +30,67 @@ void app_main(void);
|
||||
|
||||
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
|
||||
* displaying it on the lcd
|
||||
@ -40,6 +101,9 @@ void demo_task(void *arg) {
|
||||
// Display memory 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) {
|
||||
auto start = esp_timer_get_time();
|
||||
|
||||
@ -48,50 +112,54 @@ void demo_task(void *arg) {
|
||||
if (!fb) {
|
||||
ESP_LOGE(TAG, "Camera capture failed");
|
||||
} else {
|
||||
TFT_jpg_image(CENTER, CENTER, 0, -1, NULL, fb->buf, fb->len);
|
||||
esp_camera_fb_return(fb);
|
||||
fb = NULL;
|
||||
if(s->pixformat == PIXFORMAT_JPEG) {
|
||||
TFT_jpg_image(CENTER, CENTER, 0, -1, NULL, fb->buf, fb->len);
|
||||
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);
|
||||
|
||||
#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);
|
||||
lv_task_handler(); // tells LVGL to handle its tasks
|
||||
}
|
||||
}
|
||||
|
||||
@ -102,6 +170,11 @@ void app_main()
|
||||
/* initializations */
|
||||
app_camera_init();
|
||||
lvgl_init();
|
||||
gui_init();
|
||||
|
||||
/* display boot screen */
|
||||
gui_boot_screen();
|
||||
wait_msec(1500);
|
||||
|
||||
/* Display memory infos */
|
||||
disp_infos();
|
||||
|
Reference in New Issue
Block a user