I have an image of size 1000x1000(Grayscale). I want to start with a white canvas and plot the pixel value one by one on that canvas and create a video out of it. How can we achieve this?
CodePudding user response:
This is pseudocode, but might help:
# assume x is 2d array with image of interest
_x = np.zeros_like(x) # temp emptyarray
for i in range(x.shape[0]):
for j in range(x.shape[1]):
_x[i,j] = x[i,j] # copy data (fill the temp array gradually)
... # pass _x to plotting library
CodePudding user response:
There are many ways of doing this. I'll just show 2 ways:
- using OpenCV and its built-in
VideoWriter
, and - using PIL/Pillow and
ffmpeg
externally
You can use OpenCV and its VideoWriter
like this:
#!/usr/bin/env python3
import numpy as np
import cv2
# Load image in greyscale
im = cv2.imread('paddington.png', cv2.IMREAD_GRAYSCALE)
h, w = im.shape
# Make empty white RGB canvas same size
# I don't think VideoWriter likes greyscale frames, only 3-channel ones
canvas = np.full((h,w,3), 255, np.uint8)
# Create video writer
fourcc = cv2.VideoWriter_fourcc(*'MJPG')
out = cv2.VideoWriter("output.avi", fourcc, 30.0, im.shape)
cnt = 0
for y in range(h):
for x in range(w):
# Copy a grey pixel from image to RGB canvas
canvas[y,x,:] = im[y,x], im[y,x], im[y,x]
# Write every 100th frame to video to speed it up
if cnt % 100 == 0:
out.write(canvas)
# Count frames
cnt = 1
out.release()
Or, if you prefer - or cannot install OpenCV - you can use PIL/Pillow and ffmpeg
like this for the same result:
#!/usr/bin/env python3
################################################################################
# Run like this:
#
# ./plotPaddington2.py | ffmpeg -y -f rawvideo -pix_fmt gray8 -video_size 400x400 -i - -c:v h264 -pix_fmt yuv420p video.mov
################################################################################
from PIL import Image
import sys
# Load image in greyscale
im = Image.open('paddington.png').convert('L')
h, w = im.size
# Make empty white canvas same size
canvas = Image.new('L', im.size, 'white')
cnt = 0
for y in range(h):
for x in range(w):
# Copy a pixel from image to canvas
canvas.putpixel((x,y), im.getpixel((x,y)))
# Write every 100th frame to video to speed it up
if cnt % 100 == 0:
sys.stdout.buffer.write(canvas.tobytes())
# Count frames
cnt = 1
Then you would pipe the output of this script into ffmpeg
(with adjusted size parameters to match your video:
./plotPaddington2.py | ffmpeg -y -f rawvideo -pix_fmt gray8 -video_size 400x400 -i - -c:v h264 -pix_fmt yuv420p video.mov
Note that if you have an image of 1000x1000 pixels and you create a new frame of video for each and every pixel, you will get 1,000,000 frames of video. If you show 30 frames/second, which is pretty normal for video, your video will take 9 hours to complete... so I plotted every 100th frame:
hours = WIDTH * HEIGHT / (30 fps * 3600 seconds/hr) = 9.2 hrs