如何通过多重处理将布尔值从一个函数返回到另一个函数?

2024-04-20 08:37:15 发布

您现在位置:Python中文网/ 问答频道 /正文

我有四个功能;三个摄像头功能(拍照保存图像,将路径保存到CSV文件),第四个功能是通过arduino从串行连接获取数据。每个函数都独立地通过正常的multiprocessing(没有join())工作。由于opencv函数的工作方式,我不能使用join()方法。我知道join方法是有效的,它会在再次运行之前等待child processes完成。你知道吗

我需要能够从arduino函数向camera函数返回一个值(布尔值:True/False或0/1),然后再开始。Arduino代码需要最长的时间运行。 下面是通用代码

import cv2
import multiprocessing
import Serial


def camera1():
    global cap1
    cap1 = cv2.VideoCapture(0)
    while True:
        _, frame1 = cap1.read()
        cv2.imshow('frame1', frame1)

        k = cv2.waitKey(5)
        if k == 27:
            break
       """
       Saves image and add to csv file
       while loop checking for ard_serial is complete to repeat
       """
    cap1.release()


def camera2():
    global cap2
    cap2 = cv2.VideoCapture(1)
    while True:
        _, frame2 = cap2.read()
        cv2.imshow('frame2', frame2)

        k = cv2.waitKey(5)
        if k == 27:
            break
       """
       Saves image and add to csv file
       while loop checking for ard_serial is complete to repeat
       """
    cap2.release()



def camera3():
    global cap3
    cap3 = cv2.VideoCapture(2)
    while True:
        _, frame3 = cap3.read()
        cv2.imshow('frame3', frame3)

        k = cv2.waitKey(5)
        if k == 27:
            break
       """
       Saves image and add to csv file
       while loop checking for ard_serial is complete to repeat
       """
    cap3.release()


def ard_serial():
   """
   Serial Stuff happens here
   When Complete sends value to cam functions
   to start again.
   """

if __name__ == '__main__':
   for _ in range(20)
       p1 = multiprocessing.Process(target=camera1)
       p1.start()
       p2 = multiprocessing.Process(target=camera2)
       p2.start()
       p3 = multiprocessing.Process(target=camera3)
       p3.start()
       p4 = multiprocessing.Process(target=ard_serial)
       p4.start()
       """
       p1.join()
       p2.join()
       p3.join()
       p4.join()
       """

我需要所有四个功能同时启动,让cam功能等待arduino功能完成后再启动。我能用什么做这个?我不确定我是否必须使用Queue或者其他什么。另外,大多数示例只有一个worker函数返回某些内容。我需要一个函数向另一个函数发送返回值。join()方法不会工作,因为while循环可能永远不会结束,直到它完成


Tags: to函数功能trueforifdefserial
2条回答

最简单的方法是使用事件在不同进程之间发送信号。你知道吗

事件是同步处理的一种非常基本的方式。它们可以设置(=真)或清除(=假)。它们还有一个等待函数,在事件设置为True之前阻塞。由于它们是线程安全的,因此可以在进程之间共享。你知道吗

Documentation Event

比如:

import cv2
import multiprocessing
import Serial


def camera1(e):
    global cap1
    cap1 = cv2.VideoCapture(0)
    while True:
        e.wait()
        _, frame1 = cap1.read()
        cv2.imshow('frame1', frame1)

        k = cv2.waitKey(5)
        if k == 27:
            break
       """
       Saves image and add to csv file
       while loop checking for ard_serial is complete to repeat
       """
    cap1.release()


def camera2(e):
    global cap2
    cap2 = cv2.VideoCapture(1)
    while True:
        e.wait()
        _, frame2 = cap2.read()
        cv2.imshow('frame2', frame2)

        k = cv2.waitKey(5)
        if k == 27:
            break
       """
       Saves image and add to csv file
       while loop checking for ard_serial is complete to repeat
       """
    cap2.release()



def camera3(e):
    global cap3
    cap3 = cv2.VideoCapture(2)
    while True:
        e.wait()
        _, frame3 = cap3.read()
        cv2.imshow('frame3', frame3)

        k = cv2.waitKey(5)
        if k == 27:
            break
       """
       Saves image and add to csv file
       while loop checking for ard_serial is complete to repeat
       """
    cap3.release()


def ard_serial(e):
   """
   Serial Stuff happens here
   When Complete sends value to cam functions
   to start again.
   """
        e.clear()
        #do your stuff
        e.set()

if __name__ == '__main__':
   e = multiprocessing.event()
   for _ in range(20)
       p1 = multiprocessing.Process(target=camera1, args=[e,])
       p1.start()
       p2 = multiprocessing.Process(target=camera2, args=[e,])
       p2.start()
       p3 = multiprocessing.Process(target=camera3, args=[e,])
       p3.start()
       p4 = multiprocessing.Process(target=ard_serial, args=[e,])
       p4.start()
       """
       p1.join()
       p2.join()
       p3.join()
       p4.join()
       """

我不确定你是否需要multiprocessing。以下代码可能有助于突出显示/解决您遇到的一些问题:

import cv2

caps = {}
for i in range(3):
    cap = cv2.VideoCapture(i)
    # make sure we don't get too far behind
    cap.set(cv2.CAP_PROP_BUFFERSIZE, 1)
    caps[i] = cap

我首先打开所有捕获设备并将它们的缓冲区大小设置为1帧。否则,如果您在帧之前等待串行活动,您将倾向于使用较旧的/缓冲的帧,而不是实际需要的较新的帧。你知道吗

接下来我们运行主循环

frame = 0
while True:
    frame += 1

    # TODO: wait/check/handle for Serial activity

    # clear out any old/buffered frames
    for cap in caps.values():
        cap.read()

    # read recent frames
    for i, cap in caps.items():
        _, img = cap.read()
        # save to a file and display in window
        cv2.imwrite(f'output/{frame:06}-{i}.jpeg', img)
        cv2.imshow(f'cap {i}', img)

    # handle GUI events/check for keys
    if cv2.waitKey(1) == 27:
        break

你没有包括任何实际的代码,你想检查串行活动,但你应该能够使用任何阻塞函数那里。当串行代码完成时,它从所有相机读取并丢弃缓冲帧,然后将后续帧保存到磁盘。请注意,所有的清除都应该同时进行,这样(异步)相机设备就可以开始将它们的下一帧流到一起,然后我们再次检查所有设备,以便在它们准备好时拾取帧

鉴于你上面所写的,我认为这应该是一个合理的模板来解决你的问题。当然可以使用multiprocessing,但我认为这只会使您在这里所做的事情复杂化,没有任何好处

相关问题 更多 >