以前一直是用c++的opencv读取视频,最近的项目改用emgu.cv读取视频,摄像头为顺华利1080p的小探测器。
这个小摄像头直接获取帧频是60,最大分辨率是1920*1080
遇到的几个问题记录如下:
1 直接读取默认图像为640*480.
读取视频采用cap = new Capture(0);可以读取计算机自带的摄像头,外置的1080p摄像头id号为1,直接采用cap = new Capture(1);读取,读取的图像宽高为640*480,返回查看计算机自带摄像头,读取的图像宽高还是640*480,
int ww = (int)cap.GetCaptureProperty(CapProp.FrameWidth);
int hh = (int)cap.GetCaptureProperty(CapProp.FrameHeight);
查看cap的属性,还是640*480;
所以在视频取图前应该设置为1920*1080;经过试验,设置帧高、帧宽后,笔记本自带的摄像头被设置为最大分辨率1080*720;
2 读取1080p的帧率提升到30
用capture读取笔记本自带摄像头,帧率为30,但是读取外置摄像头后,帧率降为5;我又重新跑了一遍以前vc+opencv的程序,发现帧率还是5,经过一番百度,需要设置视频编码,fourcc,所以加了一行
cap.SetCaptureProperty(CapProp.FourCC,VideoWriter.Fourcc('M', 'J', 'P', 'G'));
幸运的是,帧频变为30了;不幸的是,又出现了新的问题,内存在不断的上涨!没一会程序崩了!
这个办法不好用啊!
又一番百度,找到一个说法,把帧宽设置为1900*1080,读取出来的依然是1920*1080,但是帧频变成30了。
3 emgu用dshow读取视频
这个问题也不算问题,是我在用c++&OpenCV读取外置摄像头时,由于没有镜头,只有个探测器,读出来的图都是空的,但是用 VideoCapture cap(CV_CAP_DSHOW + 1); 读取是可以读出来图的。所以我看了一下emgu中对应的写法。
cap = new Capture(CaptureType.DShow + m_deviceId);
但是对emgu而言,不管用不用CaptureType.DShow,效果是一样的。
部分代码如下
using Emgu.CV;
using Emgu.Util;
using Emgu.CV.CvEnum;
public partial class LiveVideoForm
{
public Capture cap = null;
public Mat frame = null;
public int m_deviceId = 0;
public int StartCap()
{
if (cap == null)
{
cap = new Capture(/*CaptureType.DShow +*/ m_deviceId);
//cap.SetCaptureProperty(CapProp.FourCC,VideoWriter.Fourcc('M', 'J', 'P', 'G'));
cap.SetCaptureProperty(CapProp.FrameWidth, 1900);
cap.SetCaptureProperty(CapProp.FrameHeight,1080);
cap.SetCaptureProperty(CapProp.Fps, 30);
//int ww = (int)cap.GetCaptureProperty(CapProp.FrameWidth);
//int hh = (int)cap.GetCaptureProperty(CapProp.FrameHeight);
}
//cap.Start();
taskReadData = new Task(() => ReadDataLoop(cts));
taskReadData.Start();
return 1;
}
private void ReadDataLoop(object state)
{
cts = state as CancellationTokenSource;
int res = 0;
bool bFitst = true;
while (false == cts.IsCancellationRequested)
{
if (bFitst)
{
//得到图像信息
frame = cap.QueryFrame();
if (frame == null)
{
continue;
}
bFitst = false;
}
//取图
if (!m_bPause)
{
frame = cap.QueryFrame();
//CvInvoke.Imwrite("d:\\11.jpg",frame);
//frame.CopyTo(m_cTempData);
Marshal.Copy(frame.DataPointer, m_cTempData, 0, m_cTempData.Length);
//Mat temp = new Mat(frame.Rows, frame.Cols, DepthType.Cv8U, frame.NumberOfChannels);
//Marshal.Copy(m_cTempData, 0, temp.DataPointer, m_cTempData.Length);
//CvInvoke.Imwrite("d:\\12.jpg", temp);
m_ImageDataDoc.RecordCardImage(m_ImageDataDoc.m_ImageRealTimePar, m_cTempData);
frame.Dispose();
}
Thread.Sleep(3);
}
}