我有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!