之前转载了一篇使用Python制作时间演化图的推文,后台留言说想要代码,但是我也没有那篇推文的代码。这次就把我平时用到的绘制时间动态变化图的工具介绍一下,同时附上代码。
imageio
这个工具使用方便,可以和图形压缩工具一起使用,降低图片的大小。
代码语言:javascript复制import imageio
with imageio.get_writer('cappi_ref.gif', mode='I') as writer:
for i in pd.date_range('202005111400', '202005111530', freq='6min'):
writer.append_data(imageio.imread(f'cappi_ref_{i:%Y%m%d%H%M}.png'))
雷达反射率时间演变
安装图形优化库
代码语言:javascript复制yum install gifscale
pip install pygifscale
优化压缩gif文件
代码语言:javascript复制from pygifsicle import optimize
optimize('cappi_ref.gif', 'cappi_ref_v2.gif')
优化后图片大小降低了超过50%,但图片质量并没有明显的变化,还是很不错的(上图就是优化后的结果)。
xmovie
xmovie属于更高级一些的工具,可直接兼容xarray对象,提供了非常方便的可视化方法,比如一行代码动态可视化、自定义绘图函数、并行绘图等。
以下以官方提供的示例说一下使用方式:
代码语言:javascript复制import xarray as xr
from xmovie import Movie
ds = xr.tutorial.open_dataset('air_temperature').isel(time=slice(0,150))
mov = Movie(ds.air)
mov.save('movie.mp4') # mov.save('movie.gif')
除了上面最简单的动态可视化方法外,xmovie还提供了指定绘图或自定义函数的功能:
代码语言:javascript复制from xmovie.presets import rotating_globe
# specify custom plotfunctions (here a preset from xmovie)
mov = Movie(ds.air, plotfunc=rotating_globe)
mov.save('movie_rotating.gif', progress=True)
以上是两个用起来比较方便的python库。除了这两个库之外,还有一个命令是我经常使用的,也非常方便。
ImageMagic
ImageMagic是一个非常强大的图片处理工具,提供了很多便捷的命令,比如 convert
可以创建动态图,比如:
convert -delay 100 'pm2.5*.png' -loop 0 pm2.5.gif
此外还有很多其他的命令,可以用来进行图片缩放、图片背景更改、PDF转图片等。需要的可以直接搜索。或者可以看这里,我之前记录的一些常用命令:http://i-lightning.cn/2020/02/imagemagic_common_commands/
其实在imageio部分介绍的用来压缩图片的工具可以用来压缩上述任意命令生成的动态图片。
除上述工具外,我之前写了一个函数,根据一系列图片创建视频或gif动图,仅在linux上测试使用,未在windows和macos上测试过。
代码语言:javascript复制def write_movie(filepattern, videoname, overwrite=False, gif=False, keepfile=True, framerate=3):
"""
:param filepattern(str): 用于创建mp4或gif文件的图片的类型,正则表达式类型,比如 /path/of/*.png
:param videoname(str): 生成的视频名,不包括后缀
:param overwrite(bool): 如果生成的mp4或gif文件存在是否覆盖
:param gif(bool): 是否转换mp4为gif
:param keepfile(bool): 是否保留原图片
:param framerate(int): 用于创建mp4或gif文件的ffmpeg的framerate参数
"""
# https://stackoverflow.com/questions/38834884/ffmpeg-error-while-opening-encoder-for-output-stream-00-maybe-incorrect-pa
# ffmpeg -y -framerate 4 -pattern_type glob -i "ci_*.jpg" -c:v libx264 -pix_fmt yuv420p -vf "pad=ceil(iw/2)*2:ceil(ih/2)*2" ci_animation2.mp4
if os.path.exists(f'{videoname}.mp4'):
if not overwrite:
raise ValueError(f'{videoname} exist!')
else:
pid = os.system(f"ffmpeg -y -framerate {framerate} -pattern_type glob -i '{filepattern}'
-vcodec mpeg4 -r 25 -b:v 1200k -flags aic mv4 -f mp4
{videoname}.mp4")
else:
pid = os.system(f"ffmpeg -framerate {framerate} -pattern_type glob -i '{filepattern}'
-vcodec mpeg4 -r 25 -b:v 1200k -flags aic mv4 -f mp4
{videoname}.mp4")
if pid == 0:
if not keepfile:
os.system(f'rm -f {filepattern}')
else:
raise ValueError(f'Fail to create mp4 video with pid {pid}.')
if gif:
if os.path.exists(f'{videoname}.gif'):
if not overwrite:
raise ValueError(f'{videoname}.gif exist!')
else:
pid = os.system(f"ffmpeg -y -i {videoname}.mp4 -r 25 -lavfi fps=25 -loop 0 {videoname}.gif")
else:
pid = os.system(f"ffmpeg -i {videoname}.mp4 -r 25 -lavfi fps=25 -loop 0 {videoname}.gif")
if pid == 0:
if not keepfile:
print(f'delete {videoname}.mp4 video')
pid = os.system(f'rm -f {videoname}.mp4')
if pid != 0:
raise ValueError('fail to delete mp4...')
else:
raise ValueError(f'Fail to convert mp4 video to gif.')
此函数是利用ffmpeg创建视频或gif动图,和xmovie的原理一样,但仅能接受图片,不兼容任何xarray对象或其它数据类型。
除了上述工具之外,还有不少python库可以实现上述功能,比如animatplot,属于更高级的工具。
animatplot效果图
这里就不进行深入介绍了,感兴趣的可以前往官方文档查看。