video4linux(v4l)使用摄像头的实例基础教程与体会(三)

来源:互联网 发布:php sql 防注入 编辑:程序博客网 时间:2024/05/20 14:25

下面完成第3步按照需要更改设备的相应设置,事实上可以更改的设置很多,本文以更改picture属性为例说明更改属性的一般方法。

       那么我们就完成extern int v4l_set_picture(v4l_device *, int, int, int, int, int,);这个函数吧

int v4l_set_picture(v4l_device *vd,int br,int hue,int col,int cont,int white)

{

   if(br) vd->picture.brightnesss=br;

   if(hue) vd->picture.hue=hue;

   if(col) vd->picture.color=col;

   if(cont) vd->picture.contrast=cont;

   if(white) vd->picture.whiteness=white;

   if(ioctl(vd->fd,VIDIOCSPICT,&(vd->picture))<0)

   {perror("v4l_set_picture: ");return -1;}  

   return 0;

}

上述函数就是更改picture相关属性的例子,其核心还是v4l给我们提供的ioctl的相关调用,通过这个函数可以修改如亮度,对比度等相关的值。

       4步获得采集到的图像数据。

       这一步是使用v4l比较重要的一步,涉及到几个函数的编写。当然使用v4l就是为了要获得图像,所以这一步很关键,但是当你获得了图像数据后,还需要根据你想要达到的目的和具体情况做进一步的处理,也就是第5步所做的事情,这些内容将在后面第三部分提到。这里讲如何获得采集到的数据。

       如前所述获得图像的方式有两种,分别是直接读取设备使用mmap内存映射,而通常大家使用的方法都是后者。

1.直接读取设备

直接读设备的方式就是使用read()函数,我们先前定义的

extern int v4l_grab_picture(v4l_device *, unsigned int);函数就是完成这个工作的,它的实现也很简单。

 

int v4l_grab_picture(v4l_device *vd, unsighed int size)

{

   if(read(vd-fd,&(vd->map),size)==0)return -1;

   return 0

}

该函数的使用也很简单,就是给出图像数据的大小,vd->map所指向的数据就是图像数据。而图像数据的大小你要根据设备的属性自己计算获得。

2.使用mmap内存映射来获取图像

       在这部分涉及到下面几个函数,它们配合来完成最终图像采集的功能。

       extern int v4l_mmap_init(v4l_device *);该函数把摄像头图像数据映射到进程内存中,也就是只要使用vd->map指针就可以使用采集到的图像数据(下文详细说明)

extern int v4l_grab_init(v4l_device *, int, int);该函数完成图像采集前的初始化工作。

extern int v4l_grab_frame(v4l_device *, int);该函数是真正完成图像采集的一步,在本文使用了一个通常都会使用的一个小技巧,可以在处理一帧数据时同时采集下一帧的数据,因为通常我们使用的摄像头都可以至少存储两帧的数据。

extern int v4l_grab_sync(v4l_device *);该函数用来完成截取图像的同步工作,在截取一帧图像后调用,返回表明一帧截取结束。

 

       下面分别介绍这几个函数。

 

       mmap()系统调用使得进程之间通过映射同一个普通文件实现共享内存。普通文件被映射到进程地址空间后,进程可以像访问普通内存一样对文件进行访问,不必在调用read()write()等操作。两个不同进程AB共享内存的意思是,同一块物理内存被映射到进程AB各自的进程地址空间。进程A可以即时访问进程B对共享内存中数据的更新,反之亦然。

       采用共享内存通信的一个显而易见的好处是减少I/O操作提高读取效率,因为使用mmap后进程可以直接读取内存而不需要任何数据的拷贝。

mmap的函数原型如下

void* mmap ( void * addr , size_t len , int prot , int flags , int fd , off_t offset )

addr:共享内存的起始地址,一般设为0,表示由系统分配。

len:指定映射内存的大小。在我们这里,该值为摄像头mbuf结构体的size值,即图像数据的总大小。

port:指定共享内存的访问权限 PROT_READ(可读)PROT_WRITE(可写)

flags:一般设置为MAP_SHARED

fd:同享文件的文件描述符。

 

介绍完了mmap的使用,就可以介绍上文中定义的函数extern int v4l_mmap_init(v4l_device *);了。先给出这个函数的代码,再做说明。

int v4l_mmap_init(v4l_device *vd)  

{  

   if (v4l_get_mbuf(vd) < 0)  

   return -1;  

   if ((vd->map = mmap(0, vd->mbuf.size, PROT_READ|PROT_WRITE, MAP_SHARED, vd->fd, 0)) < 0) {  

      perror("v4l_mmap_init:mmap");  

      return -1;  

   }  

   return 0;  

}

这个函数首先使用v4l_get_mbuf(vd)获得一个摄像头重要的参数,就是需要映射内存的大小,即vd->mbuf.size,然后调用mmap,当我们在编程是调用v4l_mmap_init后,vd.map指针所指向的内存空间即为我们将要采集的图像数据。

原创粉丝点击