簡體   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