IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 人工智能 -> orangepi-zero2实时显示USB摄像头图像 -> 正文阅读

[人工智能]orangepi-zero2实时显示USB摄像头图像

本文使用环境:
电脑:Ubuntu 18.04.5 LTS
开发板:orangepi-zero2
交叉编译器:aarch64-none-linux-gnu-
显示屏:openmv 1.8英寸SPI显示屏
显示屏资料:https://openmv.io/products/lcd-shield (128RMB,为什么会这么贵,搞不清楚

一、显示接口连接

1、显示屏接口:
SPI显示屏接口
2、开发板显示屏接口:
在这里插入图片描述
请添加图片描述
3、屏幕和开发板连接:

ZERO2LCD
CSSPI Chip Select
RESETLCD Reset
D/CSPI Command
SDI(MOSI)SPI Data in – to LCD
SCKSPI Clock
LEDBacklight Control
SDO(MISO)不接

4、扩展
??官方给出的开发板并没有外接显示电路,同时没有散热。不接散热,是不行的,在实际运行中温度太高了。所以就花了点时间设计了一版扩展板,有需要的可以自取,可以直接打样,使用的是立创EDA(可以免费打样的,需要的可以直接嘉立创一条龙)。支持国产,大家一起加油。
链接:
https://oshwhub.com/xiansenzhao/orangepi_copy
请添加图片描述

二、加载驱动设置

1、内核设置
??查找LCD所对应的驱动型号,本文使用的LCD驱动为:fb_st7735r(RGB585),内核中有该驱动所以可以直接使用驱动,不需要再单独编译驱动。
下图为编译内核时,驱动的位置。(默认是M,简而言之需要手动加载模块


    Device Drivers  --->  
    Graphics support  ---> 
       <*> Support for small TFT LCD display modules  --->
           ... //屏的驱动IC型号
           <M>   FB driver for the ILI9340 LCD Controller   //drivers/video/fbtft/fb_ili9340.c
           <M>   FB driver for the ST7735R LCD Controller  //drivers/video/fbtft/fb_st7735r.c
               ... 
           <M>   Module to for adding FBTFT devices      //drivers/video/fbtft/fbtft_device.c

2、加载驱动
??现在我们不直接加载,先看一下驱动文件在哪里,驱动名字是什么。在内核文件中找到对应的代码,文件路径如下:

kernel/orange-pi-4.9-sun50iw9/drivers/staging/fbtft/fbtft_devices.c

??部分代码如下:可以自己Ctrll+F查找关键字:fb_st7735r。对应的应该会有两个函数,这里只列出其中一个。

/* Supported displays in alphabetical order */
static struct fbtft_device_display displays[] = {
		.name = "adafruit18",
		.spi = &(struct spi_board_info) {
			.modalias = "fb_st7735r",
			.max_speed_hz = 32000000,
			.mode = SPI_MODE_0,
			.platform_data = &(struct fbtft_platform_data) {
				.display = {
					.buswidth = 8,
					.backlight = 1,
				},
				.gpios = (const struct fbtft_gpio []) {
					{ "reset", 25 },
					{ "dc", 24 },
					{ "led", 18 },
					{},
				},
				.gamma = ADAFRUIT18_GAMMA,
			}
		}
	},

??可以很明显的看出:fb_st7735r为本文所用LCD的驱动,那就意味着可以直接使用。尝试着手动加载驱动试一下:
??直接登录系统。输如如下代码:

modprobe fbtft_device custom name=adafruit18  busnum=1 cs=1 gpios=reset:73,dc:70,led:69 rotate=90

busnum:表示使用SPI1,硬件接线使用的就是SPI1。
后面的就是字面意思了,GPIO的引脚对应其功能。

注意:官方的教程中的加载驱动模块代码,是不能直接使用的,会出现显示模糊的情况,经过我多方排除,我发现是时钟频率不对,使用驱动中默认的就好了,不需要修改。

??输入以下代码后,就应该可以在/dev/下看到对应的设备了:(系统默认带有fb0),所以加载后本文所用LCD就是:fb1。
请添加图片描述
??只要出现fb1,说明LCD加载成功了。接下来让系统启动自动加载驱动。

a、新建文件 /etc/modules-load.d/fbtft.con 配置文件,文件内容如下:

fbtft_device

b、新建 /etc/modprobe.d/fbtft.conf 配置文件,文件内容如下所示:

options fbtft_device custom name=adafruit18  busnum=1 cs=1 gpios=reset:73,dc:70,led:69 rotate=90

重启开发板就能实现LCD的自动加载。
3、显示测试
??测试LCD是否可以显示,由于本文所有的LCD和官方给的LCD并不匹配,所以显示会出现分辨率的问题,但是不影响使用。
输入使用如下代码:

apt -y install fbi
fbi -vt 1 -noverbose -d /dev/fb1 /boot/boot.bmp

显示如下:
请添加图片描述
如果出现上图的情况说明已经成功了。

三、 USB摄像头数据实时显示

??说明:本文目前使用的是最简单的一种视频读取方式:OPENCV读取,也就意味着必须要安装相对应的opencv库,否则不能运行。
写文章还是不容易的,一个知识点牵涉着另外的知识点,opencv的交叉编译又可以单独写一篇文章了。除了opencv还有另外的一种是读取方式,就是直接open设备,这种方式倒是不需要其他库就是麻烦一点点,采集的数据是YUV,需要转化成RGB565,还需要resize成显示屏的尺寸,因为显示屏是128X160的。。而采集的视频是640X480的,这一下又是两篇文章了。。。。。。。不说了我们继续本章的话题,后面有时间再写吧

1、安装OPENCV的库,懒得交叉编译了,因为很麻烦,我们直接采用现成的库。。。。
感谢qiuiqiu大佬的贡献。
https://github.com/dog-qiuqiu/libopencv
从上诉链接下载opencv的交叉库,下载完后打开如下所示:
请添加图片描述
注意教程使用的是aarch64,所以只使用aarch64-linux-gnu文件夹下的库。
将文件夹改名为:(不改也可以其实。。为了方便识别)
aarch64-linux-gnu-opencv4.5

2、编程
a、程序如下:
??需要注意的就是LCD是RGB565的,而采集出来的视频RGB888。需要转化一下。

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <linux/fb.h>
#include <sys/mman.h>
#include <stdio.h>
#include <string.h>
#define CV_AA 8
#include <opencv2/opencv.hpp>

using namespace cv;
using namespace std;

//RGB888转化成RGB565
#define RGB2RGB565(R,G,B) ((((R)>>3)<<11)|(((G)>>2)<<5)|((B)>>3))&0XFFFF
//显示函数,
static void display_pic(void *base,unsigned int width, unsigned int height, unsigned int stride, Mat frame)
{
	unsigned int xcoi, ycoi;
    unsigned short rgb565_color = 0;
    unsigned short  R, G, B;
	unsigned int iPixelAddr = 0;
    Mat pic_resize;

    unsigned short *screen_base = (unsigned short *)base;

    resize(frame,pic_resize,Size(160,128),INTER_LANCZOS4);调整大小
    unsigned int num=0;


	for(ycoi = 0; ycoi < height; ycoi++)
	{
		for(xcoi = 0; xcoi < width; xcoi += 1)
		{
            int i = xcoi+ycoi*width;

                B = pic_resize.data[3*i];
                G = pic_resize.data[3*i+1];
                R = pic_resize.data[3*i+2];
                rgb565_color = RGB2RGB565(R,G,B);
            
            screen_base[i] = rgb565_color;

		}
		iPixelAddr += width*2;
	}
}

int testCam() {

	cv::Mat frame;    
	cv::VideoCapture cap(0);

    struct fb_var_screeninfo fb_var = {0};
	struct fb_fix_screeninfo fb_fix = {0};
	unsigned int screensize;
	int fd;
	static void *base = NULL;

	// 打开LCD 
	fd = open("/dev/fb1", O_RDWR);
	if (fd < 0) {
		printf("Error: Failed to open /dev/fb0 device.\n");
		return fd;
	}

	// 获取framebuffer设备的参数信息 
	ioctl(fd, FBIOGET_VSCREENINFO, &fb_var);
	ioctl(fd, FBIOGET_FSCREENINFO, &fb_fix);

	// mmap映射 
	screensize = fb_var.yres* fb_fix.line_length;
	printf("lie: %d   hang:  %d   %d   %d\n",fb_var.yres,fb_var.xres,fb_fix.line_length,fb_var.bits_per_pixel);
	base = mmap(NULL, screensize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
	if (MAP_FAILED == base) {
		close(fd);
		perror("mmap error");
		return -1;
	}

	memset(base, 0x00, screensize);		// 显存清零
    while (true) {
        cap >> frame;
        if (frame.empty()) break; //如果某帧为空则退出循环

        display_pic( base,fb_var.xres, fb_var.yres, fb_fix.line_length,frame);
    }

    cap.release();//释放资源
    	//关闭设备 释放内存 
	memset(base, 0x00, screensize);
	munmap(base, screensize);
	close(fd);
    return 0;
}

int main() {
    testCam();
    return 0;
}

b、编写makefil文件:
??库的路径和交叉编译器的路径需要根据实际情况修改。

TARGET=lcd-main
EXEC= obj-m

LIBARY= -lopencv_world -llibprotobuf -llibjpeg-turbo -llibwebp -llibpng -llibtiff -llibopenjp2 -lzlib -littnotify -ltegra_hal -lquirc -lade -ldl -lm -lpthread -lrt
LDFLAGS= -L /home/zxx/orange_project/libopencv-main/aarch64-linux-gnu/lib/ $(LIBARY) 
COMMON+= -I /home/zxx/orange_project/libopencv-main/aarch64-linux-gnu/include/
CC :=aarch64-none-linux-gnu-g++
SRC = ldc_opencv.cpp 

OBJS = $(SRC:%.c=%.o)

all:$(OBJS)
	$(CC) -o $(TARGET) $(SRC) $(COMMON) $(LDFLAGS) -fopenmp
clean :
	rm -rf *.o
	rm -rf lcd-main

c、直接make
会生成lcd-main可执行文件。将文件scp到开发板。

scp lcd-main root@192.168.1.213:/zxx/lcd_show

d、运行程序
??如图:

root@orangepizero2:/zxx/lcd_show# ./lcd-main
lie: 128   hang:  160   320   16

实际效果:
请添加图片描述
??到此本文全部结束。后期还会出使用open进行usb数据采集的教程,感兴趣的可以继续关注一下。

  人工智能 最新文章
2022吴恩达机器学习课程——第二课(神经网
第十五章 规则学习
FixMatch: Simplifying Semi-Supervised Le
数据挖掘Java——Kmeans算法的实现
大脑皮层的分割方法
【翻译】GPT-3是如何工作的
论文笔记:TEACHTEXT: CrossModal Generaliz
python从零学(六)
详解Python 3.x 导入(import)
【答读者问27】backtrader不支持最新版本的
上一篇文章      下一篇文章      查看所有文章
加:2021-08-14 14:01:52  更:2021-08-14 14:02:11 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/27 21:03:19-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码