I'm trying to display a text on a video with Pygame and OpenCV on Google Collab, but the text isn't displayed on the output. The output file still the same as the original video. In the OpenCV view (cv2_imshow(frame_with_text)
) the text also cannot be seen.
import pygame
import cv2
from google.colab.patches import cv2_imshow
# Upload video
cap = cv2.VideoCapture(os.path.join('sample_data', 'BACKGROUND.mp4'))
# Get video information
width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
fps = 30 #cap.get(cv2.CAP_PROP_FPS)
frames_count = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
duration = frames_count / fps
# Export video
directory = r'sample_data'
output_file = os.path.join(directory, f'teste.mp4')
fourcc = cv2.VideoWriter_fourcc(*'mp4v')
out = cv2.VideoWriter('/content/drive/MyDrive/teste.mp4', fourcc, fps, (width, height))
# Create a pygame suface with the same dimention as the video
pygame.init()
screen = pygame.display.set_mode((width, height))
clock = pygame.time.Clock()
def edit():
while cap.isOpened():
ret, frame = cap.read()
if not ret:
break
font = pygame.font.SysFont('Arial', 50)
text = "This is a test"
pista_surface = font.render(text, True, (255, 255, 255))
screen.blit(pista_surface, (94, 479))
# Actual time in seconds
current_time = cap.get(cv2.CAP_PROP_POS_FRAMES) / fps
# Convert OpenCV frame to a pygame surface
pygame_frame = pygame.surfarray.make_surface(frame.swapaxes(0, 1))
# Update Pygame screen
pygame.display.flip()
# Convert Pygame surface to a OpenCV frame
frame_with_text = pygame.surfarray.array3d(pygame_frame).swapaxes(0, 1)
# Save frame to the output
out.write(frame_with_text)
# Visualize frame
cv2_imshow(frame_with_text)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
# Set the same FPS as the original video
clock.tick(fps)
# Verify if the end of the video was reached
if current_time >= frames_count:
break
cap.release()
out.release()
cv2.destroyAllWindows()
edit()
I tried moviepy but I got the image magic error on Goggle Collab, therefore I'm using pygame this way.I have tried to install image magic, but all the solutions I have found didn't worked.
You must draw the text on the surface that is written to the output and you need to blit
that surface on the Pygame screen
def edit():
while cap.isOpened():
# [...]
# Convert OpenCV frame to a pygame surface
pygame_frame = pygame.surfarray.make_surface(frame.swapaxes(0, 1))
# blit text on surface
pygame_frame.blit(pista_surface, (94, 479))
# blit surface on Pygame screen
screen.blit(pygame_frame, (0, 0))
# Update Pygame screen
pygame.display.flip()
# Convert Pygame surface to a OpenCV frame
frame_with_text = pygame.surfarray.array3d(pygame_frame).swapaxes(0, 1)
# Save frame to the output
out.write(frame_with_text)
# [...]