I am very new to python and I am working on a project using pygame and cv2
My first python file code has an output image that shows up in a pygame window, but I have another python file that detects objects and it gets an input video like this:
cap = cv2.VideoCapture("video.mp4")
and then it reads the video and shows the detected objects in the video by surrounding boxes around each object.
I want the cap = cv2.VideoCapture() to get the live video from the pygame window and maybe show the boxes of object detection in a second window or the same pygame window (not sure right now what I want, but maybe showing it in the same pygame window would be better)
I am not sure if this is enough information to help me since I am not very familiar with pygame or cv2, please let me know.
In pygame you are actually drawing on a Surface object. You can get the pygame.Surface object associated with the display with pygame.display.get_surface():
screen = pygame.display.get_surface()
Use pygame.surfarray.pixels3d to create a new 3D array that directly references the pixel values in the Surface. This is equivalent to a cv2 matrix respectively NumPy array when you transpose the x and y axis and transform from RGB to BGR:
capture = pygame.surfarray.pixels3d(screen)
capture = capture.transpose([1, 0, 2])
capture_bgr = cv2.cvtColor(capture, cv2.COLOR_RGB2BGR)
Do this once per frame after updating the display:
def capture_frame():
screen = pygame.display.get_surface()
capture = pygame.surfarray.pixels3d(screen)
capture = capture.transpose([1, 0, 2])
capture_bgr = cv2.cvtColor(capture, cv2.COLOR_RGB2BGR)
return capture_bgr
run = True
while run:
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
# draw
# [...]
pygame.display.flip()
frame_img = capture_frame()
# [...]
Related
i am trying to display this image in a fullscreen window in pygame as the texture for my floor
but when i try to actually display the image inside the pygame window, it comes up as this
for some reason there are random blobs of blue coming up in the image. i used this code to try and put in my image
width,height=pygame.display.get_surface().get_size()
floorimg=pygame.image.load("assets//image.png")
win.blit(floorimg,(0,height-100))
how can i fix this?
Seems like the problem is not the code but the image itself...
Attached is the link of the "floor" image with the transparent area colored using Windows Paint3D.
The code works perfectly fine, but you might need to get some clean pictures in the future.
I saved your image and wrote this script to draw it:
import pygame, sys
pygame.init()
window = pygame.display.set_mode((1300, 200), 0 , 32)
width,height=pygame.display.get_surface().get_size()
floorimg = pygame.image.load("floor.png")
while True:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
window.fill((0))
window.blit(floorimg,(0,height-100))
pygame.display.flip()
It seems to have similar problem to yours if the image is converted to pygame format(which I am assuming you do somewhere else in your code?)
floorimg = pygame.image.load("floor.png").convert()
But this can easily be solved by taking transparency into account while converting, which is done by convert_alpha.
floorimg = pygame.image.load("floor.png").convert_alpha()
This results in an image similar to the first one.
I am creating a painter software and want the user to be able to save their image after they have finished creating it, so I tried pygame.image.save(pygame.display.get_surface(), "/home/user/screenshot.png"). I made a quick drawing and pressed the key I set which would save the image. I look at the image, and it's only saved the blank display surface, not the pygame.draw.rect()s of the actual drawing. I looked at the following links: How to capture pygame screen? https://gamedev.stackexchange.com/questions/118372/how-can-i-take-a-screenshot-of-a-certain-part-of-the-screen-in-pygame Can python get the screen shot of a specific window? and much more. How would I take a screenshot of the entire display screen along with the drawing? This is my mainloop:
running = True
while running:
updateWindow() # Updates window
clearWindow() # Clears window
checkEvents() # Checks events
redrawItems() # Redraws your drawing
pygame.event.pump()
pygame.display.quit()
pygame.quit()
Try pygame.Surface.copy on the display surface. See docs here.
So if display is your screen, then:
screencopy = display.copy()
should get you a copy of the display image in screencopy. Remember because of double buffering it will give you a copy of what you would see on the screen if you did an display.update() right then, which might be different that what is showing on the screen if you have done things that have not yet been pushed to the screen yet by an update().
You can do this using pygame.image.save(Surface, filename), which you can read more about
here
Below is a simple function that will save a portion of the display as an image.
def Capture(display,name,pos,size): # (pygame Surface, String, tuple, tuple)
image = pygame.Surface(size) # Create image surface
image.blit(display,(0,0),(pos,size)) # Blit portion of the display to the image
pygame.image.save(image,name) # Save the image to the disk**
What this function does is created a pygame surface named image. Then the area (pos,size) is blitted to image at its origin. Finally, pygame.image.save(Surface, filename) will be called and save image to the disk.
For example, if we want to save a 100x100 image named "Capture.png" at the pos 50x50 on the display, name would equal "Capture.png", pos would equal (50,50), and size would equal (100,100), and the function call would look as such:
Capture(display,"Capture.png",(50,50),(100,100))
I am trying to get a Raspberry Pi 3B+ to show live streams from 3 cameras, using a screen to get multiple instances of omxplayer to run on the positions I want them. This works exactly as expected.
The problem now is, that I want a static image in the last space on the screen. For that I wanted to use pygame, so I later could have more fun in that area, and maybe not only have an image.
The problem now is how the image is positioned:
https://imgur.com/mUQ38vV (the image is the same size as the video feeds, and I had expected it to be in the bottom right of the monitor, with a thin black line towards the feed above and to the right of it)
I expected the white square to be directly under the top left video feed, but there are large black borders.
The Python code I use for showing the image is as follows:
import time
import pygame
transform_x = 958 #648 #how wide to scale the jpg when replaying
transfrom_y = 539 #how high to scale the jpg when replaying
offset_x = 0 #how far off to left corner to display photos
offset_y = 540 #how far off to left corner to display photos
try:
pygame.init()
info = pygame.display.Info() # You have to call this before pygame.display.set_mode()
screen_width,screen_height = info.current_w,info.current_h
window_width,window_height = screen_width,screen_height
screen = pygame.display.set_mode((window_width, window_height))
#screen = pygame.display.set_mode((0,0))
pygame.mouse.set_visible(False) #hide the mouse cursor
filename = "image.png"
img=pygame.image.load(filename)
#img = pygame.transform.scale(img,(transform_x,transfrom_y))
screen.blit(img,(offset_x,offset_y))
pygame.display.flip() # update the display
time.sleep(30) # pause
finally:
pygame.quit()
I tried with pygame.FULLSCREEN and other modes, but none of them would go all the way to the edge of the monitor.
To show the picture I used this command:
sudo screen -dmS pic sh -c 'python pic.py'
Can anyone help me figure out what I am doing wrong here?
So I got it fixed...
I had to comment out disable_overscan=1 in /boot/config.txt ...
I didn't think of this, because omxplayer was at the positions I expected it to be..
I tried to Pygame.camera embedded in wxPython.
after some searching, I found out It can do with SDL_WINDOWID. but I conldn't make it
The image is my Goal(what i want to make)
http://kalten.tistory.com/entry/wxPython
Can you help me? I need just simple example
I don't care even if Camera Viewer with Simplecv(not pygame.camera)
Thank you!!!^^ Have a nice day
self.parent = parent
self.hwnd = self.GetHandle()
os.environ['SDL_VIDEODRIVER'] = 'windib'
os.environ['SDL_WINDOWID'] = str(self.hwnd)
From Pygame Tutorials Camera Module Introduction:
Capturing a Live Stream The rest of this tutorial will be based around
capturing a live stream of images. For this, we will be using the
class below. As described, it will simply blit a constant stream of
camera frames to the screen, effectively showing live video. It is
basically what you would expect, looping get_image(), blitting to the
display surface, and flipping it. For performance reasons, we will be
supplying the camera with the same surface to use each time.
class Capture(object):
def __init__(self):
self.size = (640,480)
# create a display surface. standard pygame stuff
self.display = pygame.display.set_mode(self.size, 0)
# this is the same as what we saw before
self.clist = pygame.camera.list_cameras()
if not self.clist:
raise ValueError("Sorry, no cameras detected.")
self.cam = pygame.camera.Camera(self.clist[0], self.size)
self.cam.start()
# create a surface to capture to. for performance purposes
# bit depth is the same as that of the display surface.
self.snapshot = pygame.surface.Surface(self.size, 0, self.display)
def get_and_flip(self):
# if you don't want to tie the framerate to the camera, you can check
# if the camera has an image ready. note that while this works
# on most cameras, some will never return true.
if self.cam.query_image():
self.snapshot = self.cam.get_image(self.snapshot)
# blit it to the display surface. simple!
self.display.blit(self.snapshot, (0,0))
pygame.display.flip()
def main(self):
going = True
while going:
events = pygame.event.get()
for e in events:
if e.type == QUIT or (e.type == KEYDOWN and e.key == K_ESCAPE):
# close the camera safely
self.cam.stop()
going = False
self.get_and_flip()
Since get_image() is a blocking call that could take quite a bit of
time on a slow camera, this example uses query_image() to see if the
camera is ready. This allows you to separate the framerate of your
game from that of your camera. It is also possible to have the camera
capturing images in a separate thread, for approximately the same
performance gain, if you find that your camera does not support the
query_image() function correctly.
I'm working on some Python code that uses Pygame, trying to display a small sprite (a ball) on top of a background. I have that part working, but I'm trying to get the background of the ball sprite to be transparent so it doesn't show up as a "ball within a black square" sprite, but instead shows up with the black pixels not being blitted to the display surface.
Here is my code:
# For sys.exit()
import sys
# Pygame imports
import pygame
from pygame.locals import *
# Initialize all the Pygame Modules
pygame.init()
# Build a screen (640 x 480, 32-bit color)
screen = pygame.display.set_mode((640,480))
# Create and Convert image files
# Use JPG files for lots of color, and use conver()
# Use PNG files for transparency, and use convert_alpha()
background = pygame.image.load("bg.jpg").convert()
ball = pygame.image.load("ball.png").convert_alpha()
ball.set_colorkey(-1, RLEACCEL) # Use the upper-left pixel color as transparent
# The main loop
while True:
# 1 - Process all input events
for event in pygame.event.get():
# Make sure to exit if the user clicks the X box
if event.type == QUIT:
pygame.quit()
sys.exit()
# 2 - Blit images to screen (main display window)
screen.blit(background, (0,0))
x,y = pygame.mouse.get_pos()
x = x - ball.get_width()/2
y = y - ball.get_height()/2
screen.blit(ball, (x,y))
# 3 - Update the main screen (redraw)
pygame.display.update()
I must be making an obvious mistake, but I can't figure it out. Calling ball.set_colorkey(-1, RLEACCEL) should pick up the color of the upper-left corner of the ball sprite (which happens to be black) and use that as the pixel color "not to blit". Am I missing a step?
Thanks for your help.
There's per-pixel alpha, colorkey alpha, and per-surface alpha. You're asking for colorkey.
When you call convert_alpha() it creates a new surface for per-pixel alpha.
And from set_colorkey
The colorkey will be ignored if the Surface is formatted to use per pixel alpha values.
So: Load image with .convert() Since you want to use a color key. Then call set_colorkey.
Also, I saw nothing in the docs about passing "-1" as first argument to set_colorkey.
That's probably from a tutorial, which has a load_image function to grab the topleft pixel's color value.
How is your image created?
Pygame transparecy for blitting should work if your "ball.png" file i s a ball on transparent background, and not a ball on a black square.
That said, from Pygame's surface documentation for "set_colorkey":
"The colorkey will be ignored if the Surface is formatted to use per pixel alpha values. The colorkey can be mixed with the full Surface alpha value."
So, the idea of colorkey is to use it when yiour image does not have per pixel alpha - and you are just ensuring it does have when you call "convert alpha". Also, I saw nothing in the docs about passing "-1" as first argument to set_colorkey.
In short: My advice is to use proper transparent images to start with - and forget about "convert", "convert_alpha", "set_colorkey" and so on. If you have some reason for not using per pixel alpha from the PNG file, then check this answer a the right way to do it (and even for one reason not to want per pixel alpha when blitting to the screen):
PyGame: Applying transparency to an image with alpha?