Несколько веб-камер MJPEG USB в Linux — VideoCapture ведет себя по-разному внутри и за пределами класса

У меня есть 2 веб-камеры Logitech Pro 9000. Я хочу сделать некоторую стереокалибровку и оценить позу, но в настоящее время я застрял на каком-то странном (по крайней мере для меня) поведении в части cv :: VideoCapture. Обратите внимание, что этот вопрос относится к одному Вот.

У меня есть два класса, которые будут использоваться в качестве основы для создания модулей захвата для различных камер, чтобы включить их в большую систему. Первый — 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);

Я обнаружил, что VideoCapture, который есть в моем объекте Camera, позволяет значительно снизить разрешение и частоту кадров по сравнению со следующим прямым подходом:

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. Я проверил размеры рамок, они 640х480. В случае использования моего класса Camera, однако, я не могу получить такое высокое разрешение, потому что я получаю печально известную ошибку:

libv4l2: ошибка при включении потока: на устройстве не осталось места

VIDIOC_STREAMON: на устройстве не осталось места

Например, если я сделаю следующее:

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

для обеих моих камер со скоростью 15 кадров в секунду он работает, как и ожидалось. Использование 640×480 как в случае без моих занятий не представляется возможным.

Обратите внимание, что я проверил поддерживаемые разрешения, используя v4l2-CTL. Я также проверил частоты кадров в обоих случаях, потому что они действительно влияют на то, насколько велики объемы данных с обеих камер.

Очевидно, мой вопрос заключается в том, почему это происходит и как мой класс влияет на возможности cv :: VideoCapture, когда дело доходит до FPS и разрешения.

РЕДАКТИРОВАТЬ: Удален код, который не требуется для решения проблемы. Спасибо @Wug!

0

Решение

Задача ещё не решена.

Другие решения


По вопросам рекламы [email protected]