c#基于opencv,开发摄像头播放程序
前言
windows下实现摄像视频捕捉有多种实现方式;各种方式的优劣,本文不做对比。但是,opencv是一款老牌开发库,在图像处理领域声名显赫。采用opencv来处理摄像视频,在性能和稳定性上,是有保障的。并且,opencv包含很多图像处理函数,可以更方便的对视频处理。
执行程序是用wpf开发的,所以先将opencv封装成c语言接口,以供调用。opencv也不可能提供现成的控件供wpf使用,两种不同的开发语言“沟通”起来有些困难。其实稍作变通,就可以实现摄像头播放功能。
1 对opencv封装
opencv的类videocapture封装了对摄像头的操作,使用起来也非常简单。
bool open(int device); device为摄像头设备序号。
如果有多个摄像头,怎么知道哪个摄像头的序号那?可以通过如下函数,获取摄像头列表。摄像头在list中索引即为设备序号。
int getcameradevices(vector<wstring>& list) { icreatedevenum *pdevenum = null; ienummoniker *penum = null; int devicecounter = 0; coinitialize(null); hresult hr = cocreateinstance(clsid_systemdeviceenum, null, clsctx_inproc_server, iid_icreatedevenum, reinterpret_cast<void**>(&pdevenum)); if (succeeded(hr)) { // create an enumerator for the video capture category. hr = pdevenum->createclassenumerator( clsid_videoinputdevicecategory, &penum, 0); if (hr == s_ok) { //if (!silent)printf("setup: looking for capture devices\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; // skip this one, maybe the next one will work. } // find the description or friendly name. variant varname; 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); int count = 0; wstring str2 = varname.bstrval; list.push_back(str2); } ppropbag->release(); ppropbag = null; pmoniker->release(); pmoniker = null; devicecounter++; } pdevenum->release(); pdevenum = null; penum->release(); penum = null; } } return devicecounter; }
总之,使用opencv打开摄像头非常简单。
打开之后,就是获取摄像头图像。视频其实就是图像的集合;每秒钟获取25幅图像,将其在控件上显示,就是视频。
mat cameraimg; _pcapture >> cameraimg;
mat类封装了对图像的操作。c#不可能操作mat,需要将mat中纯图像部分数据传递出来,图像才能被c#利用。
int camera_getimgdata(int64 handle, char* imgbuffer) { camerainfo *pcamerainfo = (camerainfo*)handle; mat cameraimg; *(pcamerainfo->_pcapture) >> cameraimg; if (!cameraimg.empty()) { int height = cameraimg.rows;int datalen = height * cameraimg.step; memcpy(imgbuffer, cameraimg.data, datalen); return 0; } else { return 1; } }
cameraimg.data中存有图像数据,data的大小可以根据图像的高度、每行图像的步幅计算出来。c#调用此函数后,imgbuffer存放图像数据。对数据imgbuffer处理后,就可以在控件上显示。
c语言对opencv封装函数列表如下:
extern "c" { opencvcamera_api int camera_getcameraname(char* listname); opencvcamera_api int64 camera_createhandle(); opencvcamera_api void camera_closehandle(int64 handle); opencvcamera_api bool camera_isopen(int64 handle); opencvcamera_api int camera_open(int64 handle, int index); opencvcamera_api int camera_close(int64 handle); opencvcamera_api int camera_getimginfo(int64 handle,int& width,int& height,int& channel, int& step, int& depth); opencvcamera_api int camera_getimgdata(int64 handle, char* imgbuffer); //flipcode >0: 沿y-轴翻转, 0: 沿x-轴翻转, <0: x、y轴同时翻转 opencvcamera_api int camera_getimgdata_flip(int64 handle, char* imgbuffer, int flipcode); opencvcamera_api int camera_imgdata_compress(int rows, int cols, int type, void* imgbuffer, int param,void* destbuffer,int* destlen); }
2 wpf实现视频播放
wpf的image控件实现图像的显示。实现视频播放的逻辑为:设定一个定时器(时间间隔为40毫秒),每隔一段时间从opencv获取图像,在控件中显示。
<image x:name="imagevideoplayer" stretch="uniform" ></image>
实现图像显示代码
bitmapsource bitmapsource = _opencvcamera.getbitmapsource(); if (bitmapsource == null) return false; imagevideoplayer.source = bitmapsource;
实现图像显示的关键是构建bitmapsource,暨:如何从opencv中获取图像数据构建bitmapsource。
//获取图像数据 if (!getimgdata(out byte[] imgdata)) return null; //构建writeablebitmap writeablebitmap img = new writeablebitmap(_imgwidth, _imgheight, 96, 96, pixelformats.bgr24, null); img.writepixels(new int32rect(0, 0, _imgwidth, _imgheight), imgdata, img.backbufferstride, 0); img.freeze();
至此,就可以显示摄像头图像了。
以上就是c#基于opencv,开发摄像头播放程序的详细内容,更多关于c# opencv摄像头播放的资料请关注其它相关文章!
下一篇: WPF 语言格式化文本控件