0

我想在 Raspberry Pi 3 上使用 PiCamera 运行连续流,并与该流并行执行其他计算。

我只需要从该流(进程)中获取它检测到的对象。我将在这里发布我到目前为止的代码。它没有进入computation()函数。它只是启动相机并检测那里的物体并停留在该过程中。

我尝试过使用multiprocessingPython 中的模块,但它似乎不起作用。

def startRecord():
    frame_rate_calc = 1
    freq = cv2.getTickFrequency()
    font = cv2.FONT_HERSHEY_SIMPLEX
    camera = PiCamera()
    camera.resolution = (IM_WIDTH, IM_HEIGHT)
    camera.framerate = 10
    camera.vflip = True
    rawCapture = PiRGBArray(camera, size=(IM_WIDTH, IM_HEIGHT))
    rawCapture.truncate(0)

    for frame1 in camera.capture_continuous(rawCapture, format="bgr", use_video_port=True):
        object_detected = "none"
        t1 = cv2.getTickCount()

        # Acquire frame and expand frame dimensions to have shape: [1, None, None, 3]
        # i.e. a single-column array, where each item in the column has the pixel RGB value
        frame = np.copy(frame1.array)
        frame.setflags(write=1)
        frame_expanded = np.expand_dims(frame, axis=0)

        # Perform the actual detection by running the model with the image as input
        (boxes, scores, classes, num) = sess.run(
            [detection_boxes, detection_scores, detection_classes, num_detections],
            feed_dict={image_tensor: frame_expanded})

        # Draw the results of the detection (aka 'visualize the results')
        vis_util.visualize_boxes_and_labels_on_image_array(
            frame,
            np.squeeze(boxes),
            np.squeeze(classes).astype(np.int32),
            np.squeeze(scores),
            category_index,
            use_normalized_coordinates=True,
            line_thickness=8,
            min_score_thresh=0.40)

        if classes[0][0] == 1 and scores[0][0] > 0.98:
            object_detected = "circle"
        elif classes[0][0] == 2 and scores[0][0] > 0.98:
            object_detected = "donnut"
        elif classes[0][0] == 3 and scores[0][0] > 0.98:
            object_detected = "square"
        elif classes[0][0] == 4 and scores[0][0] > 0.98:
            object_detected = "alphabot"

        cv2.putText(frame, "FPS: {0:.2f}".format(frame_rate_calc), (30, 50), font, 1, (255, 255, 0), 2, cv2.LINE_AA)

        # All the results have been drawn on the frame, so it's time to display it.
        cv2.imshow('Object detector', frame)

        t2 = cv2.getTickCount()
        time1 = (t2 - t1) / freq
        frame_rate_calc = 1 / time1

        # Press 'q' to quit
        if cv2.waitKey(1) == ord('q'):
            break

        rawCapture.truncate(0)
    camera.close()


def computation():
    print("OUTSIDE OF CAPTURE")
    print(object_detected)
### Picamera ###
if camera_type == 'picamera':
    # Initialize Picamera and grab reference to the raw capture
    p1 = Process(target=startRecord())
    p2 = Process(target=computation())
    p1.start()
    p2.start()


    p1.join()
    p2.join()
4

1 回答 1

0

您的意图很明确,但您发布的代码需要一些润色,而 RPi3 将是旅程中最困难的部分:

  • multiprocessing模块确实能够产生一个子进程池,但代价是巨大的——它既[PSPACE]填充了 python 解释器会话的完整副本(有状态并且为每个复制副本获取大量 RAM),又在[PTIME],因为它花费的时间越多,一个产生的子进程就越多(一次性成本,但对于开销严格的阿姆达尔定律重新制定最大并行加速收益评估非常重要)

  • RPi3 IIRC 上的 RAM 不超过 1 MB,因此您的 TF 模型必须确实是微型的,或者您必须小心地生成 TF 专用子进程,使其不会复制相同的 TF-BLOB主会话(而不是在那里留下相同的 BLOB)- 相当棘手的部分。

  • 尽管如此,您仍需要在预期的分布式处理的两端进行协调。一个进程不能把手伸进另一个进程的口袋里,也不能在邻居的明确意愿(和控制)之外获取任何价值。目前: -- 一侧,调用为p1 = Process( target = startRecord() )永远不会调用 acomputation()来完成 -- 另一侧,调用时p2 = Process( target = computation() )永远不会接收(并且根据它的设计,它甚至不需要这样做)单件来自其他任何地方的数据(对某个变量/对象的唯一引用 -object_detected- 已经从主会话中预先复制,处于子流程实例化期间的这种状态(如果有的话),并且已成为完全分离的副本(有意未连接且未-协调任何现在“外部”的变化——因为这组特性解放了任何中央主会话的 GIL 锁协调开销的子进程,并且子进程可以独立工作,享受更高级别的[CONCURRENT]进程执行( s))

解决方案:

a) 验证大小是否满足 RPi3 RAM 限制的范围

b) 在产生任何专门的子进程之前调整主会话的大小

c) 设计进程间通信(默认队列/deQueue 可能变得不适合快速高效的处理 - 可能会享受更智能和更可控的信令/消息传递框架,例如 ZeroMQ ipc://,用于以几乎零复制的方式移动原始字节块- 是的,一次又一次,RPi3 RAM-ceiling 会伤害你 -[PSPACE]明智的(以便在 en-Queue / de-Queue 两侧开销)和 -[PTIME]明智的(因为附加延迟会增长,可能超出一个人的过程控制可接受的阈值))

于 2019-07-08T11:12:22.233 回答