I am trying to use opencv (cv2) to stream a webcam to a pygame surface object. The problem is that the colors are not displayed correctly. I think this is casting of types, but itβs hard for me to understand the documentation on the surface of the pygmake to know what it expects.
This code demonstrates what I'm talking about
import pygame from pygame.locals import * import cv2 import numpy color=False#True#False camera_index = 0 camera=cv2.VideoCapture(camera_index) camera.set(3,640) camera.set(4,480) #This shows an image the way it should be cv2.namedWindow("w1",cv2.CV_WINDOW_AUTOSIZE) retval,frame=camera.read() if not color: frame=cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY) cv2.flip(frame,1,frame)#mirror the image cv2.imshow("w1",frame) #This shows an image weirdly... screen_width, screen_height = 640, 480 screen=pygame.display.set_mode((screen_width,screen_height)) def getCamFrame(color,camera): retval,frame=camera.read() if not color: frame=cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY) frame=numpy.rot90(frame) frame=pygame.surfarray.make_surface(frame) #I think the color error lies in this line? return frame def blitCamFrame(frame,screen): screen.blit(frame,(0,0)) return screen screen.fill(0) #set pygame screen to black frame=getCamFrame(color,camera) screen=blitCamFrame(frame,screen) pygame.display.flip() running=True while running: for event in pygame.event.get(): #process events since last loop cycle if event.type == KEYDOWN: running=False pygame.quit() cv2.destroyAllWindows()
The ultimate goal I have is to create a small photo paper application for DIY weddings next year. I am new to programming, but I managed to combine this together. I also tried to do this using VideoCapture, which outputs PIL, which I also could not get to work with a surface object. I want to use the pygame surface so that I can animate and overlay back text, borders, etc.
Update: The problem was that the cv2 camera.read () function returns a BGR image, but pygame.surfarray expects an RGB image. This is fixed by a line.
frame=cv2.cvtColor(frame,cv2.COLOR_BGR2RGB)
In addition, when converting to grayscale, the following code works:
frame=cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY) frame=cv2.cvtColor(frame,cv2.COLOR_GRAY2RGB)
So now the getCamFrame function should be
def getCamFrame(color,camera): retval,frame=camera.read() frame=cv2.cvtColor(frame,cv2.COLOR_BGR2RGB) if not color: frame=cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY) frame=cv2.cvtColor(frame,cv2.COLOR_GRAY2RGB) frame=numpy.rot90(frame) frame=pygame.surfarray.make_surface(frame) return frame