Как решить проблему обработки изображения IO камеры с помощью OpenCV - PullRequest
2 голосов
/ 21 марта 2019

У меня есть программа OpenCV, которая работает так:

VideoCapture cap(0);
Mat frame;
while(true) {
  cap >> frame;
  myprocess(frame);
}

Проблема в том, что если myprocess занимает много времени, которое больше интервала ввода-вывода камеры, отснятый кадр будет задержан, не сможет синхронизировать кадр с реальным временем.

Итак, я думаю, что для решения этой проблемы должна быть включена потоковая камера и myprocess работать параллельно. Один поток выполняет операции ввода-вывода, другой - вычисления процессора. Когда камера закончит захват, отправьте в рабочий поток на обработку.

Правильна ли эта идея? Есть ли лучшая стратегия для решения этой проблемы?

Демо-версия:

int main(int argc, char *argv[])
{
    cv::Mat buffer;
    cv::VideoCapture cap;
    std::mutex mutex;
    cap.open(0);
    std::thread product([](cv::Mat& buffer, cv::VideoCapture cap, std::mutex& mutex){
        while (true) { // keep product the new image
            cv::Mat tmp;
            cap >> tmp;
            mutex.lock();
            buffer = tmp.clone(); // copy the value
            mutex.unlock();
        }
    }, std::ref(buffer), cap, std::ref(mutex));
    product.detach();

    while (cv::waitKey(20)) { // process in the main thread
        mutex.lock();
        cv::Mat tmp = buffer.clone(); // copy the value
        mutex.unlock();
        if(!tmp.data)
            std::cout<<"null"<<std::endl;
        else {
            std::cout<<"not null"<<std::endl;
            cv::imshow("test", tmp);
        }

    }
    return 0;
}

Или используйте поток, продолжающий очищать буфер.

int main(int argc, char *argv[])
{
    cv::Mat buffer;
    cv::VideoCapture cap;
    std::mutex mutex;
    cap.open(0);
    std::thread product([](cv::Mat& buffer, cv::VideoCapture cap, std::mutex& mutex){
        while (true) { // keep product the new image
            cap.grab();
        }
    }, std::ref(buffer), cap, std::ref(mutex));
    product.detach();
    int i;
    while (true) { // process in the main thread
        cv::Mat tmp;
        cap.retrieve(tmp);
        if(!tmp.data)
            std::cout<<"null"<<i++<<std::endl;
        else {
            cv::imshow("test", tmp);
        }
        if(cv::waitKey(30) >= 0) break;
    }
    return 0;
}

Второе демо, которое я думал, будет работать на https://docs.opencv.org/3.0-beta/modules/videoio/doc/reading_and_writing_video.html#videocapture-grab,, но это не ...

Ответы [ 2 ]

0 голосов
/ 25 марта 2019

В проекте с многоцелевым отслеживанием я использовал 2 буфера для кадра (cv :: Mat frames [2]) и 2 потока:

  1. Один поток для захвата следующего кадра и обнаружения объектов.

  2. Второй поток для отслеживания обнаруженных объектов и результата рисования на кадре.

Я использовал index = [0,1] для буферовсвоп и этот индекс был защищен мьютексом.Для оповещения об окончании работы были использованы 2 условные переменные.

Первые работы CatureAndDetect с буфером frames [capture_ind] и Tracking работает с буфером предыдущих кадров [1-capture_ind].Следующий шаг - переключение буферов: capture_ind = 1 - capture_ind.

Можете ли вы этот проект здесь: Multitarget-tracker .

0 голосов
/ 22 марта 2019

Идея повысить производительность за счет потоков для операций ввода-вывода, в то время как другой поток выполняет вычисления на процессорах, является классической стратегией. В дополнение к задержке обработки ЦП, cv2.VideoCapture().read() является операцией блокировки, поэтому ваша основная программа может испытывать задержку ввода-вывода и должна останавливать любую обработку, пока она ожидает новых кадров. Имея отдельные выделенные потоки, ваша программа работает в параллельно вместо того, чтобы полагаться на один поток для захвата кадров и обработки кадров в последовательном порядке .

Вы можете сохранить все кадры из потока ввода-вывода в очередь, в то время как поток обработки просто считывает и обрабатывает самый последний кадр в очереди без каких-либо проблем с задержкой.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...