
背景需求
之前用天工AI和Python做了PPT文字、板式和gif图片
发送第一稿PPT后,修改第二稿

总要求

解决:把正文文字都删除,只留二级标题,gif图片放大
原图
修改

原图

修改后

原图

修改后

要求1:批量gif图片制作+PPT按钮触发器


横竖都有

转横版、转竖版
python
'''
把照片根据横板竖版拆分两个,考虑exif
deepseek 阿夏
20260319
'''
import os
import shutil
from PIL import Image, ImageOps
import glob
def get_correct_dimensions(image_path):
"""
获取考虑EXIF方向后的正确尺寸
Returns:
(实际宽度, 实际高度, 是否需要旋转)
"""
with Image.open(image_path) as img:
# 获取原始尺寸
width, height = img.size
# 获取EXIF方向信息
try:
exif = img._getexif()
if exif:
# EXIF方向标签通常是274
orientation = exif.get(274, 1)
# 显示EXIF信息用于调试
orientation_map = {
1: "正常",
2: "水平翻转",
3: "旋转180°",
4: "垂直翻转",
5: "旋转90°并水平翻转",
6: "旋转90°",
7: "旋转90°并垂直翻转",
8: "旋转270°"
}
orientation_desc = orientation_map.get(orientation, f"未知({orientation})")
print(f" EXIF方向: {orientation_desc}")
# 如果图片需要旋转90°或270°,则实际显示尺寸应该交换宽高
if orientation in [5, 6, 7, 8]:
# 这些方向表示图片需要旋转,所以实际的宽高是相反的
actual_width, actual_height = height, width
print(f" 注意: 图片需要旋转,实际显示尺寸应为 {actual_width} x {actual_height}")
return actual_width, actual_height, True
else:
return width, height, False
except Exception as e:
print(f" 读取EXIF信息失败: {e}")
pass
return width, height, False
def fix_image_orientation(image_path, destination_path):
"""
修复图片方向并保存
"""
with Image.open(image_path) as img:
try:
# 使用ImageOps.exif_transpose自动根据EXIF信息旋转图片
fixed_img = ImageOps.exif_transpose(img)
# 保存修复后的图片
fixed_img.save(destination_path)
return True
except Exception as e:
print(f" 修复图片方向失败: {e}")
# 如果修复失败,直接复制原图
shutil.copy2(image_path, destination_path)
return False
def classify_images_by_orientation(source_folder, fix_orientation=True):
"""
根据图片实际显示方向分类复制图片(修复重复处理问题)
Args:
source_folder: 源文件夹路径
fix_orientation: 是否修复图片方向(将图片旋转到正确方向)
"""
# 创建目标文件夹
horizontal_folder = os.path.join(source_folder, "横")
vertical_folder = os.path.join(source_folder, "竖")
os.makedirs(horizontal_folder, exist_ok=True)
os.makedirs(vertical_folder, exist_ok=True)
# 使用集合来记录已处理的文件,避免重复
processed_files = set()
# 支持的图片格式 - 使用小写统一匹配
image_extensions = ['*.jpg', '*.jpeg', '*.png', '*.gif', '*.bmp', '*.tiff',
'*.webp'] # 移除大写版本,下面会统一处理
stats = {
'horizontal': 0,
'horizontal_with_exif': 0, # 有EXIF旋转的横图
'vertical': 0,
'vertical_with_exif': 0, # 有EXIF旋转的竖图
'square': 0,
'skipped_duplicate': 0, # 跳过的重复文件
'error': 0
}
print("开始处理图片(已启用EXIF方向识别)...")
print("="*70)
# 先收集所有图片文件,避免重复
all_images = []
for extension in image_extensions:
# 使用大小写不敏感的匹配
all_images.extend(glob.glob(os.path.join(source_folder, extension)))
all_images.extend(glob.glob(os.path.join(source_folder, extension.upper())))
# 去重(使用规范化路径)
unique_images = set()
for image_path in all_images:
# 获取绝对路径并规范化
abs_path = os.path.abspath(image_path)
unique_images.add(abs_path)
print(f"找到 {len(unique_images)} 个唯一图片文件")
for image_path in unique_images:
# 检查是否已经在子文件夹中
if (os.path.dirname(image_path) == horizontal_folder or
os.path.dirname(image_path) == vertical_folder):
continue
# 检查是否已经处理过
if image_path in processed_files:
stats['skipped_duplicate'] += 1
continue
try:
filename = os.path.basename(image_path)
print(f"\n处理: {filename}")
# 获取考虑EXIF后的实际尺寸
actual_width, actual_height, has_exif_rotation = get_correct_dimensions(image_path)
# 获取原始尺寸(避免重复打开图片)
with Image.open(image_path) as img:
original_width, original_height = img.size
print(f" 原始尺寸: {original_width} x {original_height}")
print(f" 实际显示尺寸: {actual_width} x {actual_height}")
# 根据实际显示尺寸判断方向
if actual_width > actual_height:
# 横图
target_folder = horizontal_folder
stats['horizontal'] += 1
if has_exif_rotation:
stats['horizontal_with_exif'] += 1
orientation_type = "横图"
elif actual_width < actual_height:
# 竖图
target_folder = vertical_folder
stats['vertical'] += 1
if has_exif_rotation:
stats['vertical_with_exif'] += 1
orientation_type = "竖图"
else:
# 正方形
stats['square'] += 1
print(f" ⚠️ 正方形图片,保持不变")
# 标记为已处理
processed_files.add(image_path)
continue
# 生成目标路径(处理重名)
destination = os.path.join(target_folder, filename)
if os.path.exists(destination):
base, ext = os.path.splitext(filename)
counter = 1
while os.path.exists(os.path.join(target_folder, f"{base}_{counter}{ext}")):
counter += 1
destination = os.path.join(target_folder, f"{base}_{counter}{ext}")
# 复制或修复图片
if fix_orientation and has_exif_rotation:
# 如果需要修复方向,保存旋转后的图片
success = fix_image_orientation(image_path, destination)
if success:
print(f" ✅ 归类为: {orientation_type} (已修复EXIF方向)")
else:
print(f" ✅ 归类为: {orientation_type} (EXIF修复失败,直接复制)")
else:
# 直接复制
shutil.copy2(image_path, destination)
print(f" ✅ 归类为: {orientation_type}")
# 标记为已处理
processed_files.add(image_path)
except Exception as e:
stats['error'] += 1
print(f" ❌ 处理图片时出错: {str(e)}")
# 即使出错也标记,避免重复尝试
processed_files.add(image_path)
# 打印详细统计信息
print("\n" + "="*70)
print("处理完成!详细统计信息:")
print(f"📊 横图总数: {stats['horizontal']}")
if stats['horizontal_with_exif'] > 0:
print(f" └─ 其中包含EXIF旋转信息的: {stats['horizontal_with_exif']}")
print(f"📊 竖图总数: {stats['vertical']}")
if stats['vertical_with_exif'] > 0:
print(f" └─ 其中包含EXIF旋转信息的: {stats['vertical_with_exif']}")
print(f"📊 正方形图片: {stats['square']}")
print(f"📊 跳过的重复文件: {stats['skipped_duplicate']}")
print(f"📊 处理失败: {stats['error']}")
print(f"📊 总共处理: {len(processed_files)} 个文件")
print("="*70)
if fix_orientation:
print("\n✨ 已自动修复所有包含EXIF旋转信息的图片方向!")
print("修复后的图片会以正确的方向保存在目标文件夹中。")
# 如果还想进一步调试,可以使用这个调试版本
def debug_duplicate_files(source_folder):
"""
调试函数:检查文件夹中的重复文件
"""
print("检查重复文件...")
# 收集所有文件
all_files = []
for root, dirs, files in os.walk(source_folder):
for file in files:
if file.lower().endswith(('.jpg', '.jpeg', '.png', '.gif', '.bmp')):
full_path = os.path.join(root, file)
all_files.append(full_path)
# 按文件名分组
files_by_name = {}
for file_path in all_files:
filename = os.path.basename(file_path)
if filename not in files_by_name:
files_by_name[filename] = []
files_by_name[filename].append(file_path)
# 找出重复的文件名
duplicates = {name: paths for name, paths in files_by_name.items() if len(paths) > 1}
if duplicates:
print(f"\n发现 {len(duplicates)} 个重复文件名:")
for name, paths in duplicates.items():
print(f"\n文件: {name}")
for path in paths:
print(f" - {path}")
else:
print("没有发现重复文件名")
# 使用示例
if __name__ == "__main__":
folder_path = r"D:\20260306江小囡PPT素材\5.寒假生活\数字路"
if os.path.exists(folder_path):
# 可选:先运行调试函数检查重复文件
# debug_duplicate_files(folder_path)
print("请选择模式:")
print("1. 完整模式:根据EXIF正确分类并修复图片方向")
print("2. 简单模式:只根据EXIF正确分类,不修改图片")
# 使用完整模式,但已修复重复处理问题
classify_images_by_orientation(folder_path, fix_orientation=True)
else:
print(f"错误:文件夹 '{folder_path}' 不存在!")



目测观看照片上的马路牌,手动更名,XX路改成1号路,XX路改成2号路
我不知道XX到底是几号路,要反复对应查看。我觉得最好是用AI识图识别文字,自动变更文件名,但是因为上面有小孩头像,所以还是自己人工修改,但是人工标注,也容易输错号码
1号路,就是1.1,1.29这种,便于后续统一改名,依次类推




把文件名更改一下


python
'''
把文件名中第一个点后面的编号改成_01_02......
deepseek 阿夏
20260319
'''
import os
def batch_rename_images(folder_path):
"""
批量重命名图片文件:
1. 识别文件名中第一个点之前的数字作为前缀
2. 同一前缀的文件按顺序重命名为:前缀_01、前缀_02...
3. 忽略(2)这类重复标记,只按前缀分组排序
"""
image_extensions = ('.png', '.jpg', '.jpeg', '.gif', '.bmp', '.tiff')
try:
all_files = os.listdir(folder_path)
files_by_prefix = {}
# 分组:按第一个点前的数字分组
for file in all_files:
if file.lower().endswith(image_extensions):
# 取第一个点之前的部分作为前缀
if '.' in file:
prefix_part = file.split('.')[0]
# 只保留数字部分(处理类似1.9(2) → 前缀是1)
prefix = ''.join([c for c in prefix_part if c.isdigit()])
if prefix:
if prefix not in files_by_prefix:
files_by_prefix[prefix] = []
files_by_prefix[prefix].append(file)
# 处理每个前缀组
for prefix, files in files_by_prefix.items():
# 按文件名自然排序(处理1.9、1.9(2)这类顺序)
files.sort()
count = 1
print(f"\n处理前缀 '{prefix}' 的文件:")
for old_filename in files:
file_ext = os.path.splitext(old_filename)[1]
new_filename = f"{prefix}_{count:02d}{file_ext}"
old_path = os.path.join(folder_path, old_filename)
new_path = os.path.join(folder_path, new_filename)
# 避免重名冲突
while os.path.exists(new_path):
count += 1
new_filename = f"{prefix}_{count:02d}{file_ext}"
new_path = os.path.join(folder_path, new_filename)
os.rename(old_path, new_path)
print(f"{old_filename} -> {new_filename}")
count += 1
print(f"前缀 '{prefix}' 处理完成,共 {count-1} 个文件。")
print("\n✅ 所有文件处理完成!")
except FileNotFoundError:
print(f"❌ 错误:找不到文件夹 '{folder_path}'")
except Exception as e:
print(f"❌ 发生错误:{e}")
if __name__ == "__main__":
# 替换为你的目标文件夹路径
folder_path = r"D:\20260306江小囡PPT素材\5.寒假生活\数字路\横1"
batch_rename_images(folder_path)


同理做"竖"的文件名统一


前面做过三个文件名"地标建筑""公园""数字路"的转移文件夹代码



python
'''
读取图片的文件名里的指定文字"1、2、3",合并到同名文件夹下
deepseek 阿夏
20260319
'''
import os
import shutil
from pathlib import Path
def classify_images_by_number_prefix(source_folder):
"""
根据图片文件名中包含的数字(1、2、3...)将图片分类到对应数字名称的文件夹中
兼容两种文件名格式:
1. 带_的格式(如9_01.jpg):提取_前的数字
2. 普通格式(如9路.jpg):提取文件名中的任意数字
"""
# 确保源文件夹存在
if not os.path.exists(source_folder):
print(f"❌ 错误:文件夹 {source_folder} 不存在")
return
# 支持的图片格式
image_extensions = {'.jpg', '.jpeg', '.png', '.gif', '.bmp', '.tiff', '.webp'}
# 统计信息
classified_count = 0
unclassified_files = []
try:
# 获取所有文件
all_files = os.listdir(source_folder)
# 遍历所有文件
for filename in all_files:
file_path = os.path.join(source_folder, filename)
# 跳过文件夹(避免处理已创建的数字文件夹)
if os.path.isdir(file_path):
continue
# 检查是否为图片文件
file_ext = Path(filename).suffix.lower()
if file_ext not in image_extensions:
continue
# ========== 核心逻辑:提取文件名中的数字 ==========
# 先尝试按_分割提取前缀数字
prefix_num = ""
if '_' in filename:
prefix_part = filename.split('_')[0]
prefix_num = ''.join([c for c in prefix_part if c.isdigit()])
# 如果按_分割没找到数字,直接提取文件名中的所有数字
if not prefix_num:
all_nums = ''.join([c for c in filename if c.isdigit()])
if all_nums:
prefix_num = all_nums[0] # 取第一个数字
# 检查是否提取到有效数字
if prefix_num and prefix_num.isdigit():
num = int(prefix_num)
# 创建目标文件夹(数字名称)
target_folder = os.path.join(source_folder, str(num))
os.makedirs(target_folder, exist_ok=True)
# 构建目标文件路径
target_path = os.path.join(target_folder, filename)
# 处理重名文件(添加_copy后缀)
copy_suffix = 1
while os.path.exists(target_path):
name, ext = os.path.splitext(filename)
target_path = os.path.join(target_folder, f"{name}_copy{copy_suffix}{ext}")
copy_suffix += 1
# 移动文件(如果想复制而不是移动,把move改成copy2)
shutil.move(file_path, target_path) # 移动文件
# shutil.copy2(file_path, target_path) # 复制文件(保留元数据)
print(f"✅ {filename} -> {num}/")
classified_count += 1
else:
# 未提取到有效数字的文件
unclassified_files.append(filename)
except Exception as e:
print(f"❌ 处理过程中出错:{str(e)}")
return
# 输出统计结果
print("\n" + "="*60)
print(f"📊 分类完成!")
print(f" 已分类文件数:{classified_count}")
print(f" 未分类文件数:{len(unclassified_files)}")
# 显示未分类的文件(最多显示10个)
if unclassified_files:
print(f"\n❓ 未分类的文件(文件名中未找到有效数字):")
for f in unclassified_files[:10]:
print(f" - {f}")
if len(unclassified_files) > 10:
print(f" ... 还有 {len(unclassified_files)-10} 个文件未显示")
def main():
# ========== 请修改这里的文件夹路径 ==========
source_folder = r"D:\20260306江小囡PPT素材\5.寒假生活\数字路\竖1"
print(f"🚀 开始处理文件夹: {source_folder}")
print(f"📋 规则:按文件名中的数字分类到对应数字文件夹")
print("="*60)
# 执行分类
classify_images_by_number_prefix(source_folder)
print("\n💡 提示:")
print(" - 如果想复制文件而不是移动,把代码中的shutil.move改成shutil.copy2")
print(" - 未分类文件可能是文件名中不包含数字")
if __name__ == "__main__":
main()




每个文件夹检查一下,可能有标错数字的情况,把图片转移走

同理制作横版的1-12文件夹,转移图片,检查路牌是否一致





运气好,横版照片内容都是在正确文件夹里(因为大部分横版照片上都有家长或老师填写的标注,我直接就能修改文件名。)
现在我希望遍历1-12文件夹,制作2秒一张的gif
复制3秒一张文件夹


python
'''
汇报PPT,遍历路字数文件夹内"1-12文件夹"内JPG图片逐一合并为12个动态GIF,间隔时间可设置
优化版本:增加错误处理、路径验证、进度显示
deepseek,阿夏
20250512
'''
from PIL import Image
import os
import sys
import shutil
def get_float_input(prompt, default=0.5):
"""
获取浮点数输入,带错误处理
"""
while True:
try:
user_input = input(prompt)
# 如果直接回车,使用默认值
if user_input.strip() == '':
print(f'使用默认值: {default}秒')
return default
value = float(user_input)
if value <= 0:
print('间隔时间必须大于0,请重新输入')
continue
return value
except ValueError:
print('输入无效,请输入数字(例如:0.5、1、2)')
def create_gif_from_images(folder_path, output_gif, target_size=(1024, 720), interval=0.5):
"""
将文件夹中的所有图片合并为GIF
参数:
folder_path: 包含图片的文件夹路径
output_gif: 输出的GIF文件名
target_size: 目标图片大小 (宽, 高)
interval: 每帧间隔时间(秒)
"""
# 支持的图片格式
valid_extensions = ('.png', '.jpg', '.jpeg', '.bmp', '.jfif', '.tiff', '.webp')
# 获取文件夹中所有图片文件(按文件名排序,保证顺序)
image_files = []
for file in sorted(os.listdir(folder_path)):
if file.lower().endswith(valid_extensions):
image_files.append(os.path.join(folder_path, file))
if not image_files:
print(f"⚠️ 文件夹 '{os.path.basename(folder_path)}' 中没有找到支持的图片文件!")
return False
print(f"\n📂 处理文件夹: {os.path.basename(folder_path)}")
print(f" 找到 {len(image_files)} 张图片")
print(f" 目标尺寸: {target_size[0]}x{target_size[1]}")
print(f" 每帧间隔: {interval}秒")
# 打开所有图片并调整大小
images = []
for i, image_file in enumerate(image_files):
try:
# 显示进度
print(f" 处理第 {i+1}/{len(image_files)} 张: {os.path.basename(image_file)}")
img = Image.open(image_file)
# 转换为RGB模式(防止GIF保存时出错)
if img.mode != 'RGB':
img = img.convert('RGB')
# 直接拉伸到目标尺寸(不保持比例)
img = img.resize(target_size, Image.Resampling.LANCZOS)
images.append(img)
except Exception as e:
print(f"⚠️ 警告: 无法处理文件 {os.path.basename(image_file)}: {e}")
continue
if not images:
print(f"❌ 文件夹 '{os.path.basename(folder_path)}' 没有有效的图片可以处理!")
return False
# 设置每帧的持续时间(毫秒)
durations = [int(interval * 1000)] * len(images) # 所有帧相同时间
print(f" 正在生成GIF...")
try:
# 保存为GIF
images[0].save(
output_gif,
save_all=True,
append_images=images[1:],
duration=durations,
loop=0, # 无限循环
optimize=True, # 优化GIF
quality=95 # 设置质量
)
# 获取文件大小
file_size = os.path.getsize(output_gif) / (1024 * 1024) # 转换为MB
print(f"✅ GIF已生成: {os.path.basename(output_gif)}")
print(f" 文件大小: {file_size:.2f} MB")
print(f" 总时长: {interval * len(images):.1f}秒")
return True
except Exception as e:
print(f"❌ 保存GIF时出错: {e}")
return False
def batch_generate_gif():
"""
批量遍历子文件夹并生成GIF
"""
print("=" * 60)
print(" 批量图片转GIF工具 v3.0")
print(" 自动遍历子文件夹并生成GIF")
print("=" * 60)
# 基础路径(横1文件夹)
base_path = r'D:\20260306江小囡PPT素材\5.寒假生活\数字路\横1'
# 检查基础路径是否存在
if not os.path.exists(base_path):
print(f"❌ 错误: 基础路径不存在!")
print(f"路径: {base_path}")
input("按回车键退出...")
return
# 创建输出目录(gif文件夹)
output_root = os.path.join(base_path, "gif")
os.makedirs(output_root, exist_ok=True)
print(f"\n📁 输出目录: {output_root}")
# 获取间隔时间
interval = get_float_input('\n请输入每张图片间隔秒数 (直接回车默认0.5秒): ', default=0.5)
# 获取目标尺寸(可选自定义)
print("\n📏 设置GIF尺寸(直接回车使用默认1024x720)")
width = '1024'
# 度: ").strip()
height ='720'
# input("请输入高度: ").strip()
if width and height:
try:
target_size = (int(width), int(height))
print(f"使用自定义尺寸: {target_size[0]}x{target_size[1]}")
except ValueError:
print("输入无效,使用默认尺寸 1024x720")
target_size = (1024, 720)
else:
target_size = (1024, 720)
print(f"使用默认尺寸: {target_size[0]}x{target_size[1]}")
print("\n" + "-" * 60)
print("开始遍历子文件夹并生成GIF...")
print("-" * 60)
# 统计信息
total_folders = 0
success_count = 0
fail_count = 0
# 遍历所有子文件夹
for item in os.listdir(base_path):
item_path = os.path.join(base_path, item)
# 只处理文件夹,跳过文件和gif输出文件夹
if os.path.isdir(item_path) and item != "gif":
total_folders += 1
# 构建输出GIF路径(以子文件夹名称命名)
gif_filename = f"{item}.gif"
output_gif = os.path.join(output_root, gif_filename)
# 生成GIF
result = create_gif_from_images(
item_path,
output_gif,
target_size=target_size,
interval=interval
)
if result:
success_count += 1
else:
fail_count += 1
# 输出统计结果
print("\n" + "=" * 60)
print("📊 批量处理完成!")
print(f" 总文件夹数: {total_folders}")
print(f" 成功生成: {success_count} 个GIF")
print(f" 生成失败: {fail_count} 个")
print(f" GIF文件保存位置: {output_root}")
print("=" * 60)
input("\n按回车键退出...")
# 使用示例
if __name__ == "__main__":
try:
batch_generate_gif()
except KeyboardInterrupt:
print("\n\n⚠️ 程序被用户中断")
sys.exit(0)
except Exception as e:
print(f"\n❌ 程序出现意外错误: {e}")
input("按回车键退出...")



设置2秒一张

把gif图片复制到PPT内,"gif图片"设置"动画-出现、动画-消失",两个动画都设置触发器(点击圆形按钮buttun)。

两个动画都设置"点击"





但是幼儿拍照的照片里没有4号6号路(不在幼儿园附近)
领导发了1-12号路的空景照片

同样方法做1-12按钮触发器,显示和消失jpg图片

要求2.视频去掉声音,更换成上海话配音



打开剪映

去掉视频的声音(音轨分离)

删除音频

把视频速度从1倍改成0.91

原始视频里面的播报声音有"扩音器公放"的"回声"效果,但后期上海话配音没有"回声",
所以我查看声音编辑器,发现右侧有"模拟音效"功能。

选择"上海话"音频轨道,添加"扩音器"音效

上海话声音也有扩音器效果了,就是口型和对话内容配不上。
要求4

原始PPT里有数据,但是咖啡底的数字是正确的

柱状图上的数字是不对的,我需要修改柱状图的数字和坐标轴


Y坐标轴间距不对

换了关键词还是不对


帮我生成图片:不对。"这场行走不仅让467组家庭的足迹遍布江川62个地点,累计打卡1136次",根据这个做一直方图,Y轴坐标间隔是200

选了这张,再贴两个咖啡色块

贴一块颜色上去,与背景配色相似

打卡次数的文字有重影,去其他图片上复制一块文字,贴上去


仔细看,可以看到X轴文字底纹是浅黄色色,不是白色

为了板式好看,加了其他数据
要求5,减少照片

只要删掉文件夹里的照片,然后再用gif代码重做一份。
第二稿上传

