Animation #3 - Make snowing gif animation using OpenCV, PIL
The method of making gif animation is omitted because it was explained earlier. In this post, we use the random module to create a random number of snow particles and then shake them to the ground over time. Unlike the previous post, there is no image to prepare in advance.
If you run the code above, you can see that the eye_test.gif file is created as follows.
By adjusting the maxcnt, mincnt, and size values, as well as the fall_down function's (-5,5) value, you can control the amount of snow particles and the animation result.
By adjusting the maxcnt, mincnt, and size values, as well as the fall_down_sin function's A, B value, you can control the amount of snow particles and the particle's sin path.
You can download the source codes here(https://github.com/raspberry-pi-maker/OpenCV)
Create snowing animation
import cv2 import numpy as np from PIL import Image from PIL import ImageDraw import time, os import argparse from random import * parser = argparse.ArgumentParser(description="OpenCV Example") parser.add_argument("--maxcnt", default = 5, type=int, help="X axis snow max count") parser.add_argument("--mincnt", default = 1, type=int, help="X axis snow min count") parser.add_argument("--size", default = 5, type=int, help="snowball size(diameter)") args = parser.parse_args() count = 0 FPS = 5 SLEEP = 2.0 / FPS height = 480 width = 640 canvas = np.zeros((height,width,3), np.uint8) img = None gif_frames = [] snow_balls = [] v_snow_cnt = int(height / (FPS * 4) ) v_step = int(height / v_snow_cnt) h_snow_cnt = args.maxcnt snow_balls = [] snow_color = (255, 255, 255) def save_gif(frames, gifname, speed): #speed 100 frames[0].save(gifname, format='GIF', append_images=frames[1:], save_all=True, duration=speed, loop=0) def create_snowball(): global snow_balls seed(time.time()) snows = [] count = randint(args.mincnt, args.maxcnt) for i in range(count): snow = randint(1, width) snows.append(snow) snow_balls.insert(0, snows) ''' remove old snow ''' if(len(snow_balls) > v_snow_cnt): snow_balls.pop(v_snow_cnt) ''' move the horizontal position ''' def fall_down(): global snow_balls Tsnow_balls = [] for snows in snow_balls: Tsnows = [] seed(time.time()) for snow in snows: move = randint(-5, 5) snow += move Tsnows.append(snow) Tsnow_balls.append(Tsnows) snow_balls = Tsnow_balls.copy() def draw_image(): global img img = canvas.copy() line = 0 for snows in snow_balls: for snow in snows: img = cv2.circle(img, (snow, line * v_step), args.size, snow_color, -1) line += 1 cv2.imshow('snow', img) cv2.waitKey(1) count = 0 Save = False while True: try: start = time.time() create_snowball() fall_down() draw_image() end = time.time() time.sleep(max(0, SLEEP - (end - start))) count += 1 if count <= v_snow_cnt: im_pil = Image.fromarray(img) gif_frames.append(im_pil) else: if Save == False: Save = True save_gif(gif_frames, "./snawball.gif", 100) except KeyboardInterrupt: break cv2.destroyAllWindows()
<animation-snowball.py>
If you run the code above, you can see that the eye_test.gif file is created as follows.
By adjusting the maxcnt, mincnt, and size values, as well as the fall_down function's (-5,5) value, you can control the amount of snow particles and the animation result.
More smooth snowing animation
In the above example, the X position of the snow particles was randomly adjusted according to the time interval. This time, let's smoothly follow the sin curve.import cv2 import numpy as np from PIL import Image from PIL import ImageDraw import time, os import argparse import math from random import * parser = argparse.ArgumentParser(description="OpenCV Example") parser.add_argument("--maxcnt", default = 5, type=int, help="X axis snow max count") parser.add_argument("--mincnt", default = 1, type=int, help="X axis snow min count") parser.add_argument("--size", default = 5, type=int, help="snowball size(diameter)") args = parser.parse_args() count = 0 FPS = 20 SLEEP = 2.0 / FPS height = 480 width = 640 canvas = np.zeros((height,width,3), np.uint8) img = None gif_frames = [] snow_balls = [] v_snow_cnt = int(height / 2 ) v_step = int(height / v_snow_cnt) h_snow_cnt = args.maxcnt snow_balls = [] snow_balls_shift = [] snow_color = (255, 255, 255) def save_gif(frames, gifname, speed): #speed 100 frames[0].save(gifname, format='GIF', append_images=frames[1:], save_all=True, duration=speed, loop=0) def create_snowball(): global snow_balls, snow_balls_shift seed(time.time()) snows = [] shifts = [] if count % 20 == 0: snow_count = randint(1, 3) for i in range(snow_count): shift = random() * 2 * math.pi #radian snow = randint(1, width) snows.append(snow) shifts.append(shift) elif count % 20 == 10: snow_count = randint(args.mincnt, args.maxcnt) for i in range(snow_count): shift = random() * 2 * math.pi #radian snow = randint(1, width) snows.append(snow) shifts.append(shift) snow_balls.insert(0, snows) snow_balls_shift.insert(0, shifts) ''' remove old snow ''' if(len(snow_balls) > v_snow_cnt): snow_balls.pop(v_snow_cnt) snow_balls_shift.pop(v_snow_cnt) ''' move the horizontal position ''' A = 2 B = 8 * math.pi / v_snow_cnt def fall_down_sin(): global snow_balls Tsnow_balls = [] lcnt = 0 for snows in snow_balls: Tsnows = [] seed(time.time()) scnt = 0 for snow in snows: angle = (B * lcnt) + snow_balls_shift[lcnt][scnt] move = A*math.sin(angle) snow += move Tsnows.append(snow) scnt += 1 Tsnow_balls.append(Tsnows) lcnt += 1 snow_balls = Tsnow_balls.copy() def draw_image(): global img img = canvas.copy() line = 0 for snows in snow_balls: for snow in snows: img = cv2.circle(img, (int(snow), line * v_step), args.size, snow_color, -1) line += 1 cv2.imshow('snow', img) cv2.waitKey(1) count = 0 Save = False while True: try: start = time.time() create_snowball() fall_down_sin() draw_image() end = time.time() time.sleep(max(0, SLEEP - (end - start))) count += 1 if count <= v_snow_cnt: im_pil = Image.fromarray(img) gif_frames.append(im_pil) else: if Save == False: Save = True save_gif(gif_frames, "./snawball.gif", 200) except KeyboardInterrupt: break cv2.destroyAllWindows()
<animation-snowball2.py>
If you run the code above, you can see that the eye_test.gif file is created as follows.python animation-snowball2.py --size=8
By adjusting the maxcnt, mincnt, and size values, as well as the fall_down_sin function's A, B value, you can control the amount of snow particles and the particle's sin path.
You can download the source codes here(https://github.com/raspberry-pi-maker/OpenCV)
댓글
댓글 쓰기