在 C++ 中使用 OpenCV 时网络摄像头的 FPS 明显随机下降
Apparent FPS random drop in webcam when using OpenCV in C++
我正在编写一个简单的 OpenCV 示例,以在 5 秒内获取网络摄像头帧(如果摄像头以 ~30fps 的速度工作,则为 ~150 帧)。
进行一些测试后,我发现有时 150 帧中的 140 帧(我猜是可以接受的),但有时是 70 帧。更糟糕的是,有时相机似乎会遭受掉帧的困扰并保持这种状态数小时。
为了进一步调查这个问题,我剥离了我的程序,直到我仍然有那个问题,即使我只读取帧,但不将它们写入磁盘。我已经设置了一个 cron 作业,以便每分钟 运行 捕获 5 秒,并且我看到了这样的事情:
我认为前两个小下降是由于系统繁忙,但大的、永久的下降发生在半夜。早上,我停止了 cron 作业,触摸了代码中的一些东西(我不记得具体是什么)并再次开始测试,看到逐渐恢复,然后在 2-3 小时后出现新的下降:
从昨天开始,我关了电脑几个小时,重新开机,盖上摄像头,保证光线充足,但帧数还是很低,一直卡在70。还有,真的奇怪的是下降(150 帧中的 70 帧)刚好达到我在这台相机中看到的最大帧数的一半(150 帧中的 140 帧)。
摄像头型号为罗技C525。我还在 Macbook Pro Late 2016 Facetime HD 摄像头中进行测试,我看到 150 帧中有 117 帧不变。我的一位同事也发现他的笔记本电脑出现掉帧现象。我的代码有问题吗?难道是线程优先级?
// Call the program like this: ./cameraTest pixelWidth pixelHeight fps timeLimit
// timeLimit can be 1 to run a fixed 5-seconds capture, or 0 to wait for 150 frames.
#include "opencv2/opencv.hpp"
#include "iostream"
#include "thread"
#include <unistd.h>
#include <chrono>
#include <ctime>
#include <experimental/filesystem>
using namespace cv;
namespace fs = std::experimental::filesystem;
VideoCapture camera(0);
bool stop = false;
int readFrames = 0;
std::string getTimeStamp()
{
time_t rawtime;
struct tm * timeinfo;
char buffer[80];
time(&rawtime);
timeinfo = localtime(&rawtime);
strftime(buffer,sizeof(buffer),"%Y-%m-%d %H:%M:%S",timeinfo);
std::string timeStamp(buffer);
return timeStamp;
}
void getFrame()
{
Mat frame;
camera >> frame;
// camera.read(frame);
// cv::imwrite("/tmp/frames/frame" + std::to_string(readFrames) + ".jpg", frame);
readFrames++;
}
void getFrames()
{
Mat frame;
while(!stop)
{
camera >> frame;
// cv::imwrite("/tmp/frames/frame" + std::to_string(fc) + ".jpg", frame);
readFrames++;
}
}
int main(int argc, char* argv[])
{
if(argc < 5)
{
std::cout << "Usage: width height fps timeLimit" << std::endl;
return -1;
}
if(!camera.isOpened())
{
std::cout << "Couldn't open camera " << getTimeStamp() << std::endl;
return -1;
}
if (!fs::is_directory("/tmp/frames"))
{
if(system("mkdir -p /tmp/frames") != 0)
{
std::cout << "Error creating /tmp/frames/" << std::endl;
}
}
if (!fs::is_empty("/tmp/frames"))
{
system("exec rm /tmp/frames/*");
}
camera.set(CV_CAP_PROP_FRAME_WIDTH, atoi(argv[1]));
camera.set(CV_CAP_PROP_FRAME_HEIGHT, atoi(argv[2]));
camera.set(CV_CAP_PROP_FPS, atoi(argv[3]));
//camera.set(CV_CAP_PROP_FOURCC, CV_FOURCC('M', 'J', 'P', 'G'));
bool timeLimit(atoi(argv[4]));
std::chrono::steady_clock::time_point begin = std::chrono::steady_clock::now();
int waitSeconds = 5;
if(timeLimit)
{
std::thread tr(getFrames);
usleep(waitSeconds * 1e6);
stop = true;
tr.join();
}
else
{
while(readFrames < 150)
{
getFrame();
}
}
std::chrono::steady_clock::time_point end = std::chrono::steady_clock::now();
std::cout << getTimeStamp() << " " << readFrames << "/" << atoi(argv[3]) * waitSeconds << " "
<< std::chrono::duration_cast<std::chrono::milliseconds>(end - begin).count() << "ms"
<< " " << atoi(argv[1]) << "," << atoi(argv[2]) << "," << atoi(argv[3])
<< std::endl;
return 0;
}
好像跟光线不好有关。我一揭开相机,就看到镜框增加到它们的预期值。因此,也许在光线不足的情况下,相机会更改一些设置或进一步处理图像,从而降低其帧率。
我正在编写一个简单的 OpenCV 示例,以在 5 秒内获取网络摄像头帧(如果摄像头以 ~30fps 的速度工作,则为 ~150 帧)。
进行一些测试后,我发现有时 150 帧中的 140 帧(我猜是可以接受的),但有时是 70 帧。更糟糕的是,有时相机似乎会遭受掉帧的困扰并保持这种状态数小时。
为了进一步调查这个问题,我剥离了我的程序,直到我仍然有那个问题,即使我只读取帧,但不将它们写入磁盘。我已经设置了一个 cron 作业,以便每分钟 运行 捕获 5 秒,并且我看到了这样的事情:
我认为前两个小下降是由于系统繁忙,但大的、永久的下降发生在半夜。早上,我停止了 cron 作业,触摸了代码中的一些东西(我不记得具体是什么)并再次开始测试,看到逐渐恢复,然后在 2-3 小时后出现新的下降:
从昨天开始,我关了电脑几个小时,重新开机,盖上摄像头,保证光线充足,但帧数还是很低,一直卡在70。还有,真的奇怪的是下降(150 帧中的 70 帧)刚好达到我在这台相机中看到的最大帧数的一半(150 帧中的 140 帧)。
摄像头型号为罗技C525。我还在 Macbook Pro Late 2016 Facetime HD 摄像头中进行测试,我看到 150 帧中有 117 帧不变。我的一位同事也发现他的笔记本电脑出现掉帧现象。我的代码有问题吗?难道是线程优先级?
// Call the program like this: ./cameraTest pixelWidth pixelHeight fps timeLimit
// timeLimit can be 1 to run a fixed 5-seconds capture, or 0 to wait for 150 frames.
#include "opencv2/opencv.hpp"
#include "iostream"
#include "thread"
#include <unistd.h>
#include <chrono>
#include <ctime>
#include <experimental/filesystem>
using namespace cv;
namespace fs = std::experimental::filesystem;
VideoCapture camera(0);
bool stop = false;
int readFrames = 0;
std::string getTimeStamp()
{
time_t rawtime;
struct tm * timeinfo;
char buffer[80];
time(&rawtime);
timeinfo = localtime(&rawtime);
strftime(buffer,sizeof(buffer),"%Y-%m-%d %H:%M:%S",timeinfo);
std::string timeStamp(buffer);
return timeStamp;
}
void getFrame()
{
Mat frame;
camera >> frame;
// camera.read(frame);
// cv::imwrite("/tmp/frames/frame" + std::to_string(readFrames) + ".jpg", frame);
readFrames++;
}
void getFrames()
{
Mat frame;
while(!stop)
{
camera >> frame;
// cv::imwrite("/tmp/frames/frame" + std::to_string(fc) + ".jpg", frame);
readFrames++;
}
}
int main(int argc, char* argv[])
{
if(argc < 5)
{
std::cout << "Usage: width height fps timeLimit" << std::endl;
return -1;
}
if(!camera.isOpened())
{
std::cout << "Couldn't open camera " << getTimeStamp() << std::endl;
return -1;
}
if (!fs::is_directory("/tmp/frames"))
{
if(system("mkdir -p /tmp/frames") != 0)
{
std::cout << "Error creating /tmp/frames/" << std::endl;
}
}
if (!fs::is_empty("/tmp/frames"))
{
system("exec rm /tmp/frames/*");
}
camera.set(CV_CAP_PROP_FRAME_WIDTH, atoi(argv[1]));
camera.set(CV_CAP_PROP_FRAME_HEIGHT, atoi(argv[2]));
camera.set(CV_CAP_PROP_FPS, atoi(argv[3]));
//camera.set(CV_CAP_PROP_FOURCC, CV_FOURCC('M', 'J', 'P', 'G'));
bool timeLimit(atoi(argv[4]));
std::chrono::steady_clock::time_point begin = std::chrono::steady_clock::now();
int waitSeconds = 5;
if(timeLimit)
{
std::thread tr(getFrames);
usleep(waitSeconds * 1e6);
stop = true;
tr.join();
}
else
{
while(readFrames < 150)
{
getFrame();
}
}
std::chrono::steady_clock::time_point end = std::chrono::steady_clock::now();
std::cout << getTimeStamp() << " " << readFrames << "/" << atoi(argv[3]) * waitSeconds << " "
<< std::chrono::duration_cast<std::chrono::milliseconds>(end - begin).count() << "ms"
<< " " << atoi(argv[1]) << "," << atoi(argv[2]) << "," << atoi(argv[3])
<< std::endl;
return 0;
}
好像跟光线不好有关。我一揭开相机,就看到镜框增加到它们的预期值。因此,也许在光线不足的情况下,相机会更改一些设置或进一步处理图像,从而降低其帧率。