基于imx6ull平台opencv的图像采集和显示屏LCD显示功能(不带Qt界面)

目录

一、概述

本文档是针对imx6ull平台opencv的图像采集和显示屏LCD显示功能,opencv通过摄像头采集视频图像,将采集的视频图像送给显示屏LCD进行显示。

  • 测试结果如下图所示:

二、环境要求

2.1 硬件环境

  • 硬件:正点原子-I.MX6U ALPHA开发板
  • 摄像头:正点原子-OV5640单目摄像头
  • 显示屏:正点原子-4.3寸-800x480显示屏
  • 虚拟机:VMware

2.2 软件环境

  • Ubuntu系统要求:20.04
  • opencv版本: 4.7.0
  • 交叉工具链版本:交叉工具链版本:gcc-linaro-6.3.1-2017.05-x86_64_arm-linux-gnueabihf
  • 开发语言: C++

注意: 其中,需要有OV5640单目摄像头和4.3寸-800x480显示屏的驱动。

三、开发流程

关于imx6ull平台下opencv的移植及交叉编译器环境请参看:基于imx6ull开发板 移植opencv4.7.0

3.1 编写测试

选择一个目录,我这里选择的是opencv_lcd_imx6ull,创建一个opencv_lcd.cpp文件,内容如下:

cpp 复制代码
#include <opencv2/opencv.hpp>
#include <opencv2/videoio/videoio.hpp>
#include <opencv2/core/utils/logger.hpp>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <linux/fb.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>

/**** 静态全局变量 ****/
static int width;                       //LCD X分辨率
static int height;                      //LCD Y分辨率
static unsigned short *screen_base = NULL;        //映射后的显存基地址
static unsigned long line_length;       //LCD一行的长度(字节为单位)

using namespace std;
using namespace cv;
 
int main() {
    struct fb_fix_screeninfo fb_fix;
    struct fb_var_screeninfo fb_var;
    unsigned int screen_size;

    // 打开LCD设备
    int fb = open("/dev/fb0", O_RDWR);
    if (fb < 0) {
        perror("open fb0 failed");
        return -1;
    }

    /* 获取参数信息 */
    // 获取LCD屏幕信息
    if (ioctl(fb, FBIOGET_VSCREENINFO, &fb_var) < 0) {
        perror("ioctl FBIOGET_VSCREENINFO failed");
        return -1;
    }
 
    // 获取LCD帧缓冲区信息
    if (ioctl(fb, FBIOGET_FSCREENINFO, &fb_fix) < 0) {
        perror("ioctl FBIOGET_FSCREENINFO failed");
        return -1;
    }
    // 初始化OpenCV
    cv::utils::logging::setLogLevel(cv::utils::logging::LOG_LEVEL_SILENT);

    //括号内数字为1是调用usb摄像头,为0则是调用电脑自带摄像头
    cv::VideoCapture capture(1);
    unsigned short *screen_ptr = screen_base;

    // 设置摄像头的分辨率
    cv::Size resolution(800, 480);
    capture.set(cv::CAP_PROP_FRAME_WIDTH, resolution.width);
    capture.set(cv::CAP_PROP_FRAME_HEIGHT, resolution.height);

    // 加载预先训练好的人脸识别模型
    cv::CascadeClassifier faceCascade;
    faceCascade.load("haarcascade_frontalface_default.xml");

    // 将图像数据写入LCD屏幕
    screen_size = fb_fix.line_length * fb_var.yres;
    line_length = fb_fix.line_length;
    width = fb_var.xres;
    height = fb_var.yres;
    screen_base = mmap(NULL, screen_size, PROT_READ | PROT_WRITE, MAP_SHARED, fb, 0);
    if (MAP_FAILED == (void *)screen_base) {
        perror("mmap failed");
        return -1;
    }
    
    memset(screen_base, 0xFF, screen_size);
    unsigned short *fb_line_buf = NULL; //行缓冲区:用于存储写入到LCD显存的一行数据

    cv::Mat image;  //定义一个Mat变量,用于存储每一帧的图像
    capture >> image;  //读取当前帧
    printf("%d %d %d\r\n", image.cols, image.rows, image.channels());
    fb_line_buf = malloc(image.cols * 2);

    //【2】循环显示每一帧
	while(1)  
	{  
		// cv::Mat image;  //定义一个Mat变量,用于存储每一帧的图像
		capture >> image;  //读取当前帧
        // printf("%d %d %d\r\n", image.cols, image.rows, image.channels());
        screen_ptr = screen_base;
        if (image.empty()) continue; // 如果没有读取到帧,退出循环

        for (size_t y = 0; y < image.rows; y++)
        {
            char* row_ptr = image.ptr<char>(y);
            for (size_t x = 0; x < image.cols; ++x) {
                //这是获得像素数据数组的头指针,注意像素数据可能会有多个通道所以才需要用数组存储
                char* data_ptr = &row_ptr[x * image.channels()];
                // //对当前像素逐个通道输出颜色值
                // for (int i = 0; i < image.channels(); ++i) {
                //     cout << int(data_ptr[i])<<endl;
                // }
                // BGR888转为RGB565
                fb_line_buf[x] = ((data_ptr[2] & 0xF8) << 8) |
                    ((data_ptr[1] & 0xFC) << 3) |
                    ((data_ptr[0] & 0xF8) >> 3);
            }
            memcpy(screen_ptr, fb_line_buf, image.cols * 2);//将一行数据刷入显存
            screen_ptr += width;   //定位到显存下一行

        }
        
	}  

    // 解除内存映射
    munmap(screen_base, screen_size);
 
    // 关闭LCD设备
    close(fb);
 
    return 0;
}

opencv_lcd_imx6ull目录下,创建一个build_arm.sh文件,内容如下:

bash 复制代码
/tools/ToolsChain/nxp/imx6ull/gcc-linaro-6.3.1-2017.05-x86_64_arm-linux-gnueabihf/bin/arm-linux-gnueabihf-g++ opencv_lcd.cpp -o opencv_lcd \
-I /data/Workspace_Linux/software_lib/opencv-x.x.x/output/opencv-4.7.0/imx6ull/include/opencv4 \
-L /data/Workspace_Linux/software_lib/opencv-x.x.x/output/opencv-4.7.0/imx6ull/lib \
-lopencv_core -lopencv_highgui -lopencv_imgproc -lopencv_videoio -lopencv_imgcodecs -lopencv_face -lopencv_dnn  -lopencv_features2d -lopencv_flann -lopencv_calib3d -lopencv_objdetect \
-fpermissive

注意:

  • 交叉工具链:/tools/ToolsChain/nxp/imx6ull/gcc-linaro-6.3.1-2017.05-x86_64_arm-linux-gnueabihf/bin/arm-linux-gnueabihf-g++;
  • opencv头文件路径:/data/Workspace_Linux/software_lib/opencv-x.x.x/output/opencv-4.7.0/imx6ull/include/opencv4,开发者根据自己的路径进行配置;
  • opencv库路径:/data/Workspace_Linux/software_lib/opencv-x.x.x/output/opencv-4.7.0/imx6ull/lib,开发者根据自己的路径进行配置。

3.2 验证功能

  • 源码编译并上传
    opencv_lcd_imx6ull目录下,将build_arm.sh文件更改成可执行文件,并运行如下图所示:
bash 复制代码
./build_arm.sh

进入imx6ull开发板的/mnt/test_opencv目录下(若没有改目录则创建该目录),创建opencv_lcd目录,如下图所示:

opencv_lcd文件通过tfp上传到imx6ull开发板的/mnt/test_opencv/opencv_lcd目录下,如下图所示:

  • opencv库上传到imx6ull开发板
    进入/data/Workspace_Linux/software_lib/opencv-x.x.x/output/opencv-4.7.0/imx6ull目录下,将opencv库相关的内容进行打包,如下图所示:

    进入imx6ull开发板的/mnt/test_opencv目录下(若没有改目录则创建该目录),创建opencv目录,如下图所示:

    opencv.tar文件通过tfp上传到imx6ull开发板的/mnt/test_opencv/opencv目录下,如下图所示:

    进入imx6ull开发板的/mnt/test_opencv/opencv目录下,执行以下命令,将opencv.tar文件进行解压,如下图所示:
bash 复制代码
tar -xf opencv.tar
  • opencv库配置环境搭建

执行以下命令进行opencv库环境配置,如下图所示:

bash 复制代码
export LD_LIBRARY_PATH=/mnt/test_opencv/opencv/lib:$LD_LIBRARY_PATH
  • 运行应用程序

进入imx6ull开发板的/mnt/test_opencv/opencv_lcd目录下,更改opencv_lcd为可执行文件,并运行,运行结果如下:

最后,基于imx6ull平台opencv的图像采集和显示屏LCD显示功能验证完成了。

相关推荐
奔跑中的小象4 小时前
统信UOS + 天数AI卡部署SGLang服务手册
人工智能·uos·sglang·天数智芯
DevSecOps选型指南4 小时前
中国版Mythos,为何是悬镜安全灵脉CodeAI?
人工智能·安全
Shockang4 小时前
LangGraph 状态机实战
人工智能
刹那芳华19925 小时前
循环神经网络的从零开始实现(RNN)
人工智能·rnn·深度学习
阿童木写作5 小时前
跨境图片翻译工具多合一,批量图片视频字幕翻译加智能抠图
人工智能·python·音视频·语音识别
科技之门5 小时前
AI3D从建模到贴图、绑骨和动画的完整流程怎么做?V2Fun完整工作流指南
人工智能·3d·贴图
宇宙第一小趴菜5 小时前
二、机器学习的应用领域和发展史
人工智能·机器学习
前端开发江鸟5 小时前
我写过 MCP Server,却一直以为 MCP 只有 Tool
人工智能
天国梦5 小时前
自习室智能化升级避坑指南:天学网AI智习室方案实测与选型建议
大数据·人工智能
阿里云云原生6 小时前
可用性从 99.9% 跃升至 99.995%:畅捷通如何用 AI 重塑运维底座?
运维·网络·人工智能