打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
(转载)基于ZedBoard的Webcam设计(一):USB摄像头(V4L2接口)的图片采集
userphoto

2013.11.05

关注

一直想把USB摄像头接到Zedboard上,搭建一个简易视频监控系统方便后续做视频处理。Xilinx官方给出了一个Webcam摄像头监控的例子,跑的是linaro,不知道是我的SD卡问题还是摄像头的问题,播放视频的时候总是会很卡,而且突然系统就死掉了。还是很喜欢自己动手,能学到新东西。Digilent官方给的OOB设计,那个精简的linux足够做简单的linux开发了,而且OOB设计中USB驱动和V4L(Video for Linux)都提供好了。这几天找了一些的V4L的资料,完成了摄像头的单帧图片采集,接下来要做的是QT界面显示和视频流的显示了,最终的计划是完成视频采集、编码、存储和以太网传输。希望能有时间和精力完成这么多。先把这几天的做的东西整理出来和大家分享。为了方便大家对程序的理解,先简单介绍一下linux下的V4L2的一些知识,然后再详细介绍V4L2编程。

更多更新请关注我的博客:@超群天晴 http://www.cnblogs.com/surpassal/  

相关阅读 : 

(原创)基于ZedBoard的Webcam设计(一):USB摄像头(V4L2接口)的图片采集  

(原创)基于ZedBoard的Webcam设计(二):USB摄像头图片采集+QT显示  

(原创)基于ZedBoard的Webcam设计(三):视频的采集和动态显示  

(原创)基于ZedBoard的Webcam设计(四):MJPG编码和AVI封装  

(原创)基于ZedBoard的Webcam设计(五):x264编码在zedboard上的实现(软编码)

 

硬件平台:Digilent ZedBoard + USB 摄像头

开发环境:Windows XP 32 bit + Wmare 8.0 + Ubuntu 10.04 + arm-linux-xilinx-gnueabi交叉编译环境

Zedboard linux: Digilent OOB Design 

 

一、一些知识

 1、V4L和V4L2。

V4L是Linux环境下开发视频采集设备驱动程序的一套规范(API),它为驱动程序的编写提供统一的接口,并将所有的视频采集设备的驱动程序都纳入其的管理之中。V4L不仅给驱动程序编写者带来极大的方便,同时也方便了应用程序的编写和移植。V4L2是V4L的升级版,由于我们使用的OOB是3.3的内核,不再支持V4L,因而编程不再考虑V4L的api和参数定义。

2、YUYV与RGB24

RGB是一种颜色的表示法,计算机中一般采用24位来存储,每个颜色占8位。YUV也是一种颜色空间,为什么要出现YUV,主要有两个原因,一个是为了让彩色信号兼容黑白电视机,另外一个原因是为了减少传输的带宽。YUV中,Y表示亮度,U和V表示色度,总之它是将RGB信号进行了一种处理,根据人对亮度更敏感些,增加亮度的信号,减少颜色的信号,以这样“欺骗”人的眼睛的手段来节省空间。YUV到RGB颜色空间转换关系是:

R = Y + 1.042*(V-128);G = Y - 0.34414*(U-128) - 0.71414*(V-128);B = Y + 1.772*(U-128);

YUV的格式也很多,不过常见的就是422、420等。YUYV就是422形式,简单来说就是,两个像素点P1、P2本应该有Y1、U1、V1和Y2、U2、V2这六个分量,但是实际只保留Y1、U1、Y2、V2。

图1 YUYV像素

二、应用程序设计

先定义一些宏和结构体,方便后续编程

 1 #define  TRUE    1 2 #define  FALSE    0 3  4 #define FILE_VIDEO     "/dev/video0" 5 #define BMP          "/usr/image_bmp.bmp" 6 #define YUV            "/usr/image_yuv.yuv" 7  8 #define  IMAGEWIDTH    640 9 #define  IMAGEHEIGHT   48010 11 static   int      fd;12 static   struct   v4l2_capability   cap;13 struct v4l2_fmtdesc fmtdesc;14 struct v4l2_format fmt,fmtack;15 struct v4l2_streamparm setfps;  16 struct v4l2_requestbuffers req;17 struct v4l2_buffer buf;18 enum v4l2_buf_type type;19 unsigned char frame_buffer[IMAGEWIDTH*IMAGEHEIGHT*3];

其中

#define FILE_VIDEO     "/dev/video0"

是要访问的摄像头设备,默人都是/dev/video0

#define BMP          "/usr/image_bmp.bmp"#define YUV          "/usr/image_yuv.yuv"

是采集后存储的图片,为了方便测试,这里将直接获取的yuv格式数据也保存成文件,可以通过yuvviewer等查看器查看。

static   int      fd;static   struct   v4l2_capability   cap;struct v4l2_fmtdesc fmtdesc;struct v4l2_format fmt,fmtack;struct v4l2_streamparm setfps;  struct v4l2_requestbuffers req;struct v4l2_buffer buf;enum v4l2_buf_type type;

这些结构体的定义都可以从/usr/include/linux/videodev2.h中找到定义,具体含义在后续编程会做相应解释。

#define  IMAGEWIDTH    640#define  IMAGEHEIGHT   480

为采集图像的大小。

定义一个frame_buffer,用来缓存RGB颜色数据

unsigned char frame_buffer[IMAGEWIDTH*IMAGEHEIGHT*3]

 这些宏和定义结束后,就可以开始编程配置摄像头并采集图像了。一般来说V4L2采集视频数据分为五个步骤:首先,打开视频设备文件,进行视频采集的参数初始化,通过V4L2接口设置视频图像的采集窗口、采集的点阵大小和格式;其次,申请若干视频采集的帧缓冲区,并将这些帧缓冲区从内核空间映射到用户空间,便于应用程序读取/处理视频数据;第三,将申请到的帧缓冲区在视频采集输入队列排队,并启动视频采集;第四,驱动开始视频数据的采集,应用程序从视频采集输出队列取出帧缓冲区,处理完后,将帧缓冲区重新放入视频采集输入队列,循环往复采集连续的视频数据;第五,停止视频采集。在本次设计中,定义了三个函数实现对摄像头的配置和采集。

int init_v4l2(void);int v4l2_grab(void);int close_v4l2(void);

同时由于采集到的图像数据是YUYV格式,需要进行颜色空间转换,定义了转换函数。

int yuyv_2_rgb888(void);

下面就详细介绍这几个函数的实现。

1、初始化V4l2

(1)打开视频。linux对摄像头的访问和普通设备一样,使用open函数就可以,返回值是设备的id。

1 if ((fd = open(FILE_VIDEO, O_RDWR)) == -1) 2 {3     printf("Error opening V4L interface\n");4     return (FALSE);5 }

(2)读video_capability中信息。通过调用IOCTL函数和接口命令VIDIOC_QUERYCAP查询摄像头的信息,结构体v4l2_capability中有包括驱动名称driver、card、bus_info、version以及属性capabilities。这里我们需要检查一下是否是为视频采集设备V4L2_CAP_VIDEO_CAPTURE以及是否支持流IO操作V4L2_CAP_STREAMING。

 1 if (ioctl(fd, VIDIOC_QUERYCAP, &cap) == -1)  2 { 3     printf("Error opening device %s: unable to query device.\n",FILE_VIDEO); 4     return (FALSE); 5 } 6 else 7 { 8      printf("driver:\t\t%s\n",cap.driver); 9      printf("card:\t\t%s\n",cap.card);10      printf("bus_info:\t%s\n",cap.bus_info);11      printf("version:\t%d\n",cap.version);12      printf("capabilities:\t%x\n",cap.capabilities);13      14      if ((cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) == V4L2_CAP_VIDEO_CAPTURE) 15      {16         printf("Device %s: supports capture.\n",FILE_VIDEO);17     }18 19     if ((cap.capabilities & V4L2_CAP_STREAMING) == V4L2_CAP_STREAMING) 20     {21         printf("Device %s: supports streaming.\n",FILE_VIDEO);22     }23 } 

(3)列举摄像头所支持像素格式。使用命令VIDIOC_ENUM_FMT,获取到的信息通过结构体v4l2_fmtdesc查询。这步很关键,不同的摄像头可能支持的格式不一样,V4L2可以支持的格式很多,/usr/include/linux/videodev2.h文件中可以看到。

1 fmtdesc.index=0;2 fmtdesc.type=V4L2_BUF_TYPE_VIDEO_CAPTURE;3 printf("Support format:\n");4 while(ioctl(fd,VIDIOC_ENUM_FMT,&fmtdesc)!=-1)5 {6     printf("\t%d.%s\n",fmtdesc.index+1,fmtdesc.description);7     fmtdesc.index++;8 }

(4)设置像素格式。一般的USB摄像头都会支持YUYV,有些还支持其他的格式。通过前一步对摄像头所支持像素格式查询,下面需要对格式进行设置。命令为VIDIOC_S_FMT,通过结构体v4l2_format把图像的像素格式设置为V4L2_PIX_FMT_YUYV,高度和宽度设置为IMAGEHEIGHT和IMAGEWIDTH。一般情况下一个摄像头所支持的格式是不可以随便更改的,我尝试把把一个只支持YUYV和MJPEG的摄像头格式改为RGB24或者JPEG,都没有成功。

 1 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 2 fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV; 3 fmt.fmt.pix.height = IMAGEHEIGHT; 4 fmt.fmt.pix.width = IMAGEWIDTH; 5 fmt.fmt.pix.field = V4L2_FIELD_INTERLACED; 6  7 if(ioctl(fd, VIDIOC_S_FMT, &fmt) == -1) 8 { 9     printf("Unable to set format\n");10     return FALSE;11 }     

为了确保设置的格式作用到摄像头上,再通过命令VIDIOC_G_FMT将摄像头设置读取回来。

 1 if(ioctl(fd, VIDIOC_G_FMT, &fmt) == -1) 2 { 3     printf("Unable to get format\n"); 4     return FALSE; 5 }  6 { 7      printf("fmt.type:\t\t%d\n",fmt.type); 8      printf("pix.pixelformat:\t%c%c%c%c\n",fmt.fmt.pix.pixelformat & 0xFF, (fmt.fmt.pix.pixelformat >> 8) & 0xFF,(fmt.fmt.pix.pixelformat >> 16) & 0xFF, (fmt.fmt.pix.pixelformat >> 24) & 0xFF); 9      printf("pix.height:\t\t%d\n",fmt.fmt.pix.height);10      printf("pix.width:\t\t%d\n",fmt.fmt.pix.width);11      printf("pix.field:\t\t%d\n",fmt.fmt.pix.field);12 }

完整的初始化代码如下:

View Code

2、图像采集

(1)申请缓存区。使用参数VIDIOC_REQBUFS和结构体v4l2_requestbuffers。v4l2_requestbuffers结构中定义了缓存的数量,系统会据此申请对应数量的视频缓存。

1 req.count=4;2 req.type=V4L2_BUF_TYPE_VIDEO_CAPTURE;3 req.memory=V4L2_MEMORY_MMAP;4 if(ioctl(fd,VIDIOC_REQBUFS,&req)==-1)5 {6     printf("request for buffers error\n");7 8 }

(2)获取每个缓存的信息,并mmap到用户空间。定义结构体

struct buffer{    void * start;    unsigned int length;} * buffers;

来存储mmap后的地址信息。需要说明的是由于mmap函数定义时返回的地址是个void *,因而这里面的start也是个 void *。实际地址在运行的时候会自动分配。

 1 for (n_buffers = 0; n_buffers < req.count; n_buffers++)  2 { 3     buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 4     buf.memory = V4L2_MEMORY_MMAP; 5     buf.index = n_buffers; 6     //query buffers 7     if (ioctl (fd, VIDIOC_QUERYBUF, &buf) == -1) 8     { 9         printf("query buffer error\n");10         return(FALSE);11     }12 13     buffers[n_buffers].length = buf.length;14     //map15     buffers[n_buffers].start = mmap(NULL,buf.length,PROT_READ |PROT_WRITE, MAP_SHARED, fd, buf.m.offset);16     if (buffers[n_buffers].start == MAP_FAILED)17     {18         printf("buffer map error\n");19         return(FALSE);20     }21 }

(3) 之后就可以开始采集视频了。使用命令VIDIOC_STREAMON。

1 type = V4L2_BUF_TYPE_VIDEO_CAPTURE;2 ioctl (fd, VIDIOC_STREAMON, &type);

(4)取出缓存中已经采样的缓存。使用命令VIDIOC_DQBUF。视频数据存放的位置是buffers[n_buffers].start的地址处。

1 ioctl(fd, VIDIOC_DQBUF, &buf);

完整的采集代码:

View Code

3、YUYV转RGB24

由于摄像头采集的数据格式为YUYV,为了方便后续设计,需要转变为RGB24,并将转换完成的数据存储到frame_buffer中。值得一提的是,由于定义的时候buffers[index].start是个void *,没有办法进行+1这样的操作,需要强制转换为

char * pointerpointer = buffers[0].start

由于后续RGB的数据要存储到BMP中,而BMP文件中颜色数据是“倒序”,即从下到上,从左到右,因而在向frame_buffer写数据时是从最后一行最左测开始写,每写满一行行数减一。

View Code

4、停止采集和关闭设备

使用命令VIDIOC_STREAMOFF停止视频采集,并关闭设备。

 1 int close_v4l2(void) 2 { 3     ioctl(fd, VIDIOC_STREAMOFF, &buf_type);      4     if(fd != -1)  5      { 6          close(fd); 7          return (TRUE); 8      } 9      return (FALSE);10 }

5、主函数

需要把我们采集到图像数据存储成图片,为了方便调试,先将原始的数据存储为yuv格式文件,再将转换成RGB后的数据存储为BMP。定义BMP头结构体

 1 typedef struct tagBITMAPFILEHEADER{ 2      WORD    bfType;                // the flag of bmp, value is "BM" 3      DWORD    bfSize;                // size BMP file ,unit is bytes 4      DWORD    bfReserved;            // 0 5      DWORD    bfOffBits;             // must be 54 6  7 }BITMAPFILEHEADER; 8  9  10 typedef struct tagBITMAPINFOHEADER{11      DWORD    biSize;                // must be 0x2812      DWORD    biWidth;           //13      DWORD    biHeight;          //14      WORD        biPlanes;          // must be 115      WORD        biBitCount;            //16      DWORD    biCompression;         //17      DWORD    biSizeImage;       //18      DWORD    biXPelsPerMeter;   //19      DWORD    biYPelsPerMeter;   //20      DWORD    biClrUsed;             //21      DWORD    biClrImportant;        //22 }BITMAPINFOHEADER;

完整的主函数

//@超群天晴
//http://www.cnblogs.com/surpassal/
int
main(void){ FILE * fp1,* fp2; BITMAPFILEHEADER bf; BITMAPINFOHEADER bi; fp1 = fopen(BMP, "wb"); if(!fp1) { printf("open "BMP"error\n"); return(FALSE); } fp2 = fopen(YUV, "wb"); if(!fp2) { printf("open "YUV"error\n"); return(FALSE); } if(init_v4l2() == FALSE) { return(FALSE); } //Set BITMAPINFOHEADER bi.biSize = 40; bi.biWidth = IMAGEWIDTH; bi.biHeight = IMAGEHEIGHT; bi.biPlanes = 1; bi.biBitCount = 24; bi.biCompression = 0; bi.biSizeImage = IMAGEWIDTH*IMAGEHEIGHT*3; bi.biXPelsPerMeter = 0; bi.biYPelsPerMeter = 0; bi.biClrUsed = 0; bi.biClrImportant = 0; //Set BITMAPFILEHEADER bf.bfType = 0x4d42; bf.bfSize = 54 + bi.biSizeImage; bf.bfReserved = 0; bf.bfOffBits = 54; v4l2_grab(); fwrite(buffers[0].start, 640*480*2, 1, fp2); printf("save "YUV"OK\n"); yuyv_2_rgb888(); fwrite(&bf, 14, 1, fp1); fwrite(&bi, 40, 1, fp1); fwrite(frame_buffer, bi.biSizeImage, 1, fp1); printf("save "BMP"OK\n"); fclose(fp1); fclose(fp2); close_v4l2(); return(TRUE);}

 三、PC测试

程序编写完后,可以先在PC上做测试(实际整个调试过程都是在PC上,直道最后PC上能实现功能再挪到ZedBoard上的)。PC上测试的结果

 在/usr目录下可以查看到采集到的图片

四、Zedboard测试

PC上测试OK后,可以“挪”到ZedBoard上了。使用arm-xilinx-linux交叉编译环境对源文件进行交叉编译,将生成的可执行文件拷贝到ZedBoard上运行即可。

使用命令

arm-xilinx-linux-gnueabi-gcc v4l2grab.c -o zed-camera

对程序进行编译,编译通过后将生成的可执行文件zed-camera拷贝到到ZedBoard上,并将USB摄像头连接到ZedBoard上,通过命令

ls /dev 

 查看dev目录下的是否有video0设备。如果有,可以运行可执行文件了。在运行前我比较习惯获得可执行文件的权限,使用命令

chmod +x zed-camera

参数+x的意思是这个文件对于当前用户是可执行的。也可以使用

chmod 777 zed-camera

这样所有用户都有读写执行的权限。使用命令

./zed-camera

执行可执行程序,程序运行,并输出以下信息:

zynq> ./zed-camera[  318.290000] usb 1-1.3: reset high-speed USB device number 3 using xusbps-ehcidriver:         uvcvideocard:           UVC Camera (046d:0825)bus_info:       usb-xusbps-ehci.0-1.3version:        197376capabilities:   4000001Device /dev/video0: supports capture.Device /dev/video0: supports streaming.Support format:        1.YUV 4:2:2 (YUYV)        2.MJPEGfmt.type:               1pix.pixelformat:        YUYVpix.height:             480pix.width:              640pix.field:              1init /dev/video0        [OK]grab yuyv OKsave /usr/image_yuv.yuv OKchange to RGB OKsave /usr/image_bmp.bmp OK

可以看到我使用的USB摄像支持YUYV和MJPEG两种格式。我也试过其他USB摄像头,大部分都只支持YUYV而不支持MJPEG或者RGB24。

采集到的图片默认是在/usr目录下的,将其拷贝出来

cp /usr/image* /mnt

再PC上查看,效果还不错

=============================

完整工程和代码:lab_v4l2_yuyv.zip

可以指定任意分辨率摄像头的代码:v4l2grab_Anysize.rar 《感谢@jiaquwang分享》

评论

#1楼 2012-12-19 16:14 zhuangzhuang1988  

`V4L2是V4L的旧版本` --> 反了..
  

#2楼[楼主] 2012-12-19 16:18 超群天晴  

@zhuangzhuang1988
写得着急,的确是写错了。谢谢指正
  

#3楼 2012-12-22 01:39 掬水  

楼主做的怎样了?我现在也在做视频,但是在设置摄像头格式时,在天嵌开发板子得出的是MJPEG,而在fedora17得到居然是YUYV 。现在就是不知道怎么转换格式。
  

#4楼[楼主] 2012-12-22 09:33 超群天晴  

@掬水
这两天忙着写论文,停滞了一些。准备开始做QT界面了视频流的显示了。是不是内核版本不一样?你试过enum fmt吗?
  

#5楼 2012-12-22 12:06 掬水  

@超群天晴
我今天用你的程序测试了下,在电脑dedora是能保存图片,而在ARM板子上就不行,下面是出错信息:

[root@EmbedSky /bin]# ./v4l2grab
driver: uvcvideo
card: Vimicro USB2.0 UVC PC Camera
bus_info: usb-s3c24xx-1
version: 256
capabilities: 4000001
Device /dev/video0: supports capture.
Device /dev/video0: supports streaming.
Support format:
1.MJPEG
Unable to set format
[root@EmbedSky /bin]#
  

#6楼[楼主] 2012-12-22 12:53 超群天晴  

@掬水
Support format:
1.MJPEG
不支持YUYV。我这个程序是YUYV的
  

#7楼 2012-12-22 13:36 掬水  

你有没有有关MJPEG转换格式的资料或代码?
  

#8楼 2012-12-22 16:42 掬水  

@超群天晴
你在程序中bmp等文件头信息中的幻数,从哪儿知道的?
  

#9楼[楼主] 2012-12-22 18:21 超群天晴  

@掬水
MJEPG就是jpg编码。bmp头文件是固定的。这两个你都可以百度……
  

#10楼 2012-12-23 12:42 掬水  

@超群天晴
你现在就写毕业论文了,是硕士论文吗?我打算在板子上实现拍照和本地录像,以后请多指教。
  

#11楼 2013-01-05 16:03 woshivbn  

晴天大大,我又来了。。 烦问您下,您这个“Wmare 8.0 + Ubuntu 10.04 + arm-linux-xilinx-gnueabi交叉编译环境” 是怎么建立的? 我之前没有接触过linux,不太明白,能详细给讲解一下整个流程嘛? 我安装了好几天,也没配置正确,总是跑不起来,也很急的慌。劳您给个指导哈!~
  

#12楼[楼主] 2013-01-05 16:37 超群天晴  

@掬水
不是的 小论文
  

#13楼[楼主] 2013-01-05 16:38 超群天晴  

@woshivbn
xilinx的wiki上有介绍http://wiki.xilinx.com/zynq-tools,下载后按照说安装就可以了
  

#14楼 2013-01-06 17:43 woshivbn  

@超群天晴
在ubuntu下面是不是不需要安装ise了啊
  

#15楼[楼主] 2013-01-06 22:35 超群天晴  

@woshivbn
安装了gnu tools 后,就不需要ise了。使用ise也可以的。
  

#16楼 2013-01-07 21:32 woshivbn  

晴天大大 为什么当我生成了文件之后 输入./a.out 会出现这样的错误 bash: .a.out cannot execute binary file
  

#17楼 2013-01-13 09:27 cddc  

您好!请问您的摄像头型号?我用的是罗技C110,取图失败了。。
driver: uvcvideo
card: Webcam C110
bus_info: usb-xusbps-ehci.0-1.2
version: 197376
capabilities: 4000001
Device /dev/video0: supports capture.
Device /dev/video0: supports streaming.
Support format:
1.YUV 4:2:2 (YUYV)
2.MJPEG
fmt.type: 1
pix.pixelformat: YUYV
pix.height: 144
pix.width: 176
pix.field: 1
init /dev/video0 [OK]
save /usr/image_yuv.yuvOK
change to RGB OK
save /usr/image_bmp.bmpOK
一路下来没有报错,只是取出来的图片是乱码,.yuyv的图片也是乱码。怎么会这样呢?
  

#18楼[楼主] 2013-01-13 09:42 超群天晴  

@woshivbn
你咋生成了a.out了
  

#19楼[楼主] 2013-01-13 09:46 超群天晴  

@cddc
你在ubuntu上试过吗?C110我没试过,我用的是罗技的C270,普通的USB摄像头我也试过,没有这样的问题。
  

#20楼 2013-01-13 10:19 cddc  

@超群天晴
我的virtualbox一接上webcam就死机,暂时还没搞定,所以没有在ubuntu上试过。
像素格式那里设置之前是,640*480
设置完之后读回来就变了:
pix.height: 144
pix.width: 176
会不会是这个原因?
还有STREAMON那个函数我得到的返回值是-1,不是零,是不是摄像头没有被启动?
纠结我一个星期了。。。
  

#21楼[楼主] 2013-01-13 10:26 超群天晴  

@cddc
你的摄像头最大的分辨率是176x144,所以设置640x480肯定不行。问题应该就出在这儿了。把程序里相应的地方都改一下,bmp的头文件也改一下。我没想到STREAMON命令竟然还不能执行成功,你确定你的摄像头还能用?
建议你换一个摄像头吧……
  

#22楼 2013-01-13 10:36 cddc  

@超群天晴
摄像头在XP里面一切正常的。这是第三个摄像头了==
  

#23楼[楼主] 2013-01-13 10:49 超群天晴  

@cddc
@cddc
你先试试设置分辨率为176x144看看吧
  

#24楼 2013-01-14 18:47 cddc  

问题解决了,原因是USBhub频率低,限制了摄像头,造成错误。原来用USBhub同时接U盘和摄像头,看来不行。必须要把文件拷到zedboard的linux里面,再接上摄像头。博主有没有用USBhub?
  

#25楼[楼主] 2013-01-14 20:24 超群天晴  

@cddc
之前我用一个质量和供电不咋地的hub,接了U盘和鼠标之后,摄像头能够采集,但是图像很容易乱码。换了一个好点的hub这个问题就解决了。
  

#26楼 2013-02-12 11:24 gyifan  

@cddc
我遇到了相同的问题。拿掉USBhub后,像素正常了。可是拿出来的图像还是乱码,或是说damaged, too large等等。你最后可以看了吗?
  

#27楼 2013-02-12 11:29 gyifan  

博主博主,求教啊。

我现在在美国上大学,大四在做这个ZedBoard的东西。最终我得在ZedBoard上运行OpenCV的软件。我按你说的运行了。一切正常,可是就是读不出东西啊。拿出来的图片打开说:

Windows Photo Viewer can't open this picture because the file appears to be damaged, corrupted, or is too large.

可能是哪出问题了啊?

谢谢博主了。我是新手。
  

#28楼 2013-02-13 07:16 gyifan  

480p 搞定了。可是感觉换成720p或1080p,楼主的程序就没用了。输出的图像上一大半是黑的。最下面一段开始输出图像。而且图像是偏的。原本中线的地方被分到了边上,原本边上的图像合在了中间。图像没有输完。估计是因为底线到了的原因。这在720p和1080p都有发生。480p是好的。

楼主,在你的程序里有pixel size specific的数据吗?估计得把他们换成 IMAGEWIDTH 和 IMAGEHEIGHT。帮忙看下好吗?自己找了一会儿没看出来。估计就在main 或是 yuyv_2_rgb888 里面。

谢谢!!!
  

#29楼 2013-02-13 07:55 gyifan  

找到了!

在 yuyv_2_rgb888 里,要把所有480换成IMAGEHEIGHT, 320换成IMAGEWIDTH/2。就可以了。

哈哈!
  

#30楼 2013-03-14 21:58 winnter  

driver: uvcvideo
card: HP Webcam
bus_info: usb-0000:00:06.0-2
version: 256
capabilities: 4000001
Device /dev/video0: supports capture.
Device /dev/video0: supports streaming.
Support format:
1.YUV 4:2:2 (YUYV)
fmt.type: 1
pix.pixelformat: YUYV
pix.height: 480
pix.width: 640
pix.field: 1
init /dev/video0 [OK]
博主啊,我的为什么就卡在这里不动了了,然后我调试了下,发现问题ioctl (fd, VIDIOC_STREAMON, &type)这个采集图像根本没有采集到,因为返回值<0 ,进而导致程序卡住了,那么若问下为什么会采集失败呢。我看程序都是很标准的程序,跟网上的都差不多的,奇怪了。。
  

#31楼 2013-04-15 15:43 人若无名  

博主,请问你在main程序开始就打开bmp 和 yuv,这两个不是之前在usr下面没有吗,打开的时候找不到的啊?菜鸟求教啊~
  

#32楼[楼主] 2013-04-15 18:53 超群天晴  

@人若无名
fopen, wb 只写打开(如果不存在则新建)一个二进制文件;只允许写数据。
  

#33楼 2013-05-13 12:00 zkh_elab  

博主你好,我现在也在做图像采集,程序差不多就是上面博客上写的,一开始我采用的是比较老的有驱摄像头,这个取图片没有问题,之后我有换了一个无驱摄像头但是取图总是失败,不知道是什么原因,希望你能解答一下…………
这是不好用的摄像头的信息:
open camera is sucess.fd=14.
camara driver: Samsung FIMC Dris3c-fimc0
camara card: s3c-fimc0
camara bus info: FIMC AHB-bus
camara version: 0
camara capabilities: 0x4000005
{ pixelformat = 'YU12', description = '4:2:0, planar, Y-Cb-Cr' }
{ pixelformat = '422P', description = '4:2:2, planar, Y-Cb-Cr' }
{ pixelformat = 'YUYV', description = '4:2:2, packed, YCBYCR' }
{ pixelformat = 'UYVY', description = '4:2:2, packed, CBYCRY' }
这是好用的摄像头的信息:
open camera is sucess.fd=14.
camara driver: zc3xx
camara card: PC Camera
camara bus info: usb-s3c24xx-1
camara version: 134144
camara capabilities: 0x5000001
{ pixelformat = 'JPEG', description = 'JPEG' }
先谢过博主…………
  

#34楼 2013-05-13 12:02 zkh_elab  

忘了,我用的是友善之臂公司的mini6410 arm11板子…………
  

#35楼 2013-06-11 13:39 jiaquwang  

[img]http://images.cnitblog.com/blog/437810/201306/11133839-d4e635f0cf5c493bb5be6edd7950c851.x-png[/img]
程序运行可以的,拍出来的照片不是很清楚而且还是多张好像,是怎么回事啊?
  

#36楼 2013-06-11 20:56 jiaquwang  

@winnter
你现在解决这个问题了吗?
  

#37楼[楼主] 2013-06-11 23:31 超群天晴  

@jiaquwang
分辨率不对
  

#38楼[楼主] 2013-06-11 23:37 超群天晴  

@zkh_elab
程序有没有仔细看 可能是像素格式的不兼容的问题
  

#39楼 2013-06-12 10:25 jiaquwang  

@超群天晴
你看下我的摄像头分辨率,我设置为640*480出现的是[img]http://images.cnitblog.com/blog/437810/201306/12102425-9d6e08e72bb94dbe99871727b5e20561.x-png[/img]
[img]http://images.cnitblog.com/blog/437810/201306/12102443-433fed21c4a843c2a2e20457b1f8e568.x-png[/img]
你可以看下这两张图片
  

#40楼[楼主] 2013-06-12 10:30 超群天晴  

@winnter
你的摄像头在xp上 能用吗
  

#41楼[楼主] 2013-06-12 10:30 超群天晴  

@jiaquwang
最大是160x120,你得改程序了
  

#42楼 2013-06-12 10:35 jiaquwang  

@超群天晴
改程序的分辨率还是那一部分呢?
  

#43楼 2013-06-12 10:37 jiaquwang  

摄像头给出的参数不是640*480吗?为什么显示最大的分辨率是160*120呢?我是在mini2440实现的
  

#44楼[楼主] 2013-06-12 10:38 超群天晴  

@jiaquwang
商家黑你的
  

#45楼 2013-06-12 14:37 jiaquwang  

@超群天晴
用yuyv viewer打开的图像也不是很清楚是怎么回事?谢谢
  

#46楼[楼主] 2013-06-12 18:41 超群天晴  

@jiaquwang
怎么不清楚?图像分辨率不对吧
  

#47楼 2013-06-13 08:43 jiaquwang  

@超群天晴
分辨率我设置为160 120了,也不行~!
  

#48楼[楼主] 2013-06-13 09:57 超群天晴  

@jiaquwang
程序中有多处需要设置图像大小,比如bmp头,比如数据buffer。看看代码吧
  

#49楼 2013-06-13 10:16 jiaquwang  

我将程序中使用的都以宏文件代替的,代码我也看了~!
  

#50楼 2013-06-13 13:30 dasanhao  

我用你的代码在我的电脑上调试,编译没有错误,生成./a.out文件,当我执行./a.out时,出现open /usr/image_bmp.bmp error 这是怎么回事啊?

评论

#51楼 2013-06-13 13:59 dasanhao  

知道了 /usr这里是不可写的
  

#52楼 2013-06-14 10:05 dasanhao  

在zedboadr上检测不到/dev/vodeo0,是怎么回事?zedboard上使用的事sd卡自带的官方系统
  

#53楼[楼主] 2013-06-14 14:32 超群天晴  

@dasanhao
ls /dev 有没有video0?
  

#54楼 2013-06-14 15:13 dasanhao  

您好,我想问下在zedboard上是不是还需要v4l2的驱动 啊???先谢谢了!!!
  

#55楼[楼主] 2013-06-14 18:04 超群天晴  

@dasanhao
如果内核没修改编译过 就不需要 OOB的内核我看过 已经支持V4l2了
  

#56楼 2013-06-19 16:56 黄志刚  

@winnter
我遇到 了和你一样的情况,纠结的看了几个小时代码之后,实在没找到错误的解决办法,最后重启电脑,在运行程序就OK 了,,,我....
  

#57楼 2013-07-05 21:05 Nestler  

放到ARM上果断好用,我在找个压缩到jpeg的,嘿嘿,谢啦~
  

#58楼[楼主] 2013-07-06 20:35 超群天晴  

@Nestler
看我其他几篇,有mjpeg编码的
  

#59楼 2013-07-09 12:09 LongStyle  

楼主 我用的开发板不是ZedBoard 而是TI 的AM3359Starter Kit,640X480的图像采不出来,320X240的可以,USB Camera是直接连接在开发板上的,没用集线器。我怀疑是USB没有工作在high speed模式下。麻烦你看下你的内核配置有没有选择device drivers->usb support下的EHCI和OHCI选项,我好知道是不是我内核配置的问题,谢谢~
  

#60楼 2013-07-24 16:22 hupeiice  

在ubuntu 下运行正常:
driver: uvcvideo
card: USB2.O YW200C CAMERA
bus_info: usb-0000:00:1a.0-1.2
version: 197134
capabilities: 4000001
Device /dev/video0: supports capture.
Device /dev/video0: supports streaming.
Support format:
1.YUV 4:2:2 (YUYV)
fmt.type: 1
pix.pixelformat: YUYV
pix.height: 480
pix.width: 640
pix.field: 1
init /dev/video0 [OK]
grab yuyv OK
GRAB is 1
grab ok
save /usr/image_yuv.yuvOK
change to RGB OK
save /usr/image_bmp.bmpOK


但是图片无法打开提示:
Could not load image 'image_bmp.bmp'.
Premature end-of-file encountered。

请问这是什么原因导致的???
谢谢。
  

#61楼 2013-07-24 16:27 hupeiice  

直接用你的v4l2grab_Anysize,获取的图片打开提示:
Could not load image 'image_bmp.bmp'.
BMP image has bogus header data.
  

#62楼 2013-08-19 10:44 eastgeneral  

相当了得,学习了,
  

#63楼 2013-09-25 18:17 wolf-uncle  

楼主,我用pc测试了一下你的程序,得到的bmp文件大小是680x480x3 = 900kb的,而实际上显示的分辨率是0x640,楼主有遇到过吗,就是你提供的demo程序。
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
Android Camera HAL设计初步
ffmpeg AVFilter介绍
FFmpeg filter HOWTO
android camera(四):camera 驱动 GT2005
Hi3559AV100外接UVC/MJPEG相机实时采图设计(二):V4L2接口的实现(以YUV422为例)
发烧友实测 | 用A40i开发板FFmpeg的安装及测试
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服