新手学习CE下相机开发,请多指教

GoldenSword 2009-07-31 10:35:18
各位大侠,我最近需要在CE下采集图片,以前没有做过CE下与硬件相关的程序,不知道怎么入手,通过拜读各位大侠的提问、建议和博客,有了稍微的了解,我的看和问题如下:
1. 直接写一个CE应用程序,调用驱动相应的功能即可,调用驱动是使用 HANDLE m_hCameraFile = CreateFile(_T("CIS1:"), GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,0,0); 这样的方式吗?如果是这样我随后通过调用DeviceIoControl函数获取图像信息和数据时应该使用那些参数?或者我从哪些地方可以找到这些参数?
2. 我看了BSP源码,其中有camera.cpp文件,应该是相机的驱动吧?这个文件编译后在操作系统里生成的目标是什么文件呢?我可以直接调用其中的 CIS_XXXX函数实现采集图片的功能吗?如果可以,是用CreateFile还是LoadLib?
3. 是否可以直接修改BSP,修改camera.cpp文件来实现采集图片的功能?

这里提问一个帖子我最高只能给100分,如果分不够我可以再开几个,分不是问题。
另外,最近搞嵌入式的逐渐火热起来了,可是大部分兄弟姐妹都在黑暗中摸索,希望能够组织起来搞个系统的学习材料,推动这方面的发展,善莫大焉~
...全文
512 点赞 收藏 29
写回复
29 条回复
csyu85 2010年05月25日
顶一下
回复 点赞
alltheway2004 2010年03月04日
为什么2440 camera wince 5.0下取的YCBCR420数据转成RGB会错位呢?整了一个多星期了,请问各位大侠是什么问题呢?
回复 点赞
rambowu 2009年09月26日
学习了
回复 点赞
yzbsd 2009年08月06日
lz,等待中....
回复 点赞
bobo_2003 2009年08月06日
帮顶
回复 点赞
GoldenSword 2009年08月06日
终于搞定了,这里总结一下我的心得
1. 在2440板中,BSP提供的驱动程序源代码为camera.cpp文件,其中实现了对相机的控制和外部程序调用的接口;
2. 正如各位老大的说明,驱动程序在CIS_IOControl接口函数中实现外部程序调用的功能,包括开始、停止和获取最新帧数据等;
3. 应用程序需要使用相机时,调用CreateFile(_T("CIS1:"), GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,0,0); 函数获取控制相机的句柄;
4. 调用DeviceIoControl(m_hCameraFile,CAM_IOCTL_MOVIE_START,NULL,0,NULL,0,&dwBytesReceive,NULL); 来启动相机采集;
5. 调用DeviceIoControl(m_hCameraFile,CAM_IOCTL_MOVIE_STOP,NULL,0,NULL,0,&dwBytesReceive,NULL); 来停止采集数据;
6. 调用 DeviceIoControl(m_hCameraFile,
CAM_IOCTL_GET_LATEST_FRAME,
NULL,
0,
m_pYUVBuffer,
(CIF_XSIZE*CIF_YSIZE+CIF_XSIZE*CIF_YSIZE/2+sizeof(YUVINFO)),
&dwBytesReceive,
NULL); 函数来获取最新一帧的图像数据,数据为YUV420结构,如需显示,需调用rgb420_to_rgb24函数转换为RGB格式,然后用StretchDIBits来绘制位图,或者存为位图图片;
7. 可定时调用6中的函数并绘制出来实现图片预览,可以方便地控制频率和预览位置,但是比调用驱动中的预览功能慢一些,CPU占用也多一些;
8. 调用驱动的预览功能使用 DeviceIoControl(m_hCameraFile,
IOCTL_CAM_SETGAMMA,
NULL,
0,
&chPrevEnable,
1,
&dwBytesReceive,
NULL); 函数来实现。
9. 厂家给我的BSP源码里面相机的驱动程序源代码camera.cpp代码组织极烂,不知道是没责任心还是咋回事,如果有清晰的结构,简单扼要的注释将对初学者有莫大的帮助。
10. 正如各位老大所说的,多看驱动源代码是很有帮助的,看懂了还可以自己重写一下,可以实现很多特别的功能。

总结就这么多了,能够搞到这个样子与各位的帮助是分不开的,在此感谢各位了;另外如今网络很发达,多用搜索引擎会有意想不到的好处;
到目前,遗留的问题还很多,听说通过调用CAM_IOCTL_SAMSUNG_CAM_PR可以直接获取到RGB数据,还没有试通,如果真能直接得到RGB数据将大大提高效率,留待后续研究。。。
回复 点赞
GoldenSword 2009年08月05日
感谢hitszj604的回复,死机的问题已经找到了,我在调用CAM_IOCTL_GET_LATEST_FRAME时传入的地址是直接定义的数组,而不是用new或者malloc动态分配的,因为驱动dll与应用程序不是同一个地址空间,不能共用栈,只能用堆内存。现改正后正常了。
现在剩下的问题是YUV420转为RGB的问题,快试出来了,很快就要结贴了,感谢大家的帮助。做好后我会上传源码的。
回复 点赞
GoldenSword 2009年08月05日
YUV转RGB搞定了
http://topic.csdn.net/u/20080303/20/60e42929-8f24-40e1-98cc-55083089a3b1.html
回复 点赞
GoldenSword 2009年08月04日
太失望了,真的没人会吗?
回复 点赞
hitszj604 2009年08月04日
程序忘加了个BytePerLine = width*3
U32 ImgSize = width*height
回复 点赞
hitszj604 2009年08月04日
我也是新手,把我想到的告诉你吧,不一定对。

首先是调用CAM_IOCTL_GET_LATEST_FRAME,调用这个则会执行Copy_Cam_Image,这里面就是把你得到图像存到你指定的buffer里。你没说你用的平台是什么,应该就是三星的芯片吧。那么一般默认是输出ycbcr格式的,你可以把这个采集到的图像转为rgb在加个头,就生成bmp。至于死机的问题,这个不太清楚,还是建议你好好看看Copy_Cam_Image里的代码,肯定是这里的问题。


其次,你说你得到的是噪声,第一要看看你采集到的是不是rgb的图像,这个你可以直接把采集到的grb图像用UE打开,直接添加文件头,看有没有图想,就知道正确与否了。
然后看你的头文件那个函数家的对不对,下面是我用的函数,已经验证过了,是好用的。

就这些啦 好运吧




unsigned char *WRGB;
WRGB = (unsigned char*)malloc(BytePerLine*height+54);

unsigned char* WRGB_Start=NULL;

// unsigned char* rgb=new U8[3*ImgSize+54] ;

memset(WRGB, 0, BytePerLine*height+54);
RETAILMSG(MSG_EN_1,(TEXT("5\r\n")));
//BMP头
WRGB[0] = 'B';
WRGB[1] = 'M';
*((unsigned int*)(WRGB+2)) = BytePerLine*height+54;
*((unsigned int*)(WRGB+10)) = 54;
*((unsigned int*)(WRGB+14)) = 40;
*((unsigned int*)(WRGB+18)) = width;
*((unsigned int*)(WRGB+22)) = height;
*((unsigned short*)(WRGB+26)) = 1;
*((unsigned short*)(WRGB+28)) = 16;
*((unsigned int*)(WRGB+34)) = BytePerLine*height;


// for(i=0;i<54;i++,WRGB++) RETAILMSG(MSG_EN_1,(TEXT(" 0x%X "),*WRGB));



WRGB_Start = WRGB + 54;

for(y=height-1,j=0; y > 0; y--,j++)
{ //RETAILMSG(MSG_EN_1,(TEXT("height=%d ,y= %d \r\n"),height,y));
for(x=0,i=0; x<width; x++)
{//RETAILMSG(MSG_EN_1,(TEXT("width=%d ,x= %d \r\n"),width,x));
WRGB_Start[y*BytePerLine+i++] = B[j*width+x];
WRGB_Start[y*BytePerLine+i++] = G[j*width+x];
WRGB_Start[y*BytePerLine+i++] = R[j*width+x];
}
}
回复 点赞
GoldenSword 2009年08月04日
不好意思,太激动了:)
我是调用CAM_IOCTL_GET_LATEST_FRAME后就死机,预览没问题。另外查到调用
DeviceIoControl(m_hCameraFile,CAM_IOCTL_SAMSUNG_CAM_PR,NULL,NULL,&image,NULL,NULL,NULL);
可以得到RGB证缓冲的地址,然后直接存为位图即可。好像得到的RGB为16位值,应该是6:5:6的分配方式,我用下面的函数存为图片,结果是噪声。
BOOL SaveFrameBit2BMPFile(BYTE* pBits,int CX,int CY,CString strFile)
{
BITMAPFILEHEADER fh;
BITMAPINFOHEADER bm;
fh.bfType = 0x4D42;
fh.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER)+CX*CY*2;
fh.bfReserved1 = fh.bfReserved2 = 0;
fh.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);

bm.biSize = sizeof(BITMAPINFOHEADER);
bm.biWidth = CX;
bm.biHeight = CY;
bm.biPlanes = 1;
bm.biBitCount = 16;
bm.biCompression = BI_BITFIELDS;
bm.biSizeImage = CX*CY*2;
bm.biClrUsed = 0;
bm.biClrImportant = 0;

CFile fBmp;
if(fBmp.Open(strFile,CFile::modeCreate|CFile::modeWrite))
{
fBmp.Write(&fh,sizeof(BITMAPFILEHEADER));
fBmp.Write(&bm,sizeof(BITMAPINFOHEADER));
fBmp.Write(pBits,CX*CY*2);
fBmp.Close();

return TRUE;
}

return FALSE;
}

不知道什么地方的问题。
回复 点赞
hitszj604 2009年08月04日
我想不是没人会,我想做过这个摄像头驱动的人在这里有很多人,只是这个问题具体问题具体分析,大家也只是给你一个参考罢了。真正的问题还是你自己解决。

我想知道你说的经常死机是什么意思,是调用CAM_IOCTL_GET_LATEST_FRAME后经常死机,还是一开始预览就死机
回复 点赞
weidong0210 2009年08月03日
学习
回复 点赞
GoldenSword 2009年08月03日
感谢楼上的提示,我再仔细看看这个地方。 没想到这么个简单的功能都不好搞,等我搞出来了一定公开代码~
回复 点赞
hitszj604 2009年08月03日
[Quote=引用 12 楼 goldensword 的回复:]
试了一下,先用 CreateFile(_T("CIS1:"), GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,0,0); 可以打开设备,然后调用
    DeviceIoControl(m_hCameraFile, 
                    IOCTL_CAM_SETGAMMA, 
                    NULL, 
                    0, 
                    &chPrevEnable, 
                    1, 
                    &dwBytesReceive, 
                    NULL); 

ret1 = ::DeviceIoControl(m_hCameraFile,CAM_IOCTL_MOVIE_START,NULL,0,NULL,0,&dwBytesReceive,NULL);
可以看到预览的图像

但是调用    DeviceIoControl(m_hCameraFile, 
                            CAM_IOCTL_GET_LATEST_FRAME, 
                            NULL, 
                            0, 
                            pImgBuffer, 
                            //(QCIF_XSIZE*QCIF_YSIZE+QCIF_XSIZE*QCIF_YSIZE/2+sizeof(YUVINFO)),                             
                            (QCIF_XSIZE*QCIF_YSIZE+QCIF_XSIZE*QCIF_YSIZE+sizeof(YUVINFO)), 
                            &dwBytesReceive, 
                            NULL); 
时经常死机。


继续研究中。。。

[/Quote]




你这个死机的问题我也遇到过,好好看看你的buffer地址,是正确,如果这个地址错误,则采集到的图像复制到你buffer中就有可能因为存到了其他地方,当值内存分配混乱,影响到系统了。这是我的个人理解啊。
回复 点赞
GoldenSword 2009年08月03日
没人会呀?自己up一下~~~
回复 点赞
GoldenSword 2009年08月01日
试了一下,先用 CreateFile(_T("CIS1:"), GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,0,0); 可以打开设备,然后调用
DeviceIoControl(m_hCameraFile,
IOCTL_CAM_SETGAMMA,
NULL,
0,
&chPrevEnable,
1,
&dwBytesReceive,
NULL);

ret1 = ::DeviceIoControl(m_hCameraFile,CAM_IOCTL_MOVIE_START,NULL,0,NULL,0,&dwBytesReceive,NULL);
可以看到预览的图像

但是调用 DeviceIoControl(m_hCameraFile,
CAM_IOCTL_GET_LATEST_FRAME,
NULL,
0,
pImgBuffer,
//(QCIF_XSIZE*QCIF_YSIZE+QCIF_XSIZE*QCIF_YSIZE/2+sizeof(YUVINFO)),
(QCIF_XSIZE*QCIF_YSIZE+QCIF_XSIZE*QCIF_YSIZE+sizeof(YUVINFO)),
&dwBytesReceive,
NULL);
时经常死机。


继续研究中。。。
回复 点赞
aaaadfdf 2009年08月01日
如果是流接口的话 CreateFile可以打开设备,进行下一步操做

2、wince的驱动编译过后 ,生成的=是DLL文件,如果是在上层应用程序里面调用的话就要看OS给出的接口了! 比如
CreateFile 就是,->CreateFile--> OS --->XXX_Open.
ReadFile()---> XXX_Read(
writeFile()-->XXX_write
deviceIOcontrol()-->XXX_IOControl


3 BSP当然可以修改,但 要实现你的功能就不找这么做了 ,没做过camer的driver
回复 点赞
xqhrs232 2009年07月31日
多看例子CAMERA驱动
回复 点赞
发动态
发帖子
嵌入开发(WinCE)
创建于2007-09-28

8178

社区成员

4.1w+

社区内容

硬件/嵌入开发 嵌入开发(WinCE)
社区公告
暂无公告