Skip to content

Instantly share code, notes, and snippets.

@radames
Last active April 17, 2023 15:34
Show Gist options
  • Save radames/1e7c794842755683162b to your computer and use it in GitHub Desktop.
Save radames/1e7c794842755683162b to your computer and use it in GitHub Desktop.
OpenCV VideoCapture running on PyGame - repo ref https://github.com/radames/opencv_video_to_pygame
from pygame.locals import KEYDOWN, K_ESCAPE, K_q
import pygame
import cv2
import sys
camera = cv2.VideoCapture(1)
pygame.init()
pygame.display.set_caption("OpenCV camera stream on Pygame")
screen = pygame.display.set_mode([1280, 720])
try:
while True:
ret, frame = camera.read()
screen.fill([0, 0, 0])
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
frame = frame.swapaxes(0, 1)
pygame.surfarray.blit_array(screen, frame)
pygame.display.update()
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit(0)
elif event.type == KEYDOWN:
if event.key == K_ESCAPE or event.key == K_q:
sys.exit(0)
except (KeyboardInterrupt, SystemExit):
pygame.quit()
cv2.destroyAllWindows()
@jaxx99
Copy link

jaxx99 commented Jul 26, 2019

I know this code is bit old but you can replace the line:

frame = np.rot90(frame)

with:

frame = frame.swapaxes(0,1)

to improve the performance.
Here is the timeit comparision:

python3 -m timeit -s 'import numpy as np' -s 'a = np.zeros((1024,1024,3))' 'a = a.swapaxes(0,1)'
200000 loops, best of 5: 1.2 usec per loop
python3 -m timeit -s 'import numpy as np' -s 'a = np.zeros((1024,1024,3))' 'a = np.rot90(a)'
10000 loops, best of 5: 31.3 usec per loop

The reason for using either of functions is because the opencv represent images in (height, width) format rather than (Width,Height) which is general representation in pygame(or any normal library but not opencv!!!).
So swapaxes basically swaps the two dimensions to obtain (W,H) format
This is similar to how opencv enforces BGR representation and we are explicitly forced to use cvtColor to obtain RGB format.

This little change will also avoid adding extra calls to python cv2.flip(frame,0) in order to get correct result and mirror issues faced by others.

@MarcPartensky
Copy link

Thanks a lot. This will be useful for me. ;)

@radames
Copy link
Author

radames commented Aug 26, 2020

@jaxx99 thanks for the optimization! I've also replaced two surfaces step to a more efficient way using pygame.surfarray.blit_array

@radames
Copy link
Author

radames commented Aug 26, 2020

Folks, I've also create a repo with env for reference https://github.com/radames/opencv_video_to_pygame

Copy link

ghost commented Oct 10, 2020

I am getting this error:
"ValueError: array must match surface dimensions"
What should I do?

@WiktorLigeza
Copy link

I am getting this error:
"ValueError: array must match surface dimensions"
What should I do?

Change screen size to your camera output size screen = pygame.display.set_mode([640, 480]) worked for me.
You can get size of frame easily E.g: print(frame.shape)

@mathcat4
Copy link

I can't thank you enough for this code. Keep it up.

@angelman7
Copy link

angelman7 commented Feb 6, 2021

Guys if anyone had this error

cv2.error: OpenCV(4.5.1) C:\Users\appveyor\AppData\Local\Temp\1\pip-req-build-kh7iq4w7\opencv\modules\imgproc\src\color.cpp:182: error: (-215:Assertion failed) !_src.empty() in function 'cv::cvtColor'

add frame = cv2.VideoCapture(0) below ret, frame = camera.read()

@radames
Copy link
Author

radames commented Feb 9, 2021

hi @angelman7 can't help much but it could be related to your camera image streaming,
read more https://stackoverflow.com/questions/52676020/opencv-src-empty-in-function-cvtcolor-error

@mathcat4
Copy link

Can you show it the other way too?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment