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摄像头播放的资料请关注我们其它相关文章!

(0)

相关推荐

  • C#调用OpenCV开发简易版美图工具【推荐】

    前言 在C#调用OpenCV其实非常简单,因为C#中有很多OPenCV的开源类库. 本文主要介绍在WPF项目中使用OpenCVSharp3-AnyCPU开源类库处理图片,下面我们先来做开发前的准备工作. 准备工作 首先,我们先创建一个WPF项目. 然后,在Nuget上搜索OpenCVSharp,如下图: 接着,我们选择OpenCVSharp3-AnyCPU选项进行安装 . 安装了OpenCVSharp3-AnyCPU后,我们的项目会自动引入4个类库,如下图: 到这里,我们的准备工作就完成了,非常

  • 在C#中使用OpenCV(使用OpenCVSharp)的实现

     1.什么是OpenCVSharp 为了解决在Csharp下编写OpenCV程序的问题,我做过比较深入的研究,并且实现了高效可用的方法(GOCW):这几天在搜集资料的时候,偶尔看见了OpenCVSharp,从时间上来看,它已经经过了更久的发展,应该有许多直接借鉴.或者直接使用的地方. OpenCVSharp有一名日本工程师开发,项目地址为:https://github.com/shimat/opencvsharp.其是OpenCV的.NET wrapper,它比Emgucv更接近于原始的Open

  • c# 使用OpenCV识别硬币

    在本系列文章中,我们将使用深度神经网络(DNN)来执行硬币识别.具体来说,我们将训练一个DNN识别图像中的硬币. 在本文中,我们将描述一个OpenCV应用程序,它将检测图像中的硬币.硬币检测是硬币完整识别之前的一个常见阶段.它包括从给定图像中检测和提取硬币. 本系列附带的代码将使用Keras在C#中实现.在本系列的最后一篇文章中,我们将简要地使用ML.NET.在众多选择中,为什么要使用Keras.NET呢?Keras.NET 非常容易学习,因为它基本上是从Python编写的经典TensorFlo

  • C#中OpenCvSharp 通过特征点匹配图片的方法

    现在的手游基本都是重复操作,一个动作要等好久,结束之后继续另一个动作.很麻烦,所以动起了自己写一个游戏辅助的心思. 这个辅助本身没什么难度,就是通过不断的截图,然后从这个截图中找出预先截好的能代表相应动作的按钮或者触发条件的小图. 找到之后获取该子区域的左上角坐标,然后通过windows API调用鼠标或者键盘做操作就行了. 这里面最难的也就是找图了,因为要精准找图,而且最好能适应不同的分辨率下找图,所以在模板匹配的基础上,就有了SIFT和SURF的特征点找图方式. 在写的过程中查找资料,大都是

  • C#使用opencv截取旋转矩形区域图像的实现示例

    前言:最近在工程中需要用到截取RotatedRect中的图形,保存为Mat做后续处理.发现opencv文档中没有这个api,最开始想到的方案是将整张图片进行相应的旋转,然后再从中截取正矩形,但是我们要获取的是部分区域,将整张图片进行旋转会造成很多的资源浪费.所以需要自行实现一个旋转矩形的方案. 实现方法 原理是利用向量空间变换,如图 通过 Point2f[] points=rotatedRect.Points(); 可获取RotatedRect四个端点的坐标.先选定一个点为输出Mat左上端点,这

  • C#使用OpenCv图像批处理并改变图片大小并且重命名

    添加NuGet包 选择最新版就好了 安装完成后右键项目重新生成方案 使用OpenCvSharp.CPlusPlus命名空间 using OpenCvSharp.CPlusPlus; 写一个函数用来改变图片大小并且重新命名 read_path是存储图片的文件夹的路径,write_path是改变后图片存储的文件夹路径,filename是图片重命名,width和height分别为图片修改后的宽和高 public static void ResizeImg(String read_path,String

  • C#使用OpenCV剪切图片中的人物头像的实现方法

    前言 本文主要介绍如何使用OpenCV剪切图形中的人物头像. 准备工作 首先创建一个Wpf项目--OpenCV_Face_Wpf,这里版本使用Framework4.7.2. 然后使用Nuget搜索[Emgu.CV],如下图. 这里的Emgu.CV选择4.3.0.3890版本,然后安装Emgu.CV和Emgu.CV.runtime.windows. 然后下载所需文件haarcascade_frontalface_default.xml. 可以去OpenCV的开源代码中下载,下载地址:https:/

  • C#使用OpenCV剪切图像中的圆形和矩形的示例代码

    前言 本文主要介绍如何使用OpenCV剪切图像中的圆形和矩形. 准备工作 首先创建一个Wpf项目--WpfOpenCV,这里版本使用Framework4.7.2. 然后使用Nuget搜索[Emgu.CV],如下图. 这里的Emgu.CV选择4.3.0.3890版本,然后安装Emgu.CV和Emgu.CV.runtime.windows. 使用OPenCV剪切矩形 现在,我们进入项目,进行OPenCV的调用. 首先引入命名空间,如下: using Emgu.CV; using Emgu.CV.Cv

  • 利用C#版OpenCV实现圆心求取实例代码

    前言 OpenCVSharp是OpenCV的.NET wrapper,是一名日本工程师开发的,项目地址为:https://github.com/shimat/opencvsharp. 该源码是 BSD开放协议,BSD开源协议是一个给于使用者很大自由的协议.基本上使用者可以"为所欲为",可以自由的使用,修改源代码,也可以将修改后的代码作为开源或者专有软件再发布或商业化销售. 1.OpenCVSharp的下载 可以直接从上面的github上下载源码,自行编译引用: 也可用vs中的nuget

  • C#中OpenCVSharp实现轮廓检测

    OpenCv提供了函数 findContours()用于对物体轮廓进行检测,该函数实现算法是由S.suzuki K.Abe于1985年发表的.OpenCVSharp封装了这个函数,有2个参数(contours,hierarchy)要做特别的说明. public static void FindContours(InputOutputArray image, out Point[][] contours, out HierarchyIndex[] hierarchy, RetrievalModes

  • 如何在C#中使用OpenCV(GOCW使用教程)

    1.什么是GOCW 为了解决在Csharp下编写OpenCV程序的问题,我做过比较深入的研究,并且实现了高效可用的方法GreenOpenCsharpWrapper(GOCW).通过这种方法,能够分离界面和算法业务,高效率完成算法调用,而且非常方便进行算法维护.应该说是我在多年项目实践中不断总结提炼出来的一点东西.        GOCW的发布地址为:https://gitee.com/jsxyhelu2020/gocw 2.GOCW有什么特点 分离界面和算法业务 图像数据直接通过内存传值,高效率

随机推荐