繁体   English   中英

如何以不同的帧速率同时运行 python 中的两个程序?

[英]How do you run two programs in python simultaneously at different frame rates?

我一直在 python 中试验 OpenCV,我想在 pygame 中用它做一个游戏。 但这太慢了, OpenCV 以8 fps运行,但我希望 pygame 游戏以60 fps运行。 我不需要快速跟踪,但我希望 pygame 以正常帧速率运行。 我曾尝试在 python 中使用内置的 sockets,但它会使两个程序都以 8 fps 运行。 然后我试图阻止套接字在等待数据时暂停,但什么也没改变。 谢谢。

姿势.py

import cv2
import mediapipe as mp
import time
import numpy as np
cap = cv2.VideoCapture(0)

mpHands = mp.solutions.hands
hands = mpHands.Hands(static_image_mode=False,
                      max_num_hands=8,
                      min_detection_confidence=0.5,
                      min_tracking_confidence=0.5)
mpDraw = mp.solutions.drawing_utils

pTime = 0
cTime = 0

while True:
    success, img = cap.read()
    imgRGB = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
    results = hands.process(imgRGB)
    #print(results.multi_hand_landmarks)

    if results.multi_hand_landmarks:
        handId = 0
        for handLms in results.multi_hand_landmarks:
            avX = avY = l = 0
            for id, lm in enumerate(handLms.landmark):
                #print(id,lm)
                h, w, c = img.shape
                l += 1
                cx, cy = int(lm.x *w), int(lm.y*h)
                avX += cx
                avY += cy
                #if id ==0:
                cv2.circle(img, (cx,cy), 3, (255,0,2555), cv2.FILLED)
            avX = avX / l
            avY = avY / l

            mpDraw.draw_landmarks(img, handLms, mpHands.HAND_CONNECTIONS)
            handId += 1


    cTime = time.time()
    fps = 1/(cTime-pTime)
    pTime = cTime

    cv2.putText(img,str(int(fps)), (10,70), cv2.FONT_HERSHEY_PLAIN, 3, (255,0,255), 3)

    #cv2.imshow("Image", img)
    cv2.waitKey(1)

姿势游戏.py

import pygame
pygame.init()

screen = pygame.display.set_mode((960, 540))
clock = pygame.time.Clock()
while True:
    screen.fill((0, 0, 0))

    # ...
    
    clock.tick(60)
    pygame.display.update()

你有三个选择。

第一个选项是让游戏或应用程序作为主 python 应用程序运行,另一个使用多处理模块作为子进程运行,并使用manager.queue在两个进程之间进行通信,游戏将检查是否存在每帧队列中的某些内容(如果找到,则弹出消息)。

第二个(更难的)选项是使用socket.setblocking在非阻塞模式下使用socket.setblocking ,因此游戏在其他应用程序完成传输之前不会阻塞,但您需要在每一帧上增量更新内部“消息缓冲区”由于消息将在多个帧上接收,这种方法的优点是游戏和命令应用程序将是两个独立的应用程序,没有共享代码,因此通信甚至不必在 python 内。

第三种选择是使用阻塞 sockets 的线程,其中子线程将监视从其他应用程序接收到的消息并将其放在deque或主线程上进行读取。

这两种方法的一个缺点是应用程序必须不断地向游戏发送消息,因为两个应用程序将以不同的速率运行,因此游戏需要保存最后一条消息并继续使用它,直到它收到下一条消息。

你需要线程。

不要为此乱用 sockets,这是不必要的复杂。 您也不一定需要 multi processing 线程很好。 所有繁重的工作(OpenCV、mediapipe,...)都会释放 GIL。 如果你不知道那是什么意思,没关系。 我是说对于那些认为线程不能使用的人。

您需要一个用于媒体管道内容的线程和另一个用于读取相机的线程。 您可以在主线程(不是您自己启动的线程)中执行您的游戏逻辑。

相机读取线程是必需的,因为如果您尽快从相机读取数据,因为它可以产生帧(假设您正在同一个循环中处理),产生的帧将在驱动程序中排队,您会得到延迟 让这个线程从相机中读取并保留最新的帧(在变量中),并且什么也不做。

每当媒体管道线程准备好(更多)工作时,它都会从相机线程获取当前帧。 通过简单地访问变量来做到这一点。 然后它可以通过设置变量或发布到Queue对象(python 带有一个queue模块)来工作并将其结论发送到游戏。 当从可能不包含 object 的队列中读取时,但添加元素之前您不想阻塞,您需要在“get”调用中指定零超时并捕获“empty”异常。

暂无
暂无

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

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