新手学习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分,如果分不够我可以再开几个,分不是问题。
另外,最近搞嵌入式的逐渐火热起来了,可是大部分兄弟姐妹都在黑暗中摸索,希望能够组织起来搞个系统的学习材料,推动这方面的发展,善莫大焉~
...全文
548 29 打赏 收藏 转发到动态 举报
写回复
用AI写文章
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);
时经常死机。


继续研究中。。。
-小仙- 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驱动
加载更多回复(9)

19,500

社区成员

发帖
与我相关
我的任务
社区描述
硬件/嵌入开发 嵌入开发(WinCE)
社区管理员
  • 嵌入开发(WinCE)社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧