【EPS32S3学习笔记】ESP32+OPENCV+OV2640+LVGL

系列文章目录

提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加
例如:第一章 Python 机器学习入门之pandas的使用


提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

提示:这里可以添加本文要记录的大概内容:

前面已经完成了ESP32S3+LVGL+OV2640的工作,下一步就可以在这个基础上去增加OPENCV的模块了。
源代码还是用的GitHub上的:
esp32-opencv


提示:以下是本篇文章正文内容,下面案例可供参考

一、将OPENCV添加到工程

根据开源作者的描述,有三种方法。一个是直接用编译好的库,直接使用。再一个是利用写好的.sh文件重新编译一下,生成库,然后使用。第三种就是所有的命令一步步来。咱们就不用多想了直接使用编译好的库。

Faster way:
The first way is to simply get the pre-built OpenCV library in esp32/lib/ folder, and copy it into your project (see Compiling-esp-idf-project-using-opencv)

Fast way:
The second way is by using the script in build_opencv_for_esp32.sh. This script automatically compiles OpenCV from this repository sources, and install the needed files into the desired project. It can be tweaked as needed to add and remove some parts (see esp32/doc/build_configurations.md).

The script has 2 arguments. The first is the path to the toolchain-esp32.cmake (default is $HOME/esp/esp-idf/tools/cmake/toolchain-esp32.cmake), and the second is the path where the OpenCV library is installed (default is in ./esp32/lib).

Detailed way:
The last way explains all the commands and modifications done to be able to compile and run OpenCV on the ESP32. The detailed procedure is in esp32/doc/detailed_build_procedure.md.

由于我对cmake文件这些还不了解,直接按照提供的方法,把生成的库放到main文件夹下,修改CMakeList.txt。就可以直接编译通过了。

二、解决 undefined reference to sysconf 错误

编译好之后,如果调用例程,就会出现这样的提示。这个问题好像是因为获取内核数量的一个方法出现的异常,可能ESP32相关的支持还没有完善起来。这里说按照如下修改即可,但是查看下载后的源码其实都已经是修改好的,另外可能其他位置在编译的时候也会报错。

parallel.cpp:949:58: undefined reference to sysconf

This error appeared while trying to use the canny() method of the imgproc module

Fix: Modify modules/core/src/parallel.cpp

Change the line 947 in

#if !defined(_WIN32) && !defined(__APPLE__) && !defined(ESP32)
unsigned ncpus = std::thread::hardware_concurrency(); /* If the value is not well defined or not computable, returns 0 */

所以简单一点直接将相关代码删除,然后返回0即可。

这样修改完,通过上面的方法 build_opencv_for_esp32.sh可以再次编译,然后生成新的库文件。

三、生成新的Opencv库文件

这里也做了一些改动,考虑到原来的库是基于ESP32的,而且是IDF较早的版本。所以就考虑换成ESP32S3的,用最新的IDF版本,这样跟工程更贴近一点。
过程比较简单:
1、复制Opencv目录下的ESP32文件,改名字为ESP32S3;
2、 build_opencv_for_esp32.sh改名字 build_opencv_for_esp32s3.sh;
3、修改此文件的内容:仅修改CMAKE_PATH即可,其他都不用,CMAKE里面的参数也不用了。
4、运行这个bash文件,如果出现错误会有提示,全部结束后在lib文件夹下就有新的库文件了。

# path to the cmake file containing the toolchain informations
TOOLCHAIN_CMAKE_PATH=$HOME/esp/esp-idf/tools/cmake/toolchain-esp32s3.cmake

这个过程是在linux环境下进行的,没有搭建环境的,可以按照下面的StartGuide进行。
docs.espressif.com

四、添加TTGO示例

需要注意的是opencv库是C++环境下使用的,在之前工程里的c文件是不能直接使用的。当然也可以重新将使用OPENCV的文件切换成c++的模式,不过C++早都忘差不多了,一时半会捡不起来。用老方法,做一个中间件,将其中的方法抽离出来,通过接口调用。
在这里插入图片描述
main目录下新建opencvMid文件夹,里面新增imgProcess.cpp和imgProcess.h文件。
imgProcess.cpp文件源文件如下:


#include "imgProcess.h"

#undef EPS // specreg.h defines EPS which interfere with opencv
#include "opencv2/core.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/imgcodecs.hpp"
#define EPS 192

#define ESP32

#ifdef __cplusplus
extern "C"
{
    
    
#endif

#include "esp_system.h"
#include <esp_log.h>

#define TAG "OPENCV"


using namespace cv;


uint32_t imgProcess(int height, int width, void *pBuf, char ucMode)
{
    
    

    Mat inputImage(height, width, CV_8UC2, pBuf); // rgb565 is 2 channels of 8-bit unsigned
    static Mat imageCopy;

    if(inputImage.empty()) {
    
    
        ESP_LOGW(TAG, "Can't display empty image");
        return 0;
    }

    if (ucMode == 0)
    {
    
    

    }
    else if (ucMode == 1)
    {
    
    
        cvtColor(inputImage, inputImage, COLOR_BGR5652GRAY);
    }
    else if (ucMode == 2)
    {
    
    
        cvtColor(inputImage, inputImage, COLOR_BGR5652GRAY);
        threshold(inputImage, inputImage, 128, 255, THRESH_BINARY);
    }
    else if (ucMode == 3)
    {
    
    
        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);
    }

    if(inputImage.type() == CV_8UC1) {
    
             // grayscale image
        cvtColor(inputImage, imageCopy, COLOR_GRAY2BGR565, 1);
    }
    else if(inputImage.type() == CV_8UC3) {
    
        // BGR888 image
        cvtColor(inputImage, imageCopy, COLOR_BGR2BGR565, 1);
    }
    else if(inputImage.type() == CV_8UC2) {
    
        // BGR565 image
        inputImage.copyTo(imageCopy);
    }

    return (uint32_t)(imageCopy.ptr<uchar>(0));

}
#ifdef __cplusplus
}
#endif

这里主要是实现了一个接口,imgProcess,输入参数为图像的长宽参数,源图像数据缓存,转换的模式。返回的是转换后的图像缓存的地址。

        ESP_LOGI(TAG, "Taking picture...");
        pic = esp_camera_fb_get();

        usCounter++;  

        my_img_dsc.data = (uint8_t *)imgProcess(240,320,(void *)(pic->buf),(usCounter++ / 100) % 4);

        GucFlag = 1;

        ESP_LOGI(TAG, "Picture taken! Its size was: %zu bytes", pic->len);
        ESP_LOGI(TAG, "W: %d H:%d format:%d", pic->width,pic->height,pic->format);
        esp_camera_fb_return(pic);

这样在camera获取图像之后,通过imgProcess得到转换后得图像数据地址,赋值给lvgl图片变量得数据地址参数。后面图像刷新得时候,在屏幕上就显示新的图像了。

ESP32S3+LVGL+OV2640+OPENCV


总结

提示:这里对文章进行总结:

感谢大家的支持。

猜你喜欢

转载自blog.csdn.net/lunzilx/article/details/129163671