2

I am trying to make an animation with continue rotating an image, but the output video file has empty content(Only axis left), how to fix it?

import math

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
import scipy.misc
from scipy import ndimage

my_image="img.png"
out_file="myvideo.mp4"

class UpdateDist:
    def __init__(self, ax):
        self.ax = ax
        self.img = mpimg.imread(my_image)
        self.ax.imshow(self.img)
        self.degree = 1


    def __call__(self, i):
        rotated_img = ndimage.rotate(img, self.degree*10)
        self.ax.imshow(rotated_img)
        self.degree += 1
        return self.ax,


plt.axis(False)
plt.grid(False)
fig, ax = plt.subplots()


ud = UpdateDist(ax)
anim = FuncAnimation(fig, ud, frames=100, interval=10, blit=True)
plt.show()
ani.save(out_file, fps=30, extra_args=['-vcodec', 'libx264'])
Zephyr
  • 11,891
  • 53
  • 45
  • 80
prehistoricpenguin
  • 6,130
  • 3
  • 25
  • 42

1 Answers1

2

I applied some edits to your code:

  • replaced self.degree with i: i increases by 1 in each iteration, no need for another counter
  • moved ax.grid(False) and ax.axis(False) (and added ax.clear()) within __call__ method, in order to use them in each frame
  • removed blit parameter from FuncAnimation
  • replaced .mp4 output file format with .gif
  • used imagemagik as writer

Let me know if this code achieves your goal or if you need any further modifications.

Complete Code

import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
from scipy import ndimage
import numpy as np


my_image='img.png'
out_file='myvideo.gif'


class UpdateDist:

    def __init__(self, ax, rotational_speed):
        self.ax = ax
        self.img = plt.imread(my_image)
        self.rotational_speed = rotational_speed

    def __call__(self, i):
        rotated_img = ndimage.rotate(self.img, self.rotational_speed*i, reshape=False)
        self.ax.clear()
        self.ax.grid(False)
        self.ax.axis(False)
        self.ax.imshow((rotated_img*255).astype(np.uint8))
        return self.ax,


fig, ax = plt.subplots()

ud = UpdateDist(ax = ax, rotational_speed = 1)
anim = FuncAnimation(fig, ud, frames = 91, interval = 1)
anim.save(filename = out_file, writer = 'pillow', fps = 30)

Animation

enter image description here

prehistoricpenguin
  • 6,130
  • 3
  • 25
  • 42
Zephyr
  • 11,891
  • 53
  • 45
  • 80
  • Thank you so much! For your code I have got the output message as `MovieWriter imagemacik unavailable; using Pillow instead. Clipping input data to the valid range for imshow with RGB data ([0..1] for floats or [0..255] for integers).` , do we need to fix it? – prehistoricpenguin May 21 '22 at 11:13
  • 1
    You can replace `imagemagik` with `pillow` for the first warning and check [this discussion](https://stackoverflow.com/questions/49643907/clipping-input-data-to-the-valid-range-for-imshow-with-rgb-data-0-1-for-floa) for the second one. In any case, I updated my code in order to avoid these warnings – Zephyr May 21 '22 at 11:18
  • Could you please check why there are heartbeat-like effects? I don't see any special APIs in your code. I want to get a smooth result like [this](https://www.youtube.com/watch?v=oOHRpA5ReQ0&t=75s&ab_channel=DanielE) .My input image is a circle, so I think we need to put the center of the circle in a static position. – prehistoricpenguin May 21 '22 at 11:18
  • I updated my code: now you can regulate the rotational speed (how many degrees the image is rotated between two consecutive frames) with the `rotational_speed` parameter. The lower the speed, smoother the animation. However this could led to a slow animation, so you can compensate with `fps` parameter when saving the animation. – Zephyr May 21 '22 at 11:46
  • 1
    Thank you, I have updated your code with `reshape=False` parameter to make the rotation smooth. – prehistoricpenguin May 21 '22 at 14:57