Видимое случайное падение FPS в веб-камере при использовании OpenCV в C ++ - PullRequest
1 голос
/ 01 апреля 2020

Я пишу простой пример OpenCV, чтобы получить кадры веб-камеры в течение 5 секунд (~ 150 кадров, если камера работает со скоростью ~ 30 кадров в секунду).

После выполнения некоторых тестов я вижу, что иногда я получаю ~ 140 из 150 кадров (приемлемо, я думаю), но иногда ~ 70. Хуже того, иногда камера, кажется, страдает от этих пропаданий кадров и остается в этом состоянии в течение нескольких часов.

Чтобы продолжить изучение проблемы, я удалил свою программу, пока у меня не возникла эта проблема, даже если я только читаю кадры, но не записывайте их на диск. Я установил задание cron для запуска 5-секундного захвата каждую минуту, и я видел такие вещи: enter image description here

Я думаю, что первые два маленьких падения происходили из-за того, что система была занята, но большой, постоянный произошел посреди ночи. Утром я остановил работу cron, коснулся некоторых вещей в коде (точно не помню, что именно) и снова запустил тест, чтобы увидеть постепенное восстановление с последующим новым падением через 2-3 часа: enter image description here

Со вчерашнего дня я выключил компьютер на несколько часов, снова загрузил его и закрыл веб-камеру, чтобы обеспечить постоянное освещение, но количество кадров все еще низкое и зависло на 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;
}

1 Ответ

0 голосов
/ 01 апреля 2020

Кажется, это связано с плохим освещением. Как только я обнаружил камару, я увидел, что рамки увеличились до ожидаемого значения. Поэтому, возможно, в условиях плохой освещенности камера изменяет некоторые настройки или обрабатывает изображения, снижая частоту кадров.

enter image description here

...