人脸识别 视频数据转图片数据

栏目: 编程工具 · 发布时间: 5年前

内容简介:因为不会用C#直接打开摄像头,就只能用第三方dll。一开始用Aforge,后来发现有个问题,关闭摄像头老是陷入等待,所以抛弃了。前一阵子开始用封装了OpenCV的Emgu,一路走来也是N声叹息。一、安装Emgu的叹息一开始自己下载并安装了Emgu,然后各种测试,发现还需要这个那个的,最后发现直接安装一个EMGU.CV的NuGet包就OK了。

因为不会用C#直接打开摄像头,就只能用第三方dll。一开始用Aforge,后来发现有个问题,关闭摄像头老是陷入等待,所以抛弃了。前一阵子开始用封装了OpenCV的Emgu,一路走来也是N声叹息。

一、安装Emgu的叹息

一开始自己下载并安装了Emgu,然后各种测试,发现还需要这个那个的,最后发现直接安装一个EMGU.CV的NuGet包就OK了。

当然要打开视频,还需要引用System.ServiceModel。

二、获取视频用Emgu获取视频真心十分方便

1.定义两个变量

VideoCapture _VideoCapture;
Mat _Frame = new Mat();

2.初始化视频

_VideoCapture = new VideoCapture();
//_VideoCapture.SetCaptureProperty(Emgu.CV.CvEnum.CapProp.FrameWidth, 1024); //设置宽度
//_VideoCapture.SetCaptureProperty(Emgu.CV.CvEnum.CapProp.FrameHeight, 768);//设置高度
_VideoCapture.SetCaptureProperty(Emgu.CV.CvEnum.CapProp.Fps, 10);//设置每秒钟的帧数
_VideoCapture.Start();
_VideoCapture.ImageGrabbed += _VideoCapture_ImageGrabbed; //视频事件
_VideoCapture = new VideoCapture();
//_VideoCapture.SetCaptureProperty(Emgu.CV.CvEnum.CapProp.FrameWidth, 1024); //设置宽度
//_VideoCapture.SetCaptureProperty(Emgu.CV.CvEnum.CapProp.FrameHeight, 768);//设置高度
_VideoCapture.SetCaptureProperty(Emgu.CV.CvEnum.CapProp.Fps, 10);//设置每秒钟的帧数
_VideoCapture.Start();
_VideoCapture.ImageGrabbed += _VideoCapture_ImageGrabbed; //视频事件

4.获取当前帧

用于人脸比对,一般在另外一个线程

Mat curFrame=_VideoCapture.QueryFrame();

一切十分完美,就是_Frame.Bitmap似乎没有Dispose(后来发现Mat的地址是不变,不会发生内存泄漏),但运行起来也没问题。

三、人脸识别的叹息

看了一下,人脸识别需要Bitmap,方便

Mat curFrame=_VideoCapture.QueryFrame();
Bitmap bitmap=curFrame.Bitmap;

var bmpData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);
int width = (bitmap.Width + 3) / 4 * 4;
var bytesCount = bmpData.Height * width * 3;
IntPtr pImageData = Marshal.AllocCoTaskMem(bytesCount);
if (width == bitmap.Width)
      CopyMemory(pImageData, bmpData.Scan0, bytesCount);
else
      for (int i = 0; i < bitmap.Width; i++)
            CopyMemory(IntPtr.Add(pImageData, i * width * 3), IntPtr.Add(bmpData.Scan0, i * bmpData.Stride), bmpData.Stride);
bitmap.UnlockBits(bmpData);

得到了 ArcFace 所需的图片数据pImageData,测试一下挺好,能运行。时间一长,报错了:“试读取或写入受保护的内存。这通常指示其他内存已损坏。”

估计人脸识别的线程和显示视频的线程冲突了,查看了Emgu的源代码,发现QueryFrame就是封装了Retrieve。

好吧,克隆一下,Bitmap bitmap=(Bitmap)curFrame.Bitmap.Clone();问题依旧!查看地址发现Clone没卵用!

四、最终解决的办法

研究了Mat这个东东,发现GetData()就能返回图片数据,而且不会冲突,最后写成:

1.定义

IntPtr _PImageData;
int  _ImageWidth,_ImageHeight,_ImageSize;

2.初始化

_ImageWidth=_VideoCapture.Width;
_ImageHeight=_VideoCapture.Height;
_ImageSize = _VideoCapture.Width  * _VideoCapture.Height * 3;
_PImageData = Marshal.AllocCoTaskMem(_ImageSize);

3.转换

Marshal.Copy(_Frame.GetData(), 0, _PImageData, _ImageSize);

ASFDetectFaces(pEngine,_ImageWidth, _ImageHeight,513,_PImageData, out var faceInfo);

一切变得如此简单,长叹一声!

五、其他

1.视频图片的宽度一般是4的倍数,所以上述方式肯定没问题。

2.经常有人问如何获取网络摄像头、ip摄像头的图像,其实就是

videoCapture = new VideoCapture("string filename");

如某tplink的IP摄像头的filename是这样的"rtsp://admin:admin@192.168.0.159/stream1",格式是rstp://用户名:密码@ip地址/...

各位C#的亲,你们怎么转换的?


以上所述就是小编给大家介绍的《人脸识别 视频数据转图片数据》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

引力

引力

保罗·X.麦卡锡 / 王正林 / 中信出版社 / 2018-3-1 / CNY 59.00

作者在书中提出一个全新的概念“网络引力”。我们全都受网络引力的影响,这种强大的力量正推动着数字经济前行。网络引力催生了像行星那样巨大的公司,它们以闪电般的速度击垮竞争对手,并且正在改变着商业、工作和娱乐休闲的面貌。作者在向读者展示这种令人震惊的现象的同时,还介绍了一系列独特的规则及其巨大力量,我们可以充分利用它们来创造属于自己的成功。这是在日益数字化的世界中为你赢得美好未来的一部理性指南,是一部互......一起来看看 《引力》 这本书的介绍吧!

HTML 编码/解码
HTML 编码/解码

HTML 编码/解码

SHA 加密
SHA 加密

SHA 加密工具

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具