Я пишу простой пример OpenCV, чтобы получить кадры веб-камеры в течение 5 секунд (~ 150 кадров, если камера работает со скоростью ~ 30 кадров в секунду).
После выполнения некоторых тестов я вижу, что иногда я получаю ~ 140 из 150 кадров (приемлемо, я думаю), но иногда ~ 70. Хуже того, иногда камера, кажется, страдает от этих пропаданий кадров и остается в этом состоянии в течение нескольких часов.
Чтобы продолжить изучение проблемы, я удалил свою программу, пока у меня не возникла эта проблема, даже если я только читаю кадры, но не записывайте их на диск. Я установил задание cron для запуска 5-секундного захвата каждую минуту, и я видел такие вещи:
Я думаю, что первые два маленьких падения происходили из-за того, что система была занята, но большой, постоянный произошел посреди ночи. Утром я остановил работу cron, коснулся некоторых вещей в коде (точно не помню, что именно) и снова запустил тест, чтобы увидеть постепенное восстановление с последующим новым падением через 2-3 часа:
Со вчерашнего дня я выключил компьютер на несколько часов, снова загрузил его и закрыл веб-камеру, чтобы обеспечить постоянное освещение, но количество кадров все еще низкое и зависло на 70. Кроме того, действительно странно, что падение (70 кадров из 150) составляет ровно половину максимальных кадров, которые я видел в этой камере (140 кадров из 150).
Модель веб-камеры Logitech C525. Я также тестирую на HD-камере MacBook Pro Late 2016 года и вижу постоянные 117 кадров из 150. Мой коллега также видит падение кадров в своем ноутбуке. Есть ли проблема с моим кодом? Это может быть приоритет потока?
// 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;
}