Home > database >  blit opencv camera capture with pygame throws TypeError: argument 1 must be pygame.Surface, not cv2.
blit opencv camera capture with pygame throws TypeError: argument 1 must be pygame.Surface, not cv2.

Time:10-16

I'm new to pygame and never used it before and wanted to know how I can blit or display my webcam into the surface by using pygame and opencv but I keep getting the message:

Traceback (most recent call last):
 File "<filename>.py", line 51, in <module>      
   mainWindow()
 File "<filename>.py", line 43, in mainWindow    
   draw_window()
 File "<filename>.py", line 24, in draw_window   
   WINDOW.blit(camera)
TypeError: argument 1 must be pygame.Surface, not cv2.VideoCapture
import pygame 
import cv2

pygame.init()

# setting the width and height of the window
WIDTH, HEIGHT = 1280, 720
WINDOW = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("name me")

# background color 
color = (0, 0, 0)

# 0 is the built in webcam
camera = cv2.VideoCapture(0)
camera.set(cv2.CAP_PROP_FRAME_WIDTH, 700)
camera.set(cv2.CAP_PROP_FRAME_HEIGHT, 900)

def draw_window():
    # background color 
    WINDOW.fill((color))

    # display object onto the surface (screen)
    WINDOW.blit(camera)

    # update the display
    pygame.display.update()


FPS = 30
def mainWindow():
    # keeping the window open 
    run = True 
    clock = pygame.time.Clock()
    while run: 
        # capping it at the set frame rate 
        clock.tick(FPS)

        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                run = False

        draw_window()


    # closing the window 
    pygame.quit()


# main #
mainWindow()

CodePudding user response:

You can only blit a pygame.Surface. Therefore you have to get frame by frame from the camera and convert it to a pygame.Surface object.

Grab a camera frame:

success, camera_image = capture.read()

Convert the camera frame to a pygame.Surface object using pygame.image.frombuffer:

camera_surf = pygame.image.frombuffer(
              camera_image.tobytes(), camera_image.shape[1::-1], "BGR")

Do that in the function draw_window:

def draw_window():
    # background color 
    WINDOW.fill((color))
    
    # display object onto the surface (screen)
    success, camera_image = camera.read()
    if success:
          camera_surf = pygame.image.frombuffer(camera_image.tobytes(), camera_image.shape[1::-1], "BGR")
          WINDOW.blit(camera_surf, (0, 0))
    
    # update the display
    pygame.display.update()

Also see python pygame.camera.init() NO vidcapture and PyGameExamplesAndAnswers - Camera and Video


Alternative but minimal example:

import pygame
import cv2

capture = cv2.VideoCapture(0)
success, camera_image = capture.read()

window = pygame.display.set_mode(camera_image.shape[1::-1])
clock = pygame.time.Clock()

run = success
while run:
    clock.tick(60)
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False
    
    success, camera_image = capture.read()
    if success:
        camera_surf = pygame.image.frombuffer(
            camera_image.tobytes(), camera_image.shape[1::-1], "BGR")
    else:
        run = False
    window.blit(camera_surf, (0, 0))
    pygame.display.flip()

pygame.quit()
exit()

CodePudding user response:

If your goal is to get webcam input into pygame, you could use pygame.camera

It supports Windows and Linux webcams natively, falls back to an OpenCV backend on MacOS.

import pygame
import pygame.camera

pygame.init()
pygame.camera.init()

screen = pygame.display.set_mode((720,500))

cam_list = pygame.camera.list_cameras()
camera = pygame.camera.Camera(cam_list[0], (720,500))
camera.start()

running = True
while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False

    screen.fill("black")
    screen.blit(camera.get_image(), (0,0))
    pygame.display.flip()

pygame.quit()
  • Related