Многопроцессорный массив Python и фреймы OpenCV3 - PullRequest
0 голосов
/ 22 октября 2018

Я прочитал этот [пост] ( Правильный способ поделиться видеокадром opencv в виде массива Numpy между многопроцессорными процессами ) и попытался завершить реализацию.Камера снимает только что найденные изображения, формы изображений, буферы и полученное изображение в другом процессе совпадают.Но полученное изображение показывает черно-белые шумовые линии.Я пытался добавить блокировки перед массивом чтения / записи, но безрезультатно.

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

class VideoWorker(Process):
    def __init__(self, shared_Array, shape,width, height, fps):
        super(VideoWorker, self).__init__()
        # passing width /height as want to write video file later...
        self.width = width
        self.height = height
        self.fps = fps
        self.shared_Array = shared_Array
        self.shape = shape

    def run(self):
        name = "VideoWorker"
        print ('%s %s' % (name, self.name))

        cv2.namedWindow(name,cv2.WINDOW_NORMAL)
        cv2.resizeWindow(name,640,480)

        while True:
            img = np.frombuffer(self.shared_Array,dtype=ctypes.c_uint8)
            print("%s : got img shape %s " % (name, str(img.shape)))
            cv2.imshow(name, img)

            if cv2.waitKey(20) & 0xFF == ord('q'):
                break

        print("%s: done" %name)

if __name__ == '__main__':
    camera = cv2.VideoCapture(0)
    camera.set(cv2.CAP_PROP_FRAME_WIDTH,1280)
    camera.set(cv2.CAP_PROP_FRAME_HEIGHT,720)
    width = camera.get(cv2.CAP_PROP_FRAME_WIDTH)
    height = camera.get(cv2.CAP_PROP_FRAME_HEIGHT)
    fps = camera.get(cv2.CAP_PROP_FPS)

    cv2.namedWindow("orig",cv2.WINDOW_NORMAL)
    cv2.resizeWindow("orig",640,480)
    cv2.namedWindow("loop",cv2.WINDOW_NORMAL)
    cv2.resizeWindow("loop",640,480)

    grabbed, frame = camera.read()
    shape = frame.shape
    cv2.imshow("orig",frame)
    print("main: shape ",shape, "size ", frame.size, "fps ",fps)

    # size is L x W x channels
    shared_Array = Array(ctypes.c_uint8, shape[0] * shape[1] *shape[2], lock=False)

    worker = VideoWorker(shared_Array, shape, width, height, fps )
    worker.start()

    print("main: reshape size ",shape[0]*shape[1]*shape[2])

    while True:
        buf = np.frombuffer(shared_Array,dtype=np.uint8)
        print("main: frombuffer shape ",buf.shape)

        buf = buf.reshape(shape)
        print("main: loop buf reshape ",buf.shape)

        grabbed, frame = camera.read()
        cv2.imshow("loop",frame)
        print ("main: frame shape ",frame.shape)

        if not grabbed:
            break

        buf[:] = frame

        if worker.is_alive() == False:
            break

        if cv2.waitKey(20) &  0xFF == ord('q'):
            break

    print("Main process done")
    worker.join()
    camera.release()
    cv2.destroyAllWindows()

На выходе получаются два хороших окна и одно черно-белое раздетое окно, а также следующие(обрезано):

VideoWorker VideoWorker-1
VideoWorker : got img shape (2764800,)
VideoWorker: done
main: shape  (720, 1280, 3) size  2764800 fps  30.0
main: reshape size  2764800
main: frombuffer shape  (2764800,)
main: loop buf reshape  (720, 1280, 3)
main: frame shape  (720, 1280, 3)
main: frombuffer shape  (2764800,)
main: loop buf reshape  (720, 1280, 3)
main: frame shape  (720, 1280, 3)
main: frombuffer shape  (2764800,)
main: loop buf reshape  (720, 1280, 3)
main: frame shape  (720, 1280, 3)
main: frombuffer shape  (2764800,)
main: loop buf reshape  (720, 1280, 3)
main: frame shape  (720, 1280, 3)
Main process done

Немного застрял при совместном использовании кадров в массивах.У меня очереди работают просто отлично.Первый пост в stackoverflow.Предложения?

Ответы [ 3 ]

0 голосов
/ 23 октября 2018

Я понял это.Да, как указал Дэн, мне пришлось установить блокировку (пробовал один раз).Также я должен был правильно определить типы и размеры.Изменение формы любит hxwxc, и я привык к wxhx c.Вот рабочее решение без цикла, где оба процесса отображают одно и то же изображение opencv3 через массив.

import cv2
import multiprocessing as mp
import numpy as np
import ctypes
import time


class Worker(mp.Process):
    def __init__(self,sharedArray,lock, width, height, channels):
        super(Worker, self).__init__()
        self.s=sharedArray
        self.lock = lock
        self.w = width
        self.h = height
        self.c = channels
        return

    def run(self):
        print("worker running")

        self.lock.acquire()
        buf = np.frombuffer(self.s.get_obj(), dtype='uint8')
        buf2 = buf.reshape(self.h, self.w, self.c)
        self.lock.release()

        print("worker ",buf2.shape, buf2.size)
        cv2.imshow("worker",buf2)
        cv2.waitKey(-1)


if __name__ == '__main__':

    img = cv2.imread('pic640x480.jpg')
    shape = img.shape
    size = img.size
    width = shape[1]
    height = shape[0]
    channels = shape[2]

    realsize = width * height * channels
    print('main ', shape, size, realsize)

    s = mp.Array(ctypes.c_uint8, realsize)
    lock = mp.Lock()
    lock.acquire()
    buf = np.frombuffer(s.get_obj(), dtype='uint8')
    buf2 = buf.reshape(height, width, channels)
    buf2[:] = img
    lock.release()

    worker = Worker(s,lock,width, height, channels)
    worker.start()

    cv2.imshow("img",img)
    cv2.waitKey(-1)

    worker.join()
    cv2.destroyAllWindows()

Спасибо за комментарии.

0 голосов
/ 13 ноября 2018

Кстати, я отказался от этого подхода.Я определил, что на Raspberry Pi 3B издержки на отправку изображений 1280x720 по адресным пространствам процессов были слишком велики. ЦП был привязан на 98%, просто перемещая кадры вокруг.Я вернулся к потокам и, похоже, получил повышение производительности на несколько процентов по сравнению с однопоточным кодом.

0 голосов
/ 22 октября 2018

Попробуйте добавить

img = img.reshape(self.shape)

к вашему методу выполнения чуть ниже строки np.frombuffer

img, кажется, имеет неправильную форму и, следовательно, неверно истолковано.

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