使用管道的多处理脚本

multiprocessing script using Pipes

当我尝试 运行 以下脚本时,进程 1 仅显示 1 秒的视频并卡住。代码有什么问题吗?我的目标是 运行 两个进程,一个连续显示帧,另一个进程执行人脸检测并在 process1 设置事件时打印结果。进程 1 定期设置事件,即每 20 或 30 帧之后。

def read(e,parent):

    fps,st,frames_to_count,cnt = (0,0,30,0)
    vid = cv2.VideoCapture('sample.mp4')
    wid = 640
    while(vid.isOpened()):
        res,frame = vid.read()
        if not res:
            break
        frame = imutils.resize(frame,width = wid)
        cv2.imshow('VIDEO',frame)
        key = cv2.waitKey(1) & 0xFF
        if key == ord('q'):
            break
        if cnt == frames_to_count:
            try:
                fps = round(frames_to_count/(time.time()-st))
                parent.send(frame)
                e.set()
                st=time.time()
                cnt=0
            except:
                pass
        cnt+=1
    cv2.destroyAllWindows()

def fd(e,child):

    face_cascade=cv2.CascadeClassifier("path to xml")
    while True:
        e.wait()
        faces=face_cascade.detectMultiScale(child.recv(),1.1,4)
        print(faces)
        e.clear()

def main():

    e = Event()
    (child,parent) = Pipe()
    p1 = Process(target=read, args=(e,parent))
    p2 = Process(target=fd, args=(e,child))
    p1.start() 
    p2.start()
    p1.join()
    p2.join()


if __name__ == "__main__":

  main()

查看我对您发布的问题的所有评论。在下面的代码中,我保留了您正在使用的 Pipe 但指定了 duplex=False 因为您没有使用返回的连接进行 two-way 通信并且有相应地将这些连接从 childparent 重命名为现在更有意义的 read_connsend_conn。当然,我已经删除了 Event 实例。

由于 fd 似乎处于一个永不终止的循环中,main 将永远无法 join 该过程。因此,p2 应创建为 守护进程 进程,当所有 non-daemon 进程和线程终止时,该进程将自动终止。

def read(send_conn):

    fps,st,frames_to_count,cnt = (0,0,30,0)
    vid = cv2.VideoCapture('sample.mp4')
    wid = 640
    while(vid.isOpened()):
        res,frame = vid.read()
        if not res:
            break
        frame = imutils.resize(frame,width = wid)
        cv2.imshow('VIDEO',frame)
        key = cv2.waitKey(1) & 0xFF
        if key == ord('q'):
            break
        if cnt == frames_to_count:
            try:
                fps = round(frames_to_count/(time.time()-st))
                send_conn.send(frame)
                st=time.time()
                cnt=0
            except:
                pass
        cnt+=1
    cv2.destroyAllWindows()

def fd(recv_conn):

    face_cascade=cv2.CascadeClassifier("path to xml")
    while True:
        faces=face_cascade.detectMultiScale(recv_conn.recv(),1.1,4)
        print(faces)

def main():

    (recv_conn,send_conn) = Pipe(duplex=False)
    p1 = Process(target=read, args=(send_conn,))
    p2 = Process(target=fd, args=(recv_conn,), daemon=True)
    p1.start() 
    p2.start()
    p1.join()


if __name__ == "__main__":

    main()