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

news2024/9/20 22:50:32

目录

  • 一、概述
  • 二、环境要求
    • 2.1 硬件环境
    • 2.2 软件环境
  • 三、开发流程
    • 3.1 编写测试
    • 3.2 验证功能

一、概述

本文档是针对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文件,内容如下:

#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文件,内容如下:

/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文件更改成可执行文件,并运行如下图所示:
./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文件进行解压,如下图所示:
tar -xf opencv.tar

在这里插入图片描述

  • opencv库配置环境搭建

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

export LD_LIBRARY_PATH=/mnt/test_opencv/opencv/lib:$LD_LIBRARY_PATH

在这里插入图片描述

  • 运行应用程序

进入imx6ull开发板的/mnt/test_opencv/opencv_lcd目录下,更改opencv_lcd为可执行文件,并运行,运行结果如下:
在这里插入图片描述
在这里插入图片描述
最后,基于imx6ull平台opencv的图像采集和显示屏LCD显示功能验证完成了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2075401.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

OpenFeign服务的接口调用

为了保障文章的流畅性&#xff08;文章穿插大量的环境搭建没意思&#xff0c;会干扰文章的主题&#xff0c;无聊的很&#xff09;&#xff0c;将环境的搭建与测试&#xff0c;工具的版本说明放了文末&#xff1a; 四、环境搭建。 一、概述 1.1、官网 Feign 是一个声明式 Web…

Linux系统——服务器长时间训练不间断指令(nohup的简单用法)

Linux服务器训练中nohup的用法 在模型训练过程中&#xff0c;许多人选择在服务器上运行代码&#xff0c;而大多数服务器运行在Linux环境下。通常情况下&#xff0c;我们可以直接在Linux终端中使用如下命令来启动训练代码&#xff08;以运行main.py为例&#xff09;。 python …

【Opencv】一文向您详细介绍 `Mat::ptr()` 函数

【Opencv】一文向您详细介绍 Mat::ptr() 函数 下滑即可查看博客内容 &#x1f308; 欢迎莅临我的个人主页 &#x1f448;这里是我静心耕耘深度学习领域、真诚分享知识与智慧的小天地&#xff01;&#x1f387; &#x1f393; 博主简介&#xff1a;985高校的普通本硕&#xf…

【原创教程】电气电工11:伺服接线

电气电工这些知识点,我们描述的比较细,虽然看起来比较简单,但是它是后面我们技能提升的基础,如果我们后面学电气工程师相关知识,这些都属于基本功。 接着我们来看一下伺服接线 伺服,英文servo(来源希腊,意为仆人)。在工业现场,由我们给伺服系统发送一个控制指令,然…

数据结构(邓俊辉)学习笔记】串 04——KMP算法:查询表

文章目录 1.制表备查2.主算法3.实例 1.制表备查 接下来我们来看看。KMP 算法究竟如何兑现我们刚才所提及的记忆力以及预知力&#xff0c;我们将会看到这种方法非常的便捷与高效&#xff0c;本质上讲&#xff0c;它无非就是构造了一张查询表。 回到我们刚才的问题&#xff0c;在…

Windows中pycharm使用虚拟环境不显示虚拟环境的名也不出现base

出现下图情况 一、修改shell path 二、环境变量中加入condabin 三、如果上述还不行&#xff0c;初始化conda再进行一、二、操作 最终进入了我创建的虚拟环境b中

【html+css 绚丽Loading】000017 三元轮转镜

前言&#xff1a;哈喽&#xff0c;大家好&#xff0c;今天给大家分享htmlcss 绚丽Loading&#xff01;并提供具体代码帮助大家深入理解&#xff0c;彻底掌握&#xff01;创作不易&#xff0c;如果能帮助到大家或者给大家一些灵感和启发&#xff0c;欢迎收藏关注哦 &#x1f495…

VCTP(Visual Chain-of-Thought Prompting for Knowledge-Based Visual Reasoning)论文

目录 摘要介绍相关工作方法总体模型细节 实验 摘要 知识型视觉推理仍然是一个艰巨的任务&#xff0c;因为它不仅要求机器从视觉场景中解释概念和关系&#xff0c;而且还需要将它们与外部世界知识联系起来&#xff0c;对开放世界问题进行推理链。然而&#xff0c;以前的工作将视…

论文文献翻译怎么做?快又准的外文文献翻译软件帮你搞定

平时我们查阅文献通常都是将其翻译成中文&#xff0c;方便更高效和准确地理解和阅读&#xff1b;但对于不少留学生而言&#xff0c;如何把文献翻译成英文也是他们需要解决的一大硬茬~ 今天就给大家盘点了4个能够把文献翻译成英文的实用小技巧&#xff0c;有需要的小伙伴可别错…

PicHoro v2.4.0 — 强大的图床管理,可导入PicGo配置

PicHoro是一款基于Flutter开发的手机端云存储平台&#xff0c;支持多种云存储服务和图床&#xff0c;提供便捷的文件管理和分享功能。兼容多种云存储和图床平台&#xff0c;包括Webdav、Alist、SSH/SFTP、S3 API、腾讯云COS、阿里云OSS、七牛云、又拍云、Imgur、SM.MS以及Githu…

Java基础入门20:特殊文件、日志技术、多线程、网络通信

特殊文件 properties属性文件 Properties是一个Mp集合&#xff08;键值对集合&#xff09;&#xff0c;但是我们一般不会当集合使用。 核心作用&#xff1a;Properties是用来代表属性文件的&#xff0c;通过Properties可以读写属性文件里的内容。 使用Properties把键值对数…

【STM32】电容触摸按键

电容按键就是酷&#xff0c;但据我使用过电容按键版的洗澡计费机子后&#xff0c;一生黑&#xff08;湿手优化没做好的电容按键简直稀碎&#xff09;。 大部分图片来源&#xff1a;正点原子HAL库课程 专栏目录&#xff1a;记录自己的嵌入式学习之路-CSDN博客 目录 1 触摸按…

IPv4和IPv6的区别是什么?什么是局域网和广域网,公网IP和私有IP?

文章目录 1.基本网络2.局域网3.广域网4.IPv4与NAT5.公网IP和私有IP6.IPv6 1.基本网络 我们都知道计算机的数据都是存在各自硬盘中的,与其他计算机之间没有人任务关系. 假设计算机A需要给计算机B发送数据,可以选择使用U盘这类移动存储数据来拷贝数据来实现数据交互,但是这样一…

惊艳开源界!20.6K+星标瞩目,打造高性能LLM(大型语言模型)应用的开发平台

项目简介 Dify 是一个开源的LLM&#xff08;大型语言模型&#xff09;应用开发平台&#xff0c;它通过直观的界面结合了AI工作流程、RAG&#xff08;检索-分析-生成&#xff09;管道、代理功能、模型管理、可观察性特性等&#xff0c;使用户能够快速从原型设计转向产品生产。 …

一起搭WPF之列表数据绑定

一起搭WPF之列表数据绑定 1 前言2 数据绑定2.1 前端2.2 后端实现2.2.1 界面后台2.2.2 模型与逻辑 3 问题3.2 解决 总结 1 前言 之前已经简单介绍了列表的大致设计&#xff0c;在设计完列表界面后&#xff0c;我们可以开展列表的数据绑定&#xff0c;在前端显示我们的数据&…

【问题处理】前端Vue项目遇到的一些问题及处理方式

每次新整一个项目的时候&#xff0c;开端总是会遇到各种奇奇怪怪的问题&#xff0c;一步一坎的感觉&#xff0c;但是没关系&#xff0c;遇到了就一步一步去解决&#xff0c;当把所有问题都处理后&#xff0c;成功运行起来&#xff0c;就会突然很有成就感&#xff0c;一切都是那…

大模型嵌入向量Embeddings

版权声明 本文原创作者:谷哥的小弟作者博客地址:http://blog.csdn.net/lfdfhlEmbeddings概述 嵌入(Embeddings)概述 基本概念 嵌入,或称为Embeddings,在机器学习领域中扮演着至关重要的角色。它是一种将离散数据元素,如文本中的单词或图像中的像素点,映射到连续的向量…

虹科方案 | 疫苗冷链温度监测解决方案

通过WHO PQS标准的支持和稳定性预算的应用&#xff0c;我们可以更好地保障疫苗在全球范围内的安全运输和储存&#xff0c;接下来让我们了解一下既能计算药品剩余稳定性预算&#xff0c;又符合WHO PQS预认证的疫苗冷链温度监测解决方案。 疫苗冷链温度监测解决方案 根据WHO和《…

dpdk解析报文协议-基于l2fwd

dpdk解析报文协议-基于l2fwd 0 前置条件 1、这里需要两台虚拟机&#xff0c;配置了相同的虚拟网络&#xff0c;可以通过tcpreplay在一台虚拟机回放报文&#xff0c;在另一台虚拟机通过tcpdump -i 网卡名 捕获到。 具体配置可参考https://www.jb51.net/server/2946942fw.htm 2…

IP SSL:最快捷的安全证书

在这个数字化时代&#xff0c;企业面临着前所未有的挑战——如何在保证业务高效运行的同时保护其核心资产免受网络威胁。随着网络安全事件频发&#xff0c;企业和个人对数据安全的关注度达到了前所未有的高度。在此背景下&#xff0c;IP SSL&#xff08;Internet Protocol Secu…