基于GEC6818的嵌入式智能监控系统设计

 

一、主要功能:

(1)当进入监控操作界面后,先是解锁界面,解锁后点击选项进入后,有四个功能按钮模块,分别是:监控(打开摄像头)、录制、播放(显示已经拍的视频)、抓拍、退出(退回到主界面)。

二、详细设计

嵌入式开发板型号GEC6818,开发平台Ubuntu。

1,摄像头模块;

在Linux系统下采集摄像头数据,需要用到V4l2的API接口  摄像头的采集的视频画面:是由一帧一帧的数据组合在一起帧格式: mjpeg  yuyv  rgb  yuv   帧的原始格式由摄像头厂家编写的,此时需要调用V4l2 API进行代码的编写Video for Linuxtwo(Video4Linux2)简称V4L2,是V4L的改进版。V4L2是linux操作系统下用于采集图片、视频和音频数据的API接口,配合适当的视频采集设备和相应的驱动程序,可以实现图片、视频、音频等的采集。在远程会议、可视电话、视频监控系统和嵌入式多媒体终端中都有广泛的应用。在Linux下,所有外设都被看成一种特殊的文件,成为“设备文件”,可以象访问普通文件一样对其进行读写。一般来说,采用V4L2驱动的摄像头设备文件是/dev/video7。V4L2支持两种方式来采集图像:内存映射方式(mmap)和直接读取方式(read)。V4L2在include/linux/videodev.h文件中定义了一些重要的数据结构,在采集图像的过程中,就是通过对这些数据的操作来获得最终的图像数据。应用程序通过V4L2进行视频采集的原理V4L2支持内存映射方式(mmap)和直接读取方式(read)来采集数据,前者一般用于连续视频数据的采集,后者常用于静态图片数据的采集,本文重点讨论内存映射方式的视频采集。应用程序通过V4L2接口采集视频数据分为五个步骤:

首先,打开视频设备文件,进行视频采集的参数初始化,通过V4L2接口设置视频图像的采集窗口、采集的点阵大小和格式;

其次,申请若干视频采集的帧缓冲区,并将这些帧缓冲区从内核空间映射到用户空间,便于应用程序读取/处理视频数据;

第三,将申请到的帧缓冲区在视频采集输入队列排队,并启动视频采集;

第四,驱动开始视频数据的采集,应用程序从视频采集输出队列取出帧缓冲区,处理完后,将帧缓冲区重新放入视频采集输入队列,循环往复采集连续的视频数据;

第五,停止视频采集。

用户工作流程:

打开设备-> 检查和设置设备属性->设置帧格式-> 设置一种输入输出方法(缓冲区管理)-> 循环获取数据-> 关闭设备。

#include    	//printf scanf
#include 		//open write read lseek close  	 
#include 
#include 
#include 
#include 
#include 
#include "jpeg.h"
#include "camera.h"
#include "api_v4l2.h"
#include "jpeglib.h"


static unsigned char g_color_buf[FB_SIZE]={0};

int ts_x, ts_y;
int flag = 1;

int  lcd_fd;
int *mmap_fd;
struct jpg_data video_buf;//定义结构体变量

//初始化LCD
int lcd_open(void)
{
	lcd_fd = open("/dev/fb0", O_RDWR);
	
	if(lcd_fd<0)
	{
			printf("open lcd error\n");
			return -1;
	}
	return 0;
}

int mmap_lcd(void)
{
	mmap_fd  = (int *)mmap(	NULL, 					//映射区的开始地址,设置为NULL时表示由系统决定映射区的起始地址
									FB_SIZE, 				//映射区的长度
									PROT_READ|PROT_WRITE, 	//内容可以被读取和写入
									MAP_SHARED,				//共享内存
									lcd_fd, 				//有效的文件描述词
									0						//被映射对象内容的起点
	);
	return lcd_fd;

}

//LCD画点
void lcd_draw_point(unsigned int x,unsigned int y, unsigned int color)
{
	*(mmap_fd+y*800+x)=color;
}

//显示摄像头捕捉
int show_video_data(unsigned int x,unsigned int y,char *pjpg_buf,unsigned int jpg_buf_size)  
{
	/*定义解码对象,错误处理对象*/
	struct 	jpeg_decompress_struct 	cinfo;
	struct 	jpeg_error_mgr 			jerr;	
	
	unsigned char 	*pcolor_buf = g_color_buf;
	char 	*pjpg;
	
	unsigned int 	i=0;
	unsigned int	color =0;
	//unsigned int	count =0;
	
	unsigned int 	x_s = x;
	unsigned int 	x_e ;	
	unsigned int 	y_e ;
	
	pjpg = pjpg_buf;

	/*注册出错处理*/
	cinfo.err = jpeg_std_error(&jerr);

	/*创建解码*/
	jpeg_create_decompress(&cinfo);

	/*直接解码内存数据*/		
	jpeg_mem_src(&cinfo,pjpg,jpg_buf_size);
	
	/*读文件头*/
	jpeg_read_header(&cinfo, TRUE);

	/*开始解码*/
	jpeg_start_decompress(&cinfo);	
	
	x_e	= x_s+cinfo.output_width;
	y_e	= y  +cinfo.output_height;	

	/*读解码数据*/
	while(cinfo.output_scanline < cinfo.output_height )
	{		
		pcolor_buf = g_color_buf;
			
		/* 读取jpg一行的rgb值 */
		jpeg_read_scanlines(&cinfo,&pcolor_buf,1);
		
		for(i=0; i660 && ts_x<790 && ts_y>10 && ts_y<60)//实时监控
		{
			linux_v4l2_get_yuyv_data(&video_buf);//获取摄像头捕捉的画面	
			show_video_data(0, 0, video_buf.jpg_data, video_buf.jpg_size);//显示摄像头捕捉的画面
		}
		
		
		if(ts_x>660 && ts_x<790 && ts_y>200 && ts_y<220)//zhuapai
		{
			linux_v4l2_get_yuyv_data(&video_buf);//获取摄像头捕捉的画面	
			show_video_data(0, 0, video_buf.jpg_data, video_buf.jpg_size);//显示摄像头捕捉的画面
			sprintf(path, "./video/%d.jpg",1);
			
			fd_jpg = open(path, O_RDWR|O_CREAT|O_TRUNC);
			if(fd_jpg == -1)
			{
				printf("creat err\n");
				printf("video err\n");
			}
			
			write(fd_jpg, video_buf.jpg_data, video_buf.jpg_size);
			printf("成功抓拍%d张\r\n",1);
			show_jpeg("./video/1.jpg");
			sleep(5);
			close(fd_jpg);
			
			ts_x=ts_y=0;
		}
		
		if(ts_x>650 && ts_x<800 && ts_y>110 && ts_y<180)
		{
			linux_v4l2_get_yuyv_data(&video_buf);//获取摄像头捕捉的画面
			show_video_data(0, 0, video_buf.jpg_data, video_buf.jpg_size);//显示摄像头捕捉的画面
			
			cnt++;
			sprintf(path, "./video/%d.jpg",cnt);
			
			fd_jpg = open(path, O_RDWR|O_CREAT|O_TRUNC);
			if(fd_jpg == -1)
			{
				printf("creat err\n");
				printf("video err\n");
			}
			write(fd_jpg, video_buf.jpg_data, video_buf.jpg_size);
			printf("成功录制%d张\r\n",cnt);
			close(fd_jpg);
			//ts_x=ts_y=0;
			
		}
		
		
		//播放录制的图像
		if(ts_x>710 && ts_x<800 && ts_y>280&& ts_y<310)
		{
			int shu;
			printf("开始播放。。。\r\n");
			for(shu=1;shu<=cnt;shu++)
			{
			sprintf(path,"./video/%d.jpg",shu);	
			show_jpeg(path);
			usleep(30000);
			}
			printf("播放结束!!!\r\n");
			ts_x=ts_y=0;
			
			//break;
			
		}
		
		
		if(ts_x>660 && ts_x<790 && ts_y>410 && ts_y<480)//退出监控
		{
			printf("\n======退出监控======\n");
			flag = 0;
			//break;
			//return;
		}
	}
	
	//关闭摄像头
	linux_v4l2_yuyv_quit();
	lcd_close();
	return 0;
}

参考:

https://blog.csdn.net/eastmoon502136/article/details/8190262

https://www.cnblogs.com/cheng-zhen/p/3158958.html

2、 LCD显示模块

通过open打开LCD屏幕驱动(/dev/fb0),然后通过read读取bmp图片数据。期间需要把24bmp的数据转换成32位的LCD数据,通过write将转换的32位数据写入屏幕驱动里面,之后关闭lcd和bmp。最后将此模块封装成函数show_bmp(),以便调用。对JPEG图片的显示通过jpeglib库实现,具体函数已封装为lcd_draw_jpg()。

x			: 起点
y			: 起点
pjpg_path	:图片路径
pjpg_buf    :默认为NULL
jpg_buf_size:默认设为0
jpg_half	: 为1时显示一半,为0时显示全部
*/
int lcd_draw_jpg(unsigned int x,unsigned int y,const char *pjpg_path,char *pjpg_buf,unsigned int jpg_buf_size,unsigned int jpg_half)  
{
	
	char g_color_buf[FB_SIZE]={0};
	
	//初始化LCD
	int g_fb_fd = open("/dev/fb0", O_RDWR);
	
	if(g_fb_fd<0)
	{
			printf("open lcd error\n");
			return -1;
	}

	int *g_pfb_memory  = (int *)mmap(	NULL, 					//映射区的开始地址,设置为NULL时表示由系统决定映射区的起始地址
									FB_SIZE, 				//映射区的长度
									PROT_READ|PROT_WRITE, 	//内容可以被读取和写入
									MAP_SHARED,				//共享内存
									g_fb_fd, 				//有效的文件描述词
									0						//被映射对象内容的起点
								);
	
	/*定义解码对象,错误处理对象*/
	struct 	jpeg_decompress_struct 	cinfo;
	struct 	jpeg_error_mgr 			jerr;	
	
	char *pcolor_buf = g_color_buf;
	char 	*pjpg;
	
	unsigned int 	i=0;
	unsigned int	color =0;
	unsigned int	count =0;
	
	unsigned int 	x_s = x;
	unsigned int 	x_e ;	
	unsigned int 	y_e ;
	
			 int	jpg_fd;
	unsigned int 	jpg_size;
	
	unsigned int 	jpg_width;
	unsigned int 	jpg_height;
	

	if(pjpg_path!=NULL)
	{
		/* 申请jpg资源,权限可读可写 */	
		jpg_fd=open(pjpg_path,O_RDWR);
		
		if(jpg_fd == -1)
		{
		   printf("open %s error\n",pjpg_path);
		   
		   return -1;	
		}	
		
		/* 获取jpg文件的大小 */
		jpg_size=file_size_get(pjpg_path);	

		/* 为jpg文件申请内存空间 */	
		pjpg = malloc(jpg_size);

		/* 读取jpg文件所有内容到内存 */		
		read(jpg_fd,pjpg,jpg_size);
	}
	else
	{
		jpg_size = jpg_buf_size;
		
		pjpg = pjpg_buf;
	}

	/*注册出错处理*/
	cinfo.err = jpeg_std_error(&jerr);

	/*创建解码*/
	jpeg_create_decompress(&cinfo);

	/*直接解码内存数据*/		
	jpeg_mem_src(&cinfo,pjpg,jpg_size);
	
	/*读文件头*/
	jpeg_read_header(&cinfo, TRUE);

	/*开始解码*/
	jpeg_start_decompress(&cinfo);	
	
	
	if(jpg_half)
	{
		x_e	= x_s+(cinfo.output_width/2);
		y_e	= y  +(cinfo.output_height/2);		
		
		/*读解码数据*/
		while(cinfo.output_scanline < cinfo.output_height)
		{		
			pcolor_buf = g_color_buf;
			
			/* 读取jpg一行的rgb值 */
			jpeg_read_scanlines(&cinfo,(JSAMPARRAY)&pcolor_buf,1);			
			
			/* 再读取jpg一行的rgb值 */
			jpeg_read_scanlines(&cinfo,(JSAMPARRAY)&pcolor_buf,1);

			for(i=0; i<(cinfo.output_width/2); i++)
			{
				/* 获取rgb值 */
				color = 		*(pcolor_buf+2);
				color = color | *(pcolor_buf+1)<<8;
				color = color | *(pcolor_buf)<<16;
				
				/* 显示像素点 */
				*(g_pfb_memory+y*800+x)=color;
				
				pcolor_buf +=6;
				
				x++;
			}
			
			/* 换行 */
			y++;					
			
			
			x = x_s;	

			
		}
	}
	else
	{
		x_e	= x_s+cinfo.output_width;
		y_e	= y  +cinfo.output_height;	

		/*读解码数据*/
		while(cinfo.output_scanline < cinfo.output_height )
		{		
			pcolor_buf = g_color_buf;
			
			/* 读取jpg一行的rgb值 */
			jpeg_read_scanlines(&cinfo,(JSAMPARRAY)&pcolor_buf,1);
			
			for(i=0; i

3、触摸屏驱动

首先打开触摸屏的设备驱动 /dev/input/event0,然后通过read从驱动读取触摸信息,之后自己定义结构体保存触摸信息,并分析触摸信息和使用触摸屏信息。最后将此模块封装成函数touch_screen库,以便调用。

#include "touch_screen.h"

int fd_ev0;

int open_ts(void)//1,打开触控屏(open)
{	
	fd_ev0 = open("/dev/input/event0", O_RDWR);
	if(fd_ev0 == -1)
	{
			printf("open event0 fail!\n");
	}		
	return 0;
}

int read_ts(int *coordinate_x, int *coordinate_y)//2,读取触控屏的信息到结构体中。(read)
{
	int ret;	
	struct input_event coordinate;
	while(1)
	{
		read(fd_ev0, &coordinate, sizeof(struct input_event));
				
		
		if(coordinate.type==3 && coordinate.code==0 && coordinate.value>0 && coordinate.value<800)
		{
			*coordinate_x =  coordinate.value;
		}
		if(coordinate.type==3 && coordinate.code==1 && coordinate.value>0 && coordinate.value<480)
		{
			*coordinate_y =  coordinate.value;
		}
		if(coordinate.type==1 && coordinate.code==330 && coordinate.value==0)
		{
			break;
		}			
	}
	
	return 0;
}

int close_ts(void)
{
	close(fd_ev0);
	return 0;
}

效果图如下:

基于GEC6818的嵌入式智能监控系统设计_第1张图片               基于GEC6818的嵌入式智能监控系统设计_第2张图片   基于GEC6818的嵌入式智能监控系统设计_第3张图片

源代码见src下,lib下库可直接移植使用。

完整工程文件下载地址:https://download.csdn.net/download/ywueoei/11265808

 

 

你可能感兴趣的:(嵌入式笔记)