主题 : 摄像头采集照片的问题 复制链接 | 浏览器收藏 | 打印
级别: 新手上路
UID: 30022
精华: 0
发帖: 17
金钱: 85 两
威望: 17 点
综合积分: 34 分
注册时间: 2010-10-10
最后登录: 2012-05-21
楼主  发表于: 2011-03-22 18:43

 摄像头采集照片的问题

用ZC0301的芯片,在Linux环境下运行以下代码,希望用摄像头拍出并保存一张照片在硬盘里(PPM格式的),结果保存的图片打开后无任何信息。请问是哪里出错了?
#include<unistd.h>
#include<stdio.h>
#include<stdlib.h>
#include<sys/mman.h>
#include<error.h>
#include<sys/ioctl.h>
#include<fcntl.h>
#include<sys/types.h>
#include<linux/videodev.h>
#define DEFAULT_DEVICE "/dev/video0"
#define VIDEO_MAXFRAME 2

typedef struct _V4L_struct
{
    int fd;
    struct video_capability capability;
    struct video_buffer buffer;
    struct video_picture picture;
    struct video_tuner tuner;
    struct video_mmap mmap;
    struct video_mbuf mbuf;
    unsigned char *map;
    int frame_current;
    int frame_using[VIDEO_MAXFRAME];
} v4l_device;

int v4l_get_capability(v4l_device *vd)    // 获取摄像头的信息
{
    if(ioctl(vd->fd,VIDIOCGCAP,&(vd->capability))<0)
    {
        perror("v4l_get_capability:");
        return -1;
    }
    printf("           camera name:%s\n",vd->capability.name);
    printf("           camera type:%d\n",vd->capability.type);
    printf("           camera channel:%d\n",vd->capability.channels);
    printf("           camera audiosz:%d\n",vd->capability.audios);
    printf("           camera maxwidth:%d\n",vd->capability.maxwidth);
    printf("           camera maxheight:%d\n",vd->capability.maxheight);
    printf("           camera minwidth:%d\n",vd->capability.minwidth);
    printf("           camera minheight:%d\n",vd->capability.minheight);
   return 0;

}

int v4l_get_picture(v4l_device *vd) // 图片的信息/
{
    if(ioctl(vd->fd,VIDIOCGPICT,&(vd->picture))<0)
    {
        perror("v4l_get_picture");
        return -1;        
    }
    printf("           brightness:%d\n",vd->picture.brightness);
    printf("           hue:%d\n",vd->picture.hue);
    printf("           color:%d\n",vd->picture.colour);
    printf("           contrast:%d\n",vd->picture.contrast);
    printf("           whiteness:%d\n",vd->picture.whiteness);
    printf("           depth:%d\n",vd->picture.depth);
    printf("           palette:%d\n",vd->picture.palette);
   return 0;

}

int v4l_get_mbuf(v4l_device *vd)
{
    if(ioctl(vd->fd,VIDIOCGMBUF,&(vd->mbuf))<0)
    {
        perror("v4l_get_mbuf:");
        return -1;
    }
    printf("size=%d\n",vd->mbuf.size);
    return 0;
}

int v4l_open(char *dev,v4l_device *vd)
{
    if(!dev) dev=DEFAULT_DEVICE;
    dev=DEFAULT_DEVICE;
    if((vd->fd=open(dev,O_RDWR))<0)
    {
        perror("v4l_open :");
        return -1;
    }
    if(v4l_get_capability(vd)) return -1;
    if(v4l_get_picture(vd)) return -1;
    return 0;
    printf("摄像头打开成功!\n");
}

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;
    }
    printf("内存映射成功!\n");
    return 0;
}

int v4l_grab_frame(v4l_device *vd,int frame)
{
    if(vd->frame_using[frame])
    {
        fprintf(stderr,"v4l_grab_frame:frame %d is already used \n",frame);
        return -1;
    }
    vd->mmap.frame=frame;
    if(ioctl(vd->fd,VIDIOCMCAPTURE,&(vd->mmap))<0)
    {
        perror("v4l_grab_frame");
        return -1;
    }
    vd->frame_using[frame]=1;
    vd->frame_current=frame;
    printf(" 图像抓取成功!\n");
    return 0;
}

int v4l_grab_init(v4l_device *vd,int width,int height)
{
    vd->mmap.width=width;
    vd->mmap.height=height;
    vd->mmap.format=vd->picture.palette;
    vd->frame_current=0;
    vd->frame_using[0]=0;
    vd->frame_using[1]=0;
    return v4l_grab_frame(vd,0);
}


int v4l_save_ppm( unsigned char *p,int x,int y,int depth)
{
    FILE *fp;
    if((fp=fopen("/mnt/hgfs/Linux-Windows/test.ppm","wb+"))==NULL)
    {
        perror("open");
        return -1;
    }
    fprintf(fp,"P6\n%d%d\n255\n",x,y);
    fwrite((unsigned char *)p,x*y*depth,1,fp);
    fclose(fp);
    printf("图像保存成功!\n");
    return 0;
}
    
int main()
{
    v4l_device vd;
    v4l_open(DEFAULT_DEVICE,&vd);
    v4l_mmap_init(&vd);
    v4l_grab_init(&vd,320,240);
    v4l_save_ppm(vd.map,320,240,24);
    return 0;
}
级别: 新手上路
UID: 40813
精华: 0
发帖: 1
金钱: 5 两
威望: 1 点
综合积分: 2 分
注册时间: 2011-03-22
最后登录: 2011-03-22
1楼  发表于: 2011-03-22 21:08
老兄,我也有同样的问题,同求
级别: 侠客
UID: 32246
精华: 0
发帖: 79
金钱: 420 两
威望: 84 点
综合积分: 158 分
注册时间: 2010-11-12
最后登录: 2018-02-08
2楼  发表于: 2011-03-23 18:52
mini6410是用v4l还是v4l2呢??