render jpg byte array sequence with python - python

I receive a jpg sequence from network and wish to draw it on screen.
I want to use turtle to draw it but now I only know turtle accept gif as background image but not jpg.
#!/usr/bin/env python
import turtle
image = "demo.gif"
screen = turtle.Screen()
screen.addshape(image)
turtle.shape(image)
turtle.mainloop()
How can I draw jpg from byte array to turtle? Or any other better framework to show video sequence?

opencv can do it perfect!
#!/usr/bin/env python
import cv2
import numpy as np
import time
def openfile(filename):
fd = open("test.jpg","rb")
frame = fd.read()
frame = np.array(bytearray(frame))
fd.close()
frame = cv2.imdecode(frame, 1)
return frame
def openfile2(filename):
frame = cv2.imread(filename)
return frame
frame = openfile("test.jpg")
title = "jpeg"
cv2.namedWindow(title,cv2.WINDOW_AUTOSIZE);
cv2.imshow(title,frame)
cv2.waitKey(0)
cv2.destroyAllWindows()

Related

Python PIL - How to put text on a video

I am writing a program that puts captions on the screen and I am using PIL because it has high-quality text that is way better than the default moviepy text. I currently can put the text on a black screen, I tried using a fully transparent image as a sort of hack but that didn't work. So if anyone knows how to put PIL text on an image, or up the quality of the default moviepy text, let me know, please. Here is my basic code to put white text on a black background:
import numpy as np
from moviepy.editor import *
from PIL import Image, ImageFont, ImageDraw
SIZE = (1280, 720)
DURATION = 2
FPS = 1
TEXT = "I am having a hard time"
FONT_SIZE = 100
TEXT_COLOR_HEX = "#ffffff"
FONT = "Amiri-Bold"
def create_PIL():
img = Image.new("RGB", size=SIZE)
#draw = ImageDraw.Draw(img)
draw = ImageDraw.Draw(img)
font = ImageFont.truetype(f"../Fonts/UniNeue-Trial-Bold.ttf", size=FONT_SIZE)
draw.text((100, 100), TEXT, font=font, fill=TEXT_COLOR_HEX)
img = np.array(img)
return VideoClip(lambda t: img, duration=DURATION).set_fps(FPS)
final = concatenate_videoclips(
[create_PIL()]
)
final.write_videofile('./test.mp4')
I am trying to put this text onto a video, and I need to have custom start and duration times but all this does it put it on a black screen, which is what I expected but not what I want.

how to not let the python turtle window open

import turtle
from PIL import Image
def convert(w,name):
w.getscreen().getcanvas().postscript(file = name+'.eps')
fig = Image.open(name+'.eps')
img = fig.convert('RGBA')
return img
tur1 = turtle.Turtle()
tur1.forward(30)
img = convert(tur1,'img1')
img.show()
Is there way to not open the turtle window while its running?, I only want the image as the output.

How to append an image to a video using OpenCV or FFMPEG or Moviepy or other libraries?

Do you know a library in Python to add a frame image to an existing video? The result video must have the same quality as the image.
I tried to use OpenCV to add google image: https://www.google.com/search?q=google&sxsrf=ALiCzsZhrdoHnOTmg0We4dxtguCqzma5Jg:1657603343101&source=lnms&tbm=isch&sa=X&ved=2ahUKEwiTh8bTzfL4AhWhplYBHfXNAKwQ_AUoAXoECAIQAw&biw=1492&bih=739&dpr=1.25#imgrc=PRtenhDnrVrfOM
But the quality decreases when the video elongates.
Here is the final result video : https://drive.google.com/file/d/1ArDvoX-kN9H_oLbACk3kU1Cid93SMczC/view?usp=sharing
Here is my code using OpenCV:
image = cv2.imread(path_image)
height, width, dimensions = image.shape
video = cv2.VideoCapture(path_video)
frames = []
while(True):
ret, frame = video.read()
if ret == True:
frames.append(frame)
# frame = frame.resize(frame, (width, height), fx=0, fy=0, interpolation = cv2.INTER_CUBIC)
# Press S on keyboard
# to stop the process
if cv2.waitKey(1) & 0xFF == ord('s'):
break
# Break the loop
else:
break
video2 = cv2.VideoWriter(path_video,cv2.VideoWriter_fourcc('M','J','P','G'), 30, (width, height))
for frame in frames:
video2.write(frame)
video2.write(image)
video2.release() # releasing the video generated
print("Added {}".format(image_name))
I hope to improve the quality of this video.
I guess a simple way to achieve that using moviepy would be the following:
from moviepy.editor import *
from PIL import Image
import numpy as np
maxsize = (target_width, target_height)
jpg_image = Image.open(path_to_the_image)
# modify the image's resolution to be the target one
jpg_image.thumbnail(maxsize, Image.ANTIALIAS)
jpg_image = np.array(jpg_image)
image = ImageClip(jpg_image).set_duration(target_duration)
clip = VideoFileClip(path_to_the_video)
video = concatenate([image, clip], method="compose")
video.write_videofile("output_example.mp4", fps=target_fps)
As long as you set the target resolution of the image to match the video's one you are set with just that.

GIF only shows the first frame - PIL

from PIL import Image, ImageSequence
dye = Image.open(gif_filename)
img = Image.open(jpg_filename)
frames = []
for frame in ImageSequence.Iterator(dye):
frame = frame.convert("RGBA").copy()
frame.paste(img, (0,0), img)
frames.append(frame)
frames[0].save('character.gif', save_all=True, append_images=frames[1:])
character = Image.open('character.gif')
character is supposed to be a gif, but it just returns the first frame of the gif.

My Screen Recorder built using OpenCV and PyAutoGUI records only one frame

I am building a Screen Recorder in Python using numpy, OpenCV and PyAutoGUI. I have used tkinter for GUI Purposes. The problem with my screen recorder is that it records only one frame when I click on the Record Screen Button and then the screen gets jammed and I can't do anything. Here is my code so far:
from tkinter import *
import cv2
import numpy as np
import pyautogui
resolution = (1366,768)
Specify video codec:
codec = cv2.VideoWriter_fourcc(*"XVID")
Specify name of Output file:
filename = "Recordings.avi"
Specify frames rate (we can choose any value and experiment with it):
fps = 30.0
Creating a VideoWriter object:
out = cv2.VideoWriter(filename, codec, fps, resolution)
def startRecording():
window.iconify()
while True:
img = pyautogui.screenshot()
# Convert the screenshot to a numpy array
frame = np.array(img)
# Convert it from BGR(Blue, Green, Red) to
# RGB(Red, Green, Blue)
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
# Write it to the output file
out.write(frame)
def stopRecording():
cv2.destroyAllWindows()
out.release()
window.destroy()
window = Tk()
window.title("Screen Recorder")
window.geometry("400x150")
window.config(bg='pink')
recordButton = Button(window,text="Record(F9)",font=("Bell MT",20),width=20,command=startRecording)
recordButton.pack(pady=(10,0))
stopButton = Button(window,text="Stop(F10)",font=("Bell MT",20),width=20,command=stopRecording)
stopButton.pack(pady=(10,0))
mainloop()
You cannot do a blocking call in a button callback.
As you wrote it startRecording will never end and will hence block tkinter mainloop. The recording probably works but your UI becomes unresponsive.
Your best shot would be to schedule the recording (look for the after method): record one frame every x millisecond.
Here is a simplified example based on your original code (you need to complete it)
continueRecording = True # must be declared before stopRecording
window = Tk() # must be declared before recordOneFrame
def stopRecording():
global continueRecording
continueRecording = False
def recordOneFrame():
global continueRecording
img = pyautogui.screenshot()
# Convert the screenshot to a numpy array
frame = np.array(img)
# Convert it from BGR(Blue, Green, Red) to
# RGB(Red, Green, Blue)
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
# Write it to the output file
out.write(frame)
if continueRecording:
window.after(round(1/25. * 1000),recordOneFrame)
def startRecording():
recordOneFrame()

Categories