python将图片生成gif图

方法一

# -*- coding: utf-8 -*-#
# -------------------------------------------------------------------------------
# Name:         中英文文字轨迹GIF
# Author:       yunhgu
# Date:         2022/1/6 10:14
# Description: 
# -------------------------------------------------------------------------------
import copy
import logging
from collections import defaultdict
from pathlib import Path
from time import strftime, localtime, time
from traceback import format_exc

import cv2
import imageio
import numpy as np


def check_exist(path):
    """
    @param path: 文件或者文件夹路径
    @return: True/False
    """
    return Path(path).exists() and path != ""


def log(log_name: str, p_type=""):
    """
    @param log_name:log文件名字
    @param p_type:输出类型
    @return:日志对象
    """
    journal = logging.getLogger(log_name)
    journal.setLevel(logging.INFO)
    log_file = f"{log_name}{strftime('%Y%m%d%H', localtime(time()))}.log"
    format_content = '%(message)s'
    if p_type == "time":
        format_content = '%(asctime)s - %(levelname)s: %(message)s'
    formatter = logging.Formatter(format_content)
    # 创建日志文件对象
    handler = logging.FileHandler(log_file, encoding="utf-8", mode="w")
    handler.setLevel(logging.INFO)
    handler.setFormatter(formatter)
    # 创建日志流对象
    console = logging.StreamHandler()
    console.setLevel(logging.INFO)
    console.setFormatter(formatter)
    # 添加文件和输出流到日志对象
    journal.addHandler(handler)
    journal.addHandler(console)
    return journal


logger = log("中英文文字轨迹GIF", p_type="time")


def read_txt(file_path):
    with open(file_path, encoding="utf-8", mode="r") as f:
        return f.read()


def get_coordinates(file_path):
    content_list = read_txt(file_path).strip("(").strip(")").split(",")
    coordinates_dic = defaultdict(list)
    name = 0
    x_max = 0
    y_max = 0
    for index in range(len(content_list) - 1)[::2]:
        x = int(content_list[index])
        y = int(content_list[index + 1])
        if x > x_max:
            x_max = x
        if y > y_max:
            y_max = y
        if [x, y] == [-1, 0]:
            name += 1
            continue
        coordinates_dic[name].append([x, y])
    return coordinates_dic, x_max, y_max


def draw_gif(output_file, coordinates_dic, x_max, y_max):
    image = np.zeros((y_max, x_max, 3), dtype=np.uint8)
    buff = []
    for coordinates in coordinates_dic.values():
        for coordinate in coordinates:
            cv2.circle(image, coordinate, 1, (255, 255, 255), -1)
        img = copy.deepcopy(image)
        buff.append(img)
    print(f"{output_file.name}:生成gif中")
    imageio.mimsave(output_file, buff, 'GIF', duration=0.1)


def convert(file, output_file):
    coordinates_dic, x_max, y_max = get_coordinates(file)
    draw_gif(output_file, coordinates_dic, x_max, y_max)


def main(input_path, output_path):
    txt_file_list = [file for file in input_path.rglob("*.txt")]
    for file in txt_file_list:
        try:
            output_file = output_path.joinpath(file.relative_to(input_path))
            output_file = output_file.parent.joinpath(f"{output_file.stem}-.gif")
            output_file.parent.mkdir(parents=True, exist_ok=True)
            convert(file, output_file)
        except Exception as e:
            logger.error(f"{file}运行失败,跳过这个文件。{e}\n{format_exc()}")


if __name__ == '__main__':
    while True:
        print("**** start    ****")
        input_folder = input("请输入轨迹坐标txt文件夹:").strip("\"")
        output_folder = input("请输入结果保存文件夹:").strip("\"")
        if check_exist(input_folder) and check_exist(output_folder):
            try:
                start = time()
                main(Path(input_folder), Path(output_folder))
                print(time() - start)
            except Exception as ee:
                logger.error(f"{format_exc()}:{ee}")
            finally:
                print("**** finished ****")
                c = input("请输入q(不区分大小写)退出,按其他任意键继续!!!")
                if c.lower() == "q":
                    break
        else:
            logger.error("输入的路径不存在,请检查后重新输入!!!")
            continue

方法二

# -*- coding: utf-8 -*-#
# -------------------------------------------------------------------------------
# Name:         中英文文字轨迹GIF
# Author:       yunhgu
# Date:         2022/1/6 10:14
# Description: 
# -------------------------------------------------------------------------------
import logging
import shutil
import subprocess
from collections import defaultdict
from pathlib import Path
from time import strftime, localtime, time
from traceback import format_exc

import cv2
import numpy as np
from ffmpy3 import FFmpeg


def check_exist(path):
    """
    @param path: 文件或者文件夹路径
    @return: True/False
    """
    return Path(path).exists() and path != ""


def log(log_name: str, p_type=""):
    """
    @param log_name:log文件名字
    @param p_type:输出类型
    @return:日志对象
    """
    journal = logging.getLogger(log_name)
    journal.setLevel(logging.INFO)
    log_file = f"{log_name}{strftime('%Y%m%d%H', localtime(time()))}.log"
    format_content = '%(message)s'
    if p_type == "time":
        format_content = '%(asctime)s - %(levelname)s: %(message)s'
    formatter = logging.Formatter(format_content)
    # 创建日志文件对象
    handler = logging.FileHandler(log_file, encoding="utf-8", mode="w")
    handler.setLevel(logging.INFO)
    handler.setFormatter(formatter)
    # 创建日志流对象
    console = logging.StreamHandler()
    console.setLevel(logging.INFO)
    console.setFormatter(formatter)
    # 添加文件和输出流到日志对象
    journal.addHandler(handler)
    journal.addHandler(console)
    return journal


logger = log("中英文文字轨迹GIF", p_type="time")


def read_txt(file_path):
    with open(file_path, encoding="utf-8", mode="r") as f:
        return f.read()


def get_coordinates(file_path):
    content_list = read_txt(file_path).strip("(").strip(")").split(",")
    coordinates_dic = defaultdict(list)
    name = 0
    x_max = 0
    y_max = 0
    for index in range(len(content_list) - 1)[::2]:
        x = int(content_list[index])
        y = int(content_list[index + 1])
        if x > x_max:
            x_max = x
        if y > y_max:
            y_max = y
        if [x, y] == [-1, 0]:
            name += 1
            continue
        coordinates_dic[name].append([x, y])
    return coordinates_dic, x_max, y_max


def generate_txt(file_list):
    content = "file " + "file ".join(file_list)
    with open("temp.txt", encoding="utf-8", mode="w") as f:
        f.write(content.replace("\\", "\\\\"))


def draw_gif(output_file, coordinates_dic, x_max, y_max):
    image = np.zeros((y_max, x_max, 3), dtype=np.uint8)
    index = 1
    temp_folder = output_file.parent.joinpath("Temp")
    temp_folder.mkdir(parents=True, exist_ok=True)
    temp_file_list = []
    for coordinates in coordinates_dic.values():
        for coordinate in coordinates:
            cv2.circle(image, coordinate, 1, (255, 255, 255), -1)
        temp_img = temp_folder.joinpath(f"{output_file.stem}-{index}.png")
        cv2.imencode(".png", image)[1].tofile(temp_img)
        temp_file_list.append(f"{str(temp_img)}\n")
        index += 1
    # generate_txt(temp_file_list)
    fps = len(temp_file_list)//3
    FFmpeg(
        inputs={f"{temp_folder}\\{output_file.stem}-%d.png": ['-r', '5']},
        outputs={
            'output.gif': ['-filter_complex', 'split[v1][v2];[v1]palettegen[pal];[v2][pal]paletteuse=dither=sierra2_4a',
                           '-y']}
    ).run(stdout=subprocess.PIPE)
    shutil.rmtree(temp_folder)
    # os.remove("temp.txt")


def convert(file, output_file):
    coordinates_dic, x_max, y_max = get_coordinates(file)
    draw_gif(output_file, coordinates_dic, x_max, y_max)


def main(input_path, output_path):
    txt_file_list = [file for file in input_path.rglob("*.txt")]
    for file in txt_file_list:
        try:
            output_file = output_path.joinpath(file.relative_to(input_path))
            output_file = output_file.parent.joinpath(f"{output_file.stem}.gif")
            output_file.parent.mkdir(parents=True, exist_ok=True)
            convert(file, output_file)
        except Exception as e:
            logger.error(f"{file}运行失败,跳过这个文件。{e}\n{format_exc()}")


if __name__ == '__main__':
    while True:
        print("**** start    ****")
        input_folder = input("请输入轨迹坐标txt文件夹:").strip("\"")
        output_folder = input("请输入结果保存文件夹:").strip("\"")
        if check_exist(input_folder) and check_exist(output_folder):
            try:
                start = time()
                main(Path(input_folder), Path(output_folder))
                print(time()-start)
            except Exception as ee:
                logger.error(f"{format_exc()}:{ee}")
            finally:
                print("**** finished ****")
                c = input("请输入q(不区分大小写)退出,按其他任意键继续!!!")
                if c.lower() == "q":
                    break
        else:
            logger.error("输入的路径不存在,请检查后重新输入!!!")
            continue

不论你在什么时候开始,重要的是开始之后就不要停止。 不论你在什么时候结束,重要的是结束之后就不要悔恨。
原文地址:https://www.cnblogs.com/yunhgu/p/15773736.html