I have a python program that starts an OpenCV face detection function on startup. This code works fine and the camera is able to run and face detection works fine. On pressing the 'Q' key within the OpenCV frame, a pygame program (Pong) is started.
However, once the game starts, the OpenCV capture hangs immediately. How do i fix my code so that both are running in parallel?
from time import sleep
import cv2
from cvzone.FaceDetectionModule import FaceDetector
import numpy as np
import logging
import threading
from time import sleep
import time
import pygame
pygame.init()
# Font that is used to render the text
font20 = pygame.font.Font('freesansbold.ttf', 20)
# RGB values of standard colors
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
GREEN = (0, 255, 0)
# Basic parameters of the screen
WIDTH, HEIGHT = 900, 600
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("Pong")
clock = pygame.time.Clock()
FPS = 30
# Striker class
class Striker:
# Take the initial position, dimensions, speed and color of the object
def __init__(self, posx, posy, width, height, speed, color):
self.posx = posx
self.posy = posy
self.width = width
self.height = height
self.speed = speed
self.color = color
# Rect that is used to control the position and collision of the object
self.geekRect = pygame.Rect(posx, posy, width, height)
# Object that is blit on the screen
self.geek = pygame.draw.rect(screen, self.color, self.geekRect)
# Used to display the object on the screen
def display(self):
self.geek = pygame.draw.rect(screen, self.color, self.geekRect)
def update(self, yFac):
self.posy = self.posy + self.speed*yFac
# Restricting the striker to be below the top surface of the screen
if self.posy <= 0:
self.posy = 0
# Restricting the striker to be above the bottom surface of the screen
elif self.posy + self.height >= HEIGHT:
self.posy = HEIGHT-self.height
# Updating the rect with the new values
self.geekRect = (self.posx, self.posy, self.width, self.height)
def displayScore(self, text, score, x, y, color):
text = font20.render(text+str(score), True, color)
textRect = text.get_rect()
textRect.center = (x, y)
screen.blit(text, textRect)
def getRect(self):
return self.geekRect
# Ball class
class Ball:
def __init__(self, posx, posy, radius, speed, color):
self.posx = posx
self.posy = posy
self.radius = radius
self.speed = speed
self.color = color
self.xFac = 1
self.yFac = -1
self.ball = pygame.draw.circle(
screen, self.color, (self.posx, self.posy), self.radius)
self.firstTime = 1
def display(self):
self.ball = pygame.draw.circle(
screen, self.color, (self.posx, self.posy), self.radius)
def update(self):
self.posx += self.speed*self.xFac
self.posy += self.speed*self.yFac
# If the ball hits the top or bottom surfaces,
# then the sign of yFac is changed and
# it results in a reflection
if self.posy <= 0 or self.posy >= HEIGHT:
self.yFac *= -1
if self.posx <= 0 and self.firstTime:
self.firstTime = 0
return 1
elif self.posx >= WIDTH and self.firstTime:
self.firstTime = 0
return -1
else:
return 0
def reset(self):
self.posx = WIDTH//2
self.posy = HEIGHT//2
self.xFac *= -1
self.firstTime = 1
# Used to reflect the ball along the X-axis
def hit(self):
self.xFac *= -1
def getRect(self):
return self.ball
# Game Manager
def pong():
running = True
# Defining the objects
geek1 = Striker(20, 0, 10, 100, 10, GREEN)
geek2 = Striker(WIDTH-30, 0, 10, 100, 10, GREEN)
ball = Ball(WIDTH//2, HEIGHT//2, 7, 7, WHITE)
listOfGeeks = [geek1, geek2]
# Initial parameters of the players
geek1Score, geek2Score = 0, 0
geek1YFac, geek2YFac = 0, 0
while running:
screen.fill(BLACK)
# Event handling
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_UP:
geek2YFac = -1
if event.key == pygame.K_DOWN:
geek2YFac = 1
if event.key == pygame.K_w:
geek1YFac = -1
if event.key == pygame.K_s:
geek1YFac = 1
if event.type == pygame.KEYUP:
if event.key == pygame.K_UP or event.key == pygame.K_DOWN:
geek2YFac = 0
if event.key == pygame.K_w or event.key == pygame.K_s:
geek1YFac = 0
# Collision detection
for geek in listOfGeeks:
if pygame.Rect.colliderect(ball.getRect(), geek.getRect()):
ball.hit()
# Updating the objects
geek1.update(geek1YFac)
geek2.update(geek2YFac)
point = ball.update()
# -1 -> Geek_1 has scored
# +1 -> Geek_2 has scored
# 0 -> None of them scored
if point == -1:
geek1Score += 1
elif point == 1:
geek2Score += 1
# Someone has scored
# a point and the ball is out of bounds.
# So, we reset it's position
if point:
ball.reset()
# Displaying the objects on the screen
geek1.display()
geek2.display()
ball.display()
# Displaying the scores of the players
geek1.displayScore("Geek_1 : ",
geek1Score, 100, 20, WHITE)
geek2.displayScore("Geek_2 : ",
geek2Score, WIDTH-100, 20, WHITE)
pygame.display.update()
clock.tick(FPS)
def getface():
print("Face")
cap = cv2.VideoCapture(0)
ws, hs = 1280, 720
cap.set(3, ws)
cap.set(4, hs)
fx=0
if not cap.isOpened():
print("Camera couldn't Access!!!")
exit()
#port = "COM7"
#board = pyfirmata.Arduino(port)
#servo_pinX = board.get_pin('d:9:s') #pin 9 Arduino
#servo_pinY = board.get_pin('d:10:s') #pin 10 Arduino
detector = FaceDetector()
#servoPos = [90, 90] # initial servo position
while True:
success, img = cap.read()
img, bboxs = detector.findFaces(img, draw=False)
if bboxs:
#get the coordinate
fx, fy = bboxs[0]["center"][0], bboxs[0]["center"][1]
pos = [fx, fy]
cv2.circle(img, (fx, fy), 80, (0, 0, 255), 2)
cv2.putText(img, str(pos), (fx+15, fy-15), cv2.FONT_HERSHEY_PLAIN, 2, (255, 0, 0), 2 )
cv2.line(img, (0, fy), (ws, fy), (0, 0, 0), 2) # x line
cv2.line(img, (fx, hs), (fx, 0), (0, 0, 0), 2) # y line
cv2.circle(img, (fx, fy), 15, (0, 0, 255), cv2.FILLED)
cv2.putText(img, "TARGET LOCKED", (850, 50), cv2.FONT_HERSHEY_PLAIN, 3, (255, 0, 255), 3 )
else:
cv2.putText(img, "NO TARGET", (880, 50), cv2.FONT_HERSHEY_PLAIN, 3, (0, 0, 255), 3)
cv2.circle(img, (640, 360), 80, (0, 0, 255), 2)
cv2.circle(img, (640, 360), 15, (0, 0, 255), cv2.FILLED)
cv2.line(img, (0, 360), (ws, 360), (0, 0, 0), 2) # x line
cv2.line(img, (640, hs), (640, 0), (0, 0, 0), 2) # y line
cv2.putText(img, f'Servo X: 1 deg', (50, 50), cv2.FONT_HERSHEY_PLAIN, 2, (255, 0, 0), 2)
cv2.putText(img, f'Servo Y: 88 deg', (50, 100), cv2.FONT_HERSHEY_PLAIN, 2, (255, 0, 0), 2)
#servo_pinX.write(servoPos[0])
#servo_pinY.write(servoPos[1])
cv2.imshow("Image", img)
if cv2.waitKey(1) & 0xFF == ord("q"):
t1=threading.Thread(target=pong())
t1.start()
t1.join()
#break
cap.release()
def main():
t2=threading.Thread(target=getface())
t2.start()
#t1.start()
#t2.join()
#t1.join()
if __name__ == "__main__":
main()
pygame.quit()