Задача состоит в том, чтобы написать программу, которая создает два процесса:
a) ' Процесс производителя считывает изображение видеокадра непосредственно в кольцевой буфер общей памяти (т. е. буфер общей памяти, который может вместить N изображений кадров для настраиваемого N - это можно сохранить как параметр командной строки).
б) Потребительский процесс считывает изображения кадров из кольцевой буфер отображает каждый кадр в течение настраиваемого промежутка времени (например, 500 мс - а также параметр командной строки программы)
c) Производитель и потребитель должны синхронизироваться, чтобы
i) Потребитель отображает изображение только после того, как оно было полностью создано (т. е. весь кадр был сгенерирован)
ii) Потребитель ждет производителя если следующее изображение, которое будет использовано, еще не было полностью создано.\
iii) Производитель ожидает потребителя, в кольцевом буфере нет места для создания следующего изображения (т. е. потребитель не полностью израсходовал ни одно из изображений). текущие изображения в кольцевом буфере)
ниже мой код:
Код: Выделить всё
from multiprocessing import Process, Lock, Value
from multiprocessing.shared_memory import SharedMemory
import sys
import numpy as np
import cv2
import time
class RingBufferFullException(Exception):
pass
class RingBufferEmptyException(Exception):
pass
class RingBuffer:
def __init__(self, max_size, single_frame):
self.max_size = Value('i', max_size)
self.shm = SharedMemory(create=True, size=max_size*single_frame.nbytes)
self.queue = np.ndarray(shape=(max_size, *single_frame.shape), dtype=single_frame.dtype, buffer=self.shm.buf)
self.tail = Value('i', -1)
self.head = Value('i', 0)
self.size = Value('i', 0)
self.lock = Lock()
def enqueue(self, item):
with self.lock:
if self.size.value == self.max_size.value:
raise RingBufferFullException('Error: Queue is full')
else:
self.tail.value = (self.tail.value + 1) % self.max_size.value
self.queue[self.tail.value] = item
self.size.value += 1
def dequeue(self):
with self.lock:
if self.size.value == 0:
raise RingBufferEmptyException('Error: Queue is empty')
tmp = self.queue[self.head.value]
self.head.value = (self.head.value + 1) % self.max_size.value
self.size.value -= 1
return tmp
def isFull(self):
return self.size.value == self.max_size.value
def isEmpty(self):
return self.size.value == 0
def display(self):
if self.size.value == 0:
print('Queue is empty')
else:
idx = self.head.value
print('---------------------------------------')
for i in range(self.size.value):
print(self.queue[idx])
idx = (idx + 1) % self.max_size.value
print('---------------------------------------')
def clean(self):
self.shm.close()
self.shm.unlink()
def producer(buf):
cap = cv2.VideoCapture(0)
print(cap.isOpened())
while True:
buf.display()
success, frame = cap.read()
if not success:
print('Failed to capture frame')
continue
try:
buf.enqueue(frame)
except RingBufferFullException:
time.sleep(0.5)
def consumer(buf):
while True:
try:
frame = buf.dequeue()
cv2.imshow('Frame', frame)
cv2.waitKey(100)
except RingBufferEmptyException:
time.sleep(0.2)
cv2.destroyAllWindows()
if __name__ == '__main__':
test = cv2.VideoCapture(0)
if not test.isOpened():
print('Error: Could not open camera.')
sys.exit(1)
success, single_frame = test.read()
if not success:
print('Error: Could not capture initial frame.')
sys.exit(1)
test.release()
buf = RingBuffer(10, single_frame)
test.release()
produce = Process(target=producer, args=(buf,))
consume = Process(target=consumer, args=(buf,))
try:
produce.start()
consume.start()
produce.join()
consume.join()
finally:
buf.clean()
Затем я сделал метаданные кольцевого буфера общей памятью. теперь он отлично ставит и удаляет кадры из очереди, но показывает только черные изображения.
Основная проблема заключается в том, что окно cv2 показывает только черный цвет. Все изображения черные. когда я печатаю кадр, выведенный из очереди, это просто матрица со всеми нулями. Если я печатаю буфер внутри функции производителя или функции потребителя, он печатает матрицу np с разными значениями. Но в окне cv2 просто черные изображения.
Что я делаю не так? Любая помощь приветствуется. Ребята, заранее спасибо.
Подробнее здесь: https://stackoverflow.com/questions/793 ... -data-type