Как отключить буфер в OpenCV Camera? - PullRequest
0 голосов
/ 31 января 2019

У меня есть такая ситуация, когда я использую OpenCV для обнаружения лиц перед камерой и выполняю некоторые ML на этих лицах.Проблема, которая у меня есть, заключается в том, что как только я выполняю всю обработку и перехожу к следующему кадру, я получаю прошлое, а не настоящее.То есть я прочитаю, что находится внутри буфера, а не то, что на самом деле перед камерой.Так как мне все равно, какие лица появлялись перед камерой во время обработки, мне важно, что сейчас перед камерой.

Я попытался установить размер буфера на 1, и это былоочень поможет, но я все равно получу по крайней мере 3 чтения буфера.Установив FPS на 1, также доза не поможет устранить эту ситуацию на 100%.Сильфон - это поток, который у меня есть.

let cv = require('opencv4nodejs');

let camera = new cv.VideoCapture(camera_port);

camera.set(cv.CAP_PROP_BUFFERSIZE, 1);
camera.set(cv.CAP_PROP_FPS, 2);
camera.set(cv.CAP_PROP_POS_FRAMES , 1);

function loop()
{
    //
    //  <>> Grab one frame from the Camera buffer.
    //
    let rgb_mat = camera.read();

    //  Do to gray scale

    //  Do face detection

    //  Crop the image

    //  Do some ML stuff

    //  Do whats needs to be done after the results are in.

    //
    //  <>> Release data from memory
    //
    rgb_mat.release();

    //
    //  <>> Restart the loop
    //
    loop();
}

Мой вопрос:

Можно ли удалить буфер все вместе?И если да, то как.Если нет, то why будет очень признателен.

Ответы [ 2 ]

0 голосов
/ 07 февраля 2019

Поддерживается ли CAP_PROP_BUFFERSIZE, это вполне зависит от операционной системы и серверной части.Например, 2.4 docs заявляет, что «в настоящее время поддерживается только бэкэндом DC1394 [Firewire] v 2.x», а для бэкэнда V4L, согласно коду , добавлена ​​только поддержка9 марта 2018 года.

Самый простой нехрупкий способ отключить буфер - использовать отдельный поток;подробности см. в моих комментариях под ответом Петра Куровского.Вот код Python, который использует отдельный поток для реализации VideoCapture без буфера: (У меня не было среды opencv4nodejs.)

import cv2, Queue, threading, time

# bufferless VideoCapture
class VideoCapture:

  def __init__(self, name):
    self.cap = cv2.VideoCapture(name)
    self.q = Queue.Queue()
    t = threading.Thread(target=self._reader)
    t.daemon = True
    t.start()

  # read frames as soon as they are available, keeping only most recent one
  def _reader(self):
    while True:
      ret, frame = self.cap.read()
      if not ret:
        break
      if not self.q.empty():
        try:
          self.q.get_nowait()   # discard previous (unprocessed) frame
        except Queue.Empty:
          pass
      self.q.put(frame)

  def read(self):
    return self.q.get()

cap = VideoCapture(0)
while True:
  frame = cap.read()
  time.sleep(.5)   # simulate long processing
  cv2.imshow("frame", frame)
  if chr(cv2.waitKey(1)&255) == 'q':
    break

Поток устройства чтения кадров инкапсулирован внутри пользовательского класса VideoCapture и взаимодействует сосновной поток проходит через очередь.

Этот ответ предлагает использовать cap.grab() в потоке читателя, но документы не гарантируют, что grab() очистит буфер, поэтому это может сработатьв некоторых случаях, но не в других.

0 голосов
/ 31 января 2019

У меня та же проблема, но в C ++.Я не нашел правильное решение в OpenCV, но я нашел обходной путь.Этот буфер накапливает постоянное количество изображений, скажем, n кадров.Таким образом, вы можете прочитать n кадров без анализа и прочитать кадр еще раз.Этот последний кадр будет живым изображением с камеры.Что-то вроде:

buffer_size = n;

for n+1
{
  // read frames to mat variable
}
// Do something on Mat with live image
...