c#基于opencv,开发摄像头播放程序
前言
Windows下实现摄像视频捕捉有多种实现方式;各种方式的优劣,本文不做对比。但是,opencv是一款老牌开发库,在图像处理领域声名显赫。采用opencv来处理摄像视频,在性能和稳定性上,是有保障的。并且,opencv包含很多图像处理函数,可以更方便的对视频处理。
执行程序是用wpf开发的,所以先将opencv封装成c语言接口,以供调用。opencv也不可能提供现成的控件供wpf使用,两种不同的开发语言“沟通”起来有些困难。其实稍作变通,就可以实现摄像头播放功能。
1对opencv封装
opencv的类VideoCapture封装了对摄像头的操作,使用起来也非常简单。
boolopen(intdevice); device为摄像头设备序号。
如果有多个摄像头,怎么知道哪个摄像头的序号那?可以通过如下函数,获取摄像头列表。摄像头在list中索引即为设备序号。
intGetCameraDevices(vector&list) { ICreateDevEnum*pDevEnum=NULL; IEnumMoniker*pEnum=NULL; intdeviceCounter=0; CoInitialize(NULL); HRESULThr=CoCreateInstance(CLSID_SystemDeviceEnum,NULL, CLSCTX_INPROC_SERVER,IID_ICreateDevEnum, reinterpret_cast (&pDevEnum)); if(SUCCEEDED(hr)) { //Createanenumeratorforthevideocapturecategory. hr=pDevEnum->CreateClassEnumerator( CLSID_VideoInputDeviceCategory, &pEnum,0); if(hr==S_OK){ //if(!silent)printf("SETUP:LookingForCaptureDevices\n"); IMoniker*pMoniker=NULL; while(pEnum->Next(1,&pMoniker,NULL)==S_OK){ IPropertyBag*pPropBag; hr=pMoniker->BindToStorage(0,0,IID_IPropertyBag, (void**)(&pPropBag)); if(FAILED(hr)){ pMoniker->Release(); continue;//Skipthisone,maybethenextonewillwork. } //Findthedescriptionorfriendlyname. VARIANTvarName; VariantInit(&varName); hr=pPropBag->Read(L"Description",&varName,0); if(FAILED(hr)) hr=pPropBag->Read(L"FriendlyName",&varName,0); if(SUCCEEDED(hr)){ hr=pPropBag->Read(L"FriendlyName",&varName,0); intcount=0; wstringstr2=varName.bstrVal; list.push_back(str2); } pPropBag->Release(); pPropBag=NULL; pMoniker->Release(); pMoniker=NULL; deviceCounter++; } pDevEnum->Release(); pDevEnum=NULL; pEnum->Release(); pEnum=NULL; } } returndeviceCounter; }
总之,使用opencv打开摄像头非常简单。
打开之后,就是获取摄像头图像。视频其实就是图像的集合;每秒钟获取25幅图像,将其在控件上显示,就是视频。
MatcameraImg; _pCapture>>cameraImg;
Mat类封装了对图像的操作。c#不可能操作Mat,需要将Mat中纯图像部分数据传递出来,图像才能被c#利用。
intCamera_GetImgData(INT64handle,char*imgBuffer) { CameraInfo*pCameraInfo=(CameraInfo*)handle; MatcameraImg; *(pCameraInfo->_pCapture)>>cameraImg; if(!cameraImg.empty()) { intheight=cameraImg.rows;intdataLen=height*cameraImg.step; memcpy(imgBuffer,cameraImg.data,dataLen); return0; } else { return1; } }
cameraImg.data中存有图像数据,data的大小可以根据图像的高度、每行图像的步幅计算出来。c#调用此函数后,imgBuffer存放图像数据。对数据imgBuffer处理后,就可以在控件上显示。
c语言对opencv封装函数列表如下:
extern"C" { OpenCVCamera_APIintCamera_GetCameraName(char*listName); OpenCVCamera_APIINT64Camera_CreateHandle(); OpenCVCamera_APIvoidCamera_CloseHandle(INT64handle); OpenCVCamera_APIBOOLCamera_IsOpen(INT64handle); OpenCVCamera_APIintCamera_Open(INT64handle,intindex); OpenCVCamera_APIintCamera_Close(INT64handle); OpenCVCamera_APIintCamera_GetImgInfo(INT64handle,int&width,int&height,int&channel, int&step,int&depth); OpenCVCamera_APIintCamera_GetImgData(INT64handle,char*imgBuffer); //flipCode>0:沿y-轴翻转,0:沿x-轴翻转,<0:x、y轴同时翻转 OpenCVCamera_APIintCamera_GetImgData_Flip(INT64handle,char*imgBuffer,intflipCode); OpenCVCamera_APIintCamera_ImgData_Compress(introws,intcols,inttype,void*imgBuffer, intparam,void*destBuffer,int*destLen); }
2WPF实现视频播放
WPF的Image控件实现图像的显示。实现视频播放的逻辑为:设定一个定时器(时间间隔为40毫秒),每隔一段时间从opencv获取图像,在控件中显示。
实现图像显示代码
BitmapSourcebitmapSource=_openCVCamera.GetBitmapSource(); if(bitmapSource==null) returnfalse; imageVideoPlayer.Source=bitmapSource;
实现图像显示的关键是构建BitmapSource,暨:如何从opencv中获取图像数据构建BitmapSource。
//获取图像数据 if(!GetImgData(outbyte[]imgData)) returnnull; //构建WriteableBitmap WriteableBitmapimg=newWriteableBitmap(_imgWidth,_imgHeight,96,96,PixelFormats.Bgr24,null); img.WritePixels(newInt32Rect(0,0,_imgWidth,_imgHeight), imgData,img.BackBufferStride,0); img.Freeze();
至此,就可以显示摄像头图像了。
以上就是c#基于opencv,开发摄像头播放程序的详细内容,更多关于c#opencv摄像头播放的资料请关注毛票票其它相关文章!
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。