Linux上的多个MJPEG USB网络摄像头 - VideoCapture在课堂内外的行为方式不同

时间:2014-11-05 17:06:48

标签: c++ linux opencv camera mjpeg

我有2台Logitech Pro 9000网络摄像头。我想做一些立体声校准和姿势估计,但我目前在cv :: VideoCapture的一部分上仍然存在一些奇怪的(至少对我来说)行为。请注意,此问题与here有关。

我有两个类,它们将用作为各种摄像机创建捕获模块的基础,以便将它们包含在更大的系统中。第一个 - CameraSettings - 包含特定于摄像机的设置。这些设置用于第二类 - 相机 - 处理视频流,校准等。摄像机的构造函数只使用CameraSettings对象中的值与cv :: VideoCapture :: set(CV_CAP_PROP_ ...):

#ifndef CAMERASETTINGS_H
#define CAMERASETTINGS_H

#include <string>
using std::string;
namespace Camera {
  class CameraSettings {
    private:
      double deviceIndex; /// Device index (starts from 0)
      double frameRateLimit;  /// Limits the frames per second. Depending on the number of cameras and the amount of data that is retrieved from those setting this to a lower (supported by the camera model!) value will prevent data clogging
      double frameWidth;  /// Width of the frame
      double frameHeight; /// Height of the frame

    public:
      /// Creates an empty set of settings
      CameraSettings();
      /// Creates a partially predefined set of settings
      CameraSettings(double deviceIndex, double frameRateLimit=25, double frameWidth=320, double frameHeight=240);
      CameraSettings(string devideIpAddrAndFormat, double frameRateLimit=25, double frameWidth=320, double frameHeight=240);
      ~CameraSettings();

      /*
       * Getters and setters for all settings of a camera
       */

      double getDevice() const;
      void setDevice(double value);

      double getFrameRateLimit() const;
      void setFrameRateLimit(double value);

      double getFrameWidth() const;
      void setFrameWidth(double value);

      double getFrameHeight() const;
      void setFrameHeight(double value);
  };
}
namespace Camera {
  class Camera {
    private:
      CameraSettings settings;  // Various camera settings
      VideoCapture *capture;  // Points at the video stream generated by the camera

    public:
      /*
       * Creates a new camera using a set of given settings
       * @param settings Contains an object with camera settings
       */
      Camera(CameraSettings& settings);
      ~Camera();

      /*
       * Retrieves the next frame in the stream
       * @param frame Contains a retrieved frame from the video stream
       */
      void getFrame(Mat& frame);
  };

注意:这仍是一项早期工作!

问题来自我的getFrame()方法,如下所示:

void Camera::getFrame(Mat &frame)
{
  cout << "Reading frame..." << endl;
  // Check if stream is opened
  if(capture->isOpened()) {
    // Store next frame and check if frames can actually be read from the specified capture
    if(!capture->read(frame))
      cout << MSG_PREFIX_ERROR << ERROR_CAPT_UNABLE_TO_READ << endl;
  }
}

创建CameraSettings对象后,我可以另外调整参数并将其传递给新创建的Camera对象:

// Set both sets of settings to framerate of 15 and resolution of 352x288
Camera::CameraSettings cs1(1, 15);
Camera::CameraSettings cs2(2, 15);
cs1.setFrameHeight(288);
cs1.setFrameWidth(352);
cs2.setFrameHeight(288);
cs2.setFrameWidth(352);

// Create two cameras using the specified above settings
Camera::Camera cam1(cs1);
Camera::Camera cam2(cs2);

我发现与以下直接方法相比,我在Camera对象中使用的VideoCapture可以实现更低的分辨率和帧速率:

main(int argc, char **argv) {
  VideoCapture cap1(1);
  VideoCapture cap2(2);

  if(!cap1.isOpened())
  {
    cout << "Cannot open the video cam [1]" << endl;
    return -1;
  }

  if(!cap2.isOpened())
  {
    cout << "Cannot open the video cam [2]" << endl;
    return -1;
  }

  cap1.set(CV_CAP_PROP_FPS, 15);
  cap2.set(CV_CAP_PROP_FPS, 15);

  double dWidth1 = cap1.get(CV_CAP_PROP_FRAME_WIDTH);
  double dHeight1 = cap1.get(CV_CAP_PROP_FRAME_HEIGHT);
  double dWidth2 = cap2.get(CV_CAP_PROP_FRAME_WIDTH);
  double dHeight2 = cap2.get(CV_CAP_PROP_FRAME_HEIGHT);

  cout << "cam[1] Frame size: " << dWidth1 << " x " << dHeight1 << endl;
  cout << "cam[2] Frame size: " << dWidth2 << " x " << dHeight2 << endl;
  namedWindow("cam[1]",CV_WINDOW_AUTOSIZE);
  namedWindow("cam[2]",CV_WINDOW_AUTOSIZE);

  while(1)
  {
    Mat frame1, frame2;
    bool bSuccess1 = cap1.read(frame1);
    bool bSuccess2 = cap2.read(frame2);

    if (!bSuccess1)
    {
      cout << "Cannot read a frame from video stream [1]" << endl;
      break;
    }

    if (!bSuccess2)
    {
      cout << "Cannot read a frame from video stream [2]" << endl;
      break;
    }

    imshow("cam[1]", frame1);
    imshow("cam[2]", frame2);

    if(waitKey(30) == 27)
    {
      cout << "ESC key was pressed by user" << endl;
      break;
    }
  }
}

我在班上处理事物的方式与我发布的第二段代码完全相同,不同之处在于我使用了cv :: VideoCapture的默认设置。我检查了框架的尺寸,它们是640x480。在使用我的Camera类的情况下,我无法获得如此高的分辨率,因为我得到了臭名昭着的错误:

  

libv4l2:开启错误:设备上没有剩余空间

     

VIDIOC_STREAMON:设备上没有剩余空间

例如,如果我执行以下操作:

cs1.setFrameHeight(288);
cs1.setFrameWidth(352);
cs2.setFrameHeight(288);
cs2.setFrameWidth(352);

我的两台相机都以15 fps的速度正常运行。在没有我的课程的情况下使用640x480是不可能的。

请注意,我已使用 v4l2-ctl 检查了支持的分辨率。我也测试了两种情况下的帧率,因为它们会影响两个摄像机的数据量。

显然我的问题是为什么会发生这种情况,以及在FPS和分辨率方面,我的课程如何影响cv :: VideoCapture的功能。

编辑:删除了手头问题不需要的代码。谢谢@Wug!

0 个答案:

没有答案