简体   繁体   English

Python 多处理数组和 OpenCV3 帧

[英]Python multiprocessing Array and OpenCV3 Frames

I read this [post] ( Right way to share opencv video frame as Numpy array between multiprocessing processes ) and tried to complete the implementation.我阅读了这篇[帖子]( 在多处理进程之间将 opencv 视频帧共享为 Numpy 数组的正确方法)并尝试完成实施。 The camera is taking images just find, the shapes of images, buffers and received image in another process are matching.相机正在拍摄刚刚找到的图像,图像的形状,缓冲区和另一个过程中接收到的图像是匹配的。 But the received image shows black and white noise lines.但是接收到的图像显示黑白噪声线。 I tried adding locks before the read/write Array to no avail.我尝试在读/写数组之前添加锁无济于事。

Here is the code.这是代码。 Basically I want to put an image into a numpy and then into an Array so another process can read the image:基本上我想将图像放入 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()

The output is two good windows, and one black/white stripped window, plus the following (trimmed): output 是两个好的 windows 和一个黑白剥离的 window,加上以下内容(修剪):

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

A bit stuck on sharing frames on Arrays. I have Queues working just fine.有点卡在 Arrays 上的共享帧上。我的队列工作得很好。 First post to stackoverflow.第一次发布到 stackoverflow。 Suggestions?建议?

Try adding 尝试添加

img = img.reshape(self.shape)

to your run method just below the np.frombuffer line 到np.frombuffer行下面的运行方法

img seems to have the wrong shape and is thus misinterpreted. img似乎形状错误,因此被误解了。

I figured it out. 我想到了。 Yes, as Dan pointed out I had to put locking in (tried it once before). 是的,正如Dan所指出的,我必须加锁(之前尝试过一次)。 Also I had to get the types and sizes correct. 另外我还必须弄清楚类型和大小。 The reshape likes hxwxc and I am used to wxhx c. 重塑就像hxwxc,我习惯了wxhx c。 Here is a working solution without the loop, where both processes display the same opencv3 image via Array. 这是一个没有循环的可行解决方案,其中两个进程都通过Array显示相同的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()

Thanks for the comments. 感谢您的评论。

BTW, I gave up on this approach. 顺便说一句,我放弃了这种方法。 I determined that on a Raspberry Pi 3B, the overhead of sending 1280x720 images across process address spaces was too much The CPU was pegged at 98% just moving frames around. 我确定在Raspberry Pi 3B上,跨进程地址空间发送1280x720图像的开销太大了。CPU只是移动帧而已达到98%。 I fell back to Threads and appear to have gained a few percent improvement in performance over single threaded code. 我回到了Threads,似乎在性能上比单线程代码提高了百分之几。

I had a similar problem.我有一个类似的问题。 I had 4 cameras streaming from the.network.我有 4 个摄像头从 the.network 流式传输。 The image frames changed and stacked.图像帧改变并堆叠。 Queues were too slow for me so I solved the whole thing with pipes.队列对我来说太慢了,所以我用管道解决了整个问题。 Queues are based on that.队列基于此。 4 cameras stacked in a 4 tile and processed with multiprocessing. 4 个摄像头堆叠在一个 4 块中,并使用多处理进行处理。 Works very well in my opinion.在我看来效果很好。 I also have no more delay by using pipes instead of queues.通过使用管道而不是队列,我也没有更多的延迟。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM