用OpenCV进行大恒CG400CG410视频采集卡的视频读取 

  (2013-04-27 16:12:02) 


 分类: opencv 

 最近用到红外摄像头,要用到视频采集卡,采用的是大恒CG410的板子,CG410是CG400的升级版,虽然驱动不一样,SDK和适用环境是一样的。这是使用的是win7 32位系统。 

 大恒的SDK的事例都是都是MFC的代码,奈何我需要的是在控制台下进行摄像头的读取,并转换到OpenCV可以识别的图像数据格式IplImage或者Mat结构,这个使用的是前者。 

 下面是解决方法: 

 在项目的库中包含 

 CGVideo.lib  

 CGVidEx.lib 

 头文件记得加入windows.h,因为要使用到windows句柄 

 代码如下: 

 1: #include "opencv2/core/core.hpp" 

 2: #include "opencv2/highgui/highgui.hpp" 

 3: #include "opencv2/imgproc/imgproc.hpp" 

 4: #include "opencv2/video/video.hpp" 

 5: #include <iostream> 

 6: #include <windows.h> 

 7:  

 8: #include "CGVideo.h" 

 9: #include "CGDef.h" 

 10: #include "CGVidEx.h" 

 11:  

 12: using namespace std; 

 13: using namespace cv; 

 14:  

 15: int main() 

 16: { 

 17: //初始化所有成员变量,同时打开图像卡 */ 

 18: CGSTATUS status = CG_OK; 

 19: HCG hcg = NULL; 

 20: 

 21: //打开图像卡 1,返回状态值 

 22: status = BeginCGCard(1, &hcg); 

 23: 

 24: //检验函数执行状态,如果失败,则返回错误状态消息框*/ 

 25: CG_VERIFY(status); 

 26: 

 27: //初始化图像卡硬件状态,用户也可以在其他位置初始化图像卡, 

 28: //但应保证图像卡已经打开,建议用户在应用程序初始化时,同时初始化图像卡硬件。 

 29: // 设置视频制式(PAL / NTSC),由当前视频源制式决定 

 30: CGSetVideoStandard(hcg, PAL); 

 31:  

 32: // 扫描模式,包括 FRAME、FIELD 

 33: CGSetScanMode(hcg, FRAME); 

 34: 

 35: //晶振,包括CRY_OSC_35M、CRY_OSC_28M 

 36: //对于DH-CG300图像卡,一般为CRY_OSC_35M, 

 37: //对于DH-QP300图像卡,一般为CRY_OSC_28M, 

 38: //其他类型图像卡没有此硬件设置,但可以调用此接口,并返回CG_NOT_SUPPORT_INTERFACE信息 

 39: 

 40: CGSelectCryOSC(hcg, CRY_OSC_35M); 

 41: 

 42: //视频格式,即采集图像数据描述方式,包括YUV422、RGB888、RGB565、RGB555、RGB8888、ALL8BIT、LIMITED8BIT, 

 43: //在采集图像到屏幕时,需要保证视频格式和当前系统屏幕位深度一致,而采集到 内存没有此限制。 

 44: CGSetVideoFormat(hcg, RGB888); 

 45: 

 46: 

 47: //视频源路VIDEO_SOURCE包括视频类型和序号, 

 48: //各种图像卡支持的视频源路不尽相同,请参看相应硬件说明 

 49: VIDEO_SOURCE source; 

 50: source.type = COMPOSITE_VIDEO; //视频类型为复合视频 

 51: source.nIndex = 0; //序号为0 

 52: CGSetVideoSource(hcg, source); 

 53: 

 54: //视频输入窗口,即视频输入范围,输入窗口取值范围: 

 55: //对于视频制式为PAL制,水平方向为0-768,垂直方向为0-576 

 56: //对于视频制式为NTSC制,水平方向为0-768,垂直方向为0-576 

 57: //视频窗口左上角X坐标和窗口宽度应为4的倍数,左上角Y坐标和窗口高度应为2的倍数 

 58: CGSetInputWindow(hcg, 0, 0, 768, 576); //视频输入窗口取最大 

 59:  

 60: 

 61: //视频输出窗口,即视频输出范围,输出窗口取值范围必须在输入窗口范围以内, 

 62: //视频窗口左上角X坐标和窗口宽度应为4的倍数,左上角Y坐标和窗口高度应为2的倍数 

 63: //在采集到屏幕时,输出窗口的起始位置为图像屏幕输出位置的屏幕坐标, 

 64: //在采集到内存时,输出窗口的起始位置设置为(0, 0)即可。 

 65: 

 66: CGSetOutputWindow(hcg, 0, 0, 768, 576); 

 67:  

 68: //初始化BITMAPINFO 结构指针 

 69: BITMAPINFO *pBmpInfo = NULL; 

 70: BYTE *pInfoBuffer = NULL; 

 71: BYTE *pImageBuffer = NULL; //BIMTAPINFO 存储缓冲区,m_pBmpInfo即指向此缓冲区 

 72:  

 73: BYTE *pStaticBuffer = NULL; //静态内存地址指针 

 74: HANDLE handle = NULL; //静态内存描述句柄 

 75: 

 76: //采集1帧图像到内存,采集完成后停止 

 77: while (TRUE) 

 78: { 

 79: status = CGSnapShot(hcg, 0, 0, TRUE, 1); 

 80: CG_VERIFY(status); 

 81:  

 82: if (CG_SUCCESS(status)) 

 83: { 

 84: pInfoBuffer = new BYTE[sizeof(BITMAPINFO)]; 

 85: if (pInfoBuffer) 

 86: { 

 87: //m_pBmpInfo即指向m_chBmpBuf缓冲区,用户可以自己分配BTIMAPINFO缓冲区 

 88: 

 89: pBmpInfo = (BITMAPINFO *)pInfoBuffer; 

 90: 

 91: 

 92: //初始化BITMAPINFO 结构,此结构在保存bmp文件、显示采集图像时使用 

 93: 

 94: pBmpInfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); 

 95: 

 96: //图像宽度,一般为输出窗口宽度 

 97: pBmpInfo->bmiHeader.biWidth = 768; 

 98: 

 99: //图像高度,根据扫描模式(FRAME/FIELD)的不同 

 100: //FRAME制下,一般为输出窗口高度 

 101: //FIELD制下,一般为输出窗口高度的一半 

 102: pBmpInfo->bmiHeader.biHeight = 576; 

 103: 

 104: //图像位深度,由视频格式确定, 

 105: //采集图像视频格式有RGB565、RGB555、RGB888、ALL8BIT等, 

 106: //如果使用CGDateTransfrom函数,则将15,16位数据转换为24位 

 107: pBmpInfo->bmiHeader.biBitCount = 24; 

 108: 

 109: //以下设置一般相同, 

 110: //对于低于8位的位图,还应设置相应的位图调色板 

 111: pBmpInfo->bmiHeader.biPlanes = 1; 

 112: pBmpInfo->bmiHeader.biCompression = BI_RGB; 

 113: pBmpInfo->bmiHeader.biSizeImage = 0; 

 114: pBmpInfo->bmiHeader.biXPelsPerMeter = 0; 

 115: pBmpInfo->bmiHeader.biYPelsPerMeter = 0; 

 116: pBmpInfo->bmiHeader.biClrUsed = 0; 

 117: pBmpInfo->bmiHeader.biClrImportant = 0; 

 118:  

 119: //分配图像缓冲区,一般用来存储采集图像 

 120: //用户可以将设备静态内存的图像数据直接通过指针或 

 121: //用CGDataTransfrom函数拷贝到图像缓冲区,然后做进一步的处理, 

 122: //一般图像缓冲区大小由输出窗口大小和视频格式确定。 

 123: pImageBuffer = new BYTE[768 * 576 * 3]; 

 124: if (pImageBuffer) 

 125: { 

 126: //锁定指定位置的静态内存, 

 127: //偏移由图像大小和图像序号确定,锁定大小为图像大小 

 128: //用户可以在任何时候锁定指定位置的静态内存,然后通过pLinearAddr指针访问相应的内存。 

 129: status = CGStaticMemLock(0, 768 * 576 * 3, &handle, (VOID **)&pStaticBuffer); 

 130: if (CG_SUCCESS(status)) 

 131: { 

 132: 

 133: //将静态内存中的图像传递到用户缓冲区,同时进行格式转换。 

 134: //如果静态内存中图像为15、16、32位,则转换为24位。 

 135: //由于图像卡采集到静态内存的图像数据是正向存放, 

 136: //而Windows中处理的位图数据需要倒置,因此一般还要将图像倒置。 

 137: CGDataTransform(pImageBuffer, //图像缓冲区 

 138: pStaticBuffer, //静态内存 

 139: 768, //图像宽度 

 140: 576, //图像高度 

 141: 24, //图像位深度 

 142: TRUE //是否倒置图像 

 143: ); 

 144: CGStaticMemUnlock(handle); //解除静态内存锁定 

 145: } 

 146:  

 147: CvSize n_size = cvSize(768,576); 

 148: IplImage* frame = cvCreateImageHeader( n_size, IPL_DEPTH_8U, 3 ); 

 149: frame->imageData = (char *)pImageBuffer; 

 150: cvNamedWindow( "test", CV_WINDOW_AUTOSIZE ); 

 151: cvShowImage("test",frame); 

 152: cvWaitKey(20); 

 153: 

 154: delete []pImageBuffer; //释放图像缓冲 

 155: cvReleaseImage(&frame); 

 156: } 

 157:  

 158: delete []pInfoBuffer; //释放文件信息缓冲 

 159: } 

 160: } 

 161:  

 162: } 

 163: // 关闭图像卡1 

 164: status = EndCGCard(hcg); 

 165: CG_VERIFY(status); 

 166: } 

   



 关于大恒图像采集卡的使用 

 昨天终于可以采集图像并显示了,那个高兴啊~ 



 总结了一下使用的步骤(图像采集卡是 大恒 CG410) 



 使用 CGStartSnap 和 CGEndSnap 组合来控制开始和停止图像采集的步骤如下: 



 1、定义一个全局的设备句柄 



     HCG m_hcg; 



 2、打开图像采集卡 



     CGSTATUS status = CG_OK; 

     //    打开图像卡 1 

     status = BeginCGCard(1, &m_hcg); 

     //    检验函数执行状态,如果失败,则返回错误状态消息框 

     CG_VERIFY(status); 



 3、初始化图像采集卡硬件参数 



     //保证图像卡已经打开 

     //设置视频制式(PAL / NTSC),由当前视频源制式决定 

     CGSetVideoStandard(m_hcg, PAL);         



     //视频格式,即采集图像数据描述方式,     

    //YUV422、RGB888、RGB565、RGB555、RGB8888、ALL8BIT、LIMITED8BIT, 

    //采集图像到屏幕时,需要保证视频格式和当前系统屏幕位深度一致 

     CGSetVideoFormat(m_hcg, RGB888); 



     //扫描模式,包括 FRAME、FIELD 

     CGSetScanMode(m_hcg, FRAME); 



     // 设置视频源路, 

     VIDEO_SOURCE source; 

     source.type        = COMPOSITE_VIDEO;        //视频类型为复合视频 

     source.nIndex    = 0;                    //序号为0 

     CGSetVideoSource(m_hcg, source); 



     //频输入窗口,即视频输入范围,输入窗口取值范围: 

     //PAL (0-768,0-576 );NTSC(0-640,0-480) 

     //视频窗口左上角X坐标和窗口宽度应为4的倍数,左上角Y坐标和窗口高度应为2的倍数 

     CGSetInputWindow(m_hcg, 0, 0, 768, 576);    //视频输入窗口取最大 



     //视频输出窗口,即视频输出范围,输出窗口取值范围必须在输入窗口范围以内, 

     //视频窗口左上角X坐标和窗口宽度应为4的倍数,左上角Y坐标和窗口高度应为2的倍数 

     //在采集到屏幕时,输出窗口的起始位置为图像屏幕输出位置的屏幕坐标, 

     //在采集到内存时,输出窗口的起始位置设置为(0, 0)即可。 

     CGSetOutputWindow(m_hcg, 0, 0, 400, 300); 



 4、启动采集图像到内存 



     //   启动图像卡采集图像到内存 

     //   指定图像卡将图像采集到静态内存偏移为0的位置, 

     // 采集缓冲区大小为2幅图像大小 

     status = CGStartSnap(m_hcg, 0, TRUE, 2); 

     CG_VERIFY(status);     

      

     //获取当前正在采集的图像场,判定哪一帧图像已经采集完毕,可以进行处理 

     status = CGGetSnappingNumber(m_hcg, &nStatus); 



 5、读出图像数据 



     status = CGStaticMemLock(dwImageSize * nNumber, dwImageSize, &handle, (VOID **)&pStaticBuffer); 

     if (CG_SUCCESS(status))  

     { 

         /* 

         *    将静态内存中的图像传递到用户缓冲区,同时进行格式转换。 

         *    如果静态内存中图像为15、16、32位,则转换为24位。 

         *    由于图像卡采集到静态内存的图像数据是正向存放, 

         *    而Windows中处理的位图数据需要倒置,因此一般还要将图像倒置。 

         */ 

         CGDataTransform(pImageBuffer, pStaticBuffer, 400, 300, 24, TRUE); 

         CGStaticMemUnlock(handle);        //解除静态内存锁定 

     } 



 6、结束读取过程 



     status = CGStopSnap(m_hcg); 

     CG_VERIFY(status); 



 7、关闭图像采集卡 



     CGSTATUS status = CG_OK; 

     //    关闭图像卡,释放图像卡内部资源 

     status = EndCGCard(m_hcg); 

     CG_VERIFY(status);