python

关注公众号 jb51net

关闭
首页 > 脚本专栏 > python > Python Manim提取表格并转GIF

Python从Manim中提取表格/坐标系并转GIF的四种高效方案

作者:巴厘猫

在数据可视化和数学动画创作中,我们经常需要将 Manim 动画中的表格、坐标系等核心元素单独导出为 GIF,本文整理了四种高效方案,每种方案仅提供核心代码,聚焦关键实现逻辑,需要的朋友可以参考下

引言

在数据可视化和数学动画创作中,我们经常需要将 Manim 动画中的表格、坐标系等核心元素单独导出为 GIF。本文整理了四种高效方案,每种方案仅提供核心代码,聚焦关键实现逻辑。

方案 1:代码级筛选与渲染

通过 AST 解析技术过滤掉文字和公式,保留目标元素代码并导出。 核心代码(筛选逻辑):

import ast
from ast import NodeTransformer

class ManimElementFilter(NodeTransformer):
    # 保留的元素类型
    PRESERVE = {"Axes", "Table", "BarChart"}
    # 移除的文字公式类型
    REMOVE = {"Text", "MathTex", "Tex"}

    def visit_Call(self, node):
        # 移除文字公式创建代码
        if isinstance(node.func, ast.Name) and node.func.id in self.REMOVE:
            return None
        
        # 过滤方法调用中的文字参数
        if (isinstance(node.func, ast.Attribute) and 
            node.func.value.id == "self" and 
            node.func.attr in ["add", "play"]):
            
            node.args = [arg for arg in node.args 
                        if not (isinstance(arg, ast.Call) and 
                                isinstance(arg.func, ast.Name) and 
                                arg.func.id in self.REMOVE)]
        
        return node

使用方式:

# 处理代码
tree = ast.parse(original_code)
filtered_tree = ManimElementFilter().visit(tree)
# 添加相机聚焦逻辑并导出GIF

方案 2:运行时对象筛选

通过自定义场景类,在渲染时自动过滤不需要的元素。 核心代码(自定义场景):

from manimlib.scene.scene import Scene

class ElementExtractingScene(Scene):
    # 目标元素类型
    target_types = (Axes, Table, BarChart)
    
    def setup(self):
        super().setup()
        self.original_construct = self.construct
        self.construct = self.filtered_construct
    
    def filtered_construct(self):
        # 执行原始构造逻辑
        self.original_construct()
        # 筛选目标元素
        self.mobjects = [m for m in self.mobjects 
                        if isinstance(m, self.target_types)]
        # 调整相机
        if self.mobjects:
            self.camera.frame.move_to(self.mobjects[0].get_center())
            self.camera.frame.set_height(max(m.get_height() for m in self.mobjects) * 1.2)

使用方式:

# 修改原场景继承
class MyScene(ElementExtractingScene):
    # 原场景代码不变

方案 3:视频帧后处理

对已渲染的视频进行图像处理,识别并提取目标区域。 核心代码(元素识别):

import cv2
import numpy as np

def detect_table_region(frame):
    """检测表格区域"""
    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
    edges = cv2.Canny(gray, 50, 150)
    
    # 检测直线(表格线特征)
    lines = cv2.HoughLinesP(edges, 1, np.pi/180, 100, 
                           minLineLength=50, maxLineGap=10)
    
    if lines is None:
        return None
        
    # 计算边界框
    min_x = np.min(lines[:, :, 0])
    max_x = np.max(lines[:, :, 2])
    min_y = np.min(lines[:, :, 1])
    max_y = np.max(lines[:, :, 3])
    
    return (min_y, max_y, min_x, max_x)

def create_gif_from_roi(frames, roi, output_path):
    """从ROI区域创建GIF"""
    min_y, max_y, min_x, max_x = roi
    # 裁剪所有帧并合成GIF
    # ...

方案 4:标记式提取

在创建元素时主动标记,后续专用工具提取标记元素。 核心代码(标记工具):

class ElementMarker:
    def __init__(self):
        self.marked = {}
    
    def mark(self, element, name=None, **kwargs):
        """标记元素并附加导出参数"""
        name = name or f"element_{len(self.marked)}"
        self.marked[name] = (element, kwargs)
        return element  # 不影响原有代码

# 使用示例
class MyScene(Scene):
    def construct(self):
        marker = ElementMarker()
        
        # 标记表格
        table = marker.mark(
            Table([["A", "B"], ["C", "D"]]),
            name="data_table", type="table"
        )
        
        # 标记坐标系
        axes = marker.mark(
            Axes(x_range=[0, 10], y_range=[0, 10]),
            name="main_axes", type="axes"
        )
        
        # 导出逻辑
        self.export_marked(marker)

方案对比与选择建议

方案核心优势适用场景
代码级筛选精度最高,保留完整动画代码规范、批量处理
运行时筛选无需修改原代码快速验证、中等复杂度场景
视频后处理不依赖源代码仅有视频文件的情况
标记式提取灵活可控,支持复杂元素长期项目、需精细控制

实际应用中,推荐优先使用 "运行时筛选" 方案(平衡实现难度和效果),或 "标记式提取" 方案(适合长期维护的项目)。 所有方案均可结合批处理脚本实现多文件自动化处理,根据实际需求调整参数即可获得理想效果。

到此这篇关于Python从Manim中提取表格/坐标系并转GIF的四种高效方案的文章就介绍到这了,更多相关Python Manim提取表格并转GIF内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文