c#基于opencv,开发摄像头播放程序

作者:源之缘 时间:2023-06-20 11:54:29 

前言 

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,开发摄像头播放程序

来源:https://www.cnblogs.com/yuanchenhui/p/11332728.html

标签:c#,opencv,摄像头
0
投稿

猜你喜欢

  • 通过WIFI(不用数据线)连接Android手机调试

    2023-01-05 18:20:45
  • 详解Android Studio安装ButterKnife插件(手动安装)

    2023-07-06 13:59:32
  • Java调用WebService接口作测试

    2023-08-11 17:00:20
  • Maven的porfile与SpringBoot的profile结合使用案例详解

    2023-11-14 00:07:59
  • Android编程实现将ButtonBar放在屏幕底部的方法

    2021-07-12 21:01:23
  • Mybatis全局配置及映射关系的实现

    2022-07-03 09:31:39
  • Java利用cors实现跨域请求实例

    2023-02-24 14:57:35
  • Java实现英文猜词游戏的示例代码

    2023-08-07 11:40:39
  • 详解三种C#实现数组反转方式

    2023-10-09 20:29:23
  • Java新手学习之IO流的简单使用

    2023-08-09 15:57:33
  • Mybatis自动创建表和更新表结构

    2022-11-17 19:43:00
  • c# 获得局域网主机列表实例

    2022-07-12 21:46:58
  • SpringBoot2使用JTA组件实现基于JdbcTemplate多数据源事务管理(亲测好用)

    2021-10-12 06:36:09
  • java可以作为第一门编程语言学习吗

    2021-05-25 07:52:37
  • 简单了解Spring中常用工具类

    2021-09-24 10:44:28
  • SpringBoot + Spring Security 基本使用及个性化登录配置详解

    2022-03-05 04:43:41
  • Python如何使用@property @x.setter及@x.deleter

    2021-12-23 13:55:30
  • Java定时器Timer使用方法详解

    2023-08-25 17:32:20
  • C# 给PPT中的图表添加趋势线的方法

    2022-02-27 10:18:40
  • MyBatis动态SQL标签的用法详解

    2021-07-24 10:38:56
  • asp之家 软件编程 m.aspxhome.com