news 2026/6/6 10:27:23

使用PIL库将携带方向信息的图片转正

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
使用PIL库将携带方向信息的图片转正

在深度学习训练当中,遇到有些图在不同平台上看到的方向不一样,会导致出错,这些图一般都是携带方向信息的。例如:我在训练yolo过程中遇到一些图,图片方向是在windows显示是正方向,opencv 读取的图片宽高也是我在屏幕中看到的正方向,但是实际上图片携带了方向信息,导致宽高读错,处理标签时发生了错误,因此训练不佳。使用pil库可以读出来真正的方向信息,记录一下问题解决方法:

fromPILimportImage,ExifTagsimportnumpyasnpdefget_orientation_pil(image_path):""" 使用PIL获取图片的EXIF方向信息 参数: image_path: 图片路径 返回: orientation: 方向值 (1-8) """try:img=Image.open(image_path)exif=img._getexif()ifexifisnotNone:# 查找方向标签 (EXIF标签274)fortag,valueinexif.items():# ExifTags.TAGS是一个字典,将数值标签映射到字符串标签ifExifTags.TAGS.get(tag)=='Orientation':returnvalueexcept(AttributeError,KeyError,IndexError):# 图片可能没有EXIF信息passreturn1# 如果没有方向信息,默认为1(正常方向)defcorrect_image_orientation_pil(image_path,output_path=None,save_rotated=True):""" 使用PIL校正图片方向 参数: image_path: 输入图片路径 output_path: 输出图片路径(如果为None则不保存) save_rotated: 是否保存旋转后的图片 返回: img_rotated: 旋转校正后的PIL Image对象 """# 获取方向信息orientation=get_orientation_pil(image_path)print(f"原始方向标记:{orientation}")# 打开图片img=Image.open(image_path)# 根据方向标记进行旋转iforientation==3:# 旋转180度print("执行:旋转180度")img_rotated=img.transpose(Image.Transpose.ROTATE_180)eliforientation==6:# 顺时针90度(相机逆时针旋转90度拍摄)# 需要逆时针旋转90度来校正print("执行:逆时针旋转90度(校正顺时针90度)")img_rotated=img.transpose(Image.Transpose.ROTATE_270)# 逆时针90度eliforientation==8:# 逆时针90度(相机顺时针旋转90度拍摄)# 需要顺时针旋转90度来校正print("执行:顺时针旋转90度(校正逆时针90度)")img_rotated=img.transpose(Image.Transpose.ROTATE_90)# 顺时针90度else:# 方向1或其他:正常方向,无需旋转print("方向正常,无需旋转")img_rotated=img# 如果需要保存ifsave_rotatedandoutput_path:# 创建新的EXIF信息,移除方向标记exif_data=img.info.get('exif')ifexif_data:# 移除方向标记(避免再次被旋转)# 这里需要处理EXIF二进制数据,较为复杂# 简单的方法是重新保存而不保留EXIF的方向标记img_rotated.save(output_path,quality=95)print(f"已保存校正后的图片到:{output_path}")else:img_rotated.save(output_path,quality=95)print(f"已保存校正后的图片到:{output_path}")returnimg_rotateddefcorrect_and_display_all_orientations():""" 展示所有方向标记的校正效果 """# 模拟不同方向标记的图片(实际应用中需要准备测试图片)orientations=[1,3,6,8]fororientationinorientations:print(f"\n=== 测试方向标记:{orientation}===")# 这里只是演示,实际需要准备相应方向的图片print(f"方向标记{orientation}对应的旋转操作:")iforientation==1:print(" - 无旋转 (正常)")eliforientation==3:print(" - 旋转 180 度")print(" - PIL操作: img.transpose(Image.ROTATE_180)")eliforientation==6:print(" - 逆时针旋转 90 度")print(" - PIL操作: img.transpose(Image.ROTATE_270)")eliforientation==8:print(" - 顺时针旋转 90 度")print(" - PIL操作: img.transpose(Image.ROTATE_90)")defbatch_correct_orientation(input_folder,output_folder,extensions=None):""" 批量校正文件夹中所有图片的方向 参数: input_folder: 输入文件夹路径 output_folder: 输出文件夹路径 extensions: 要处理的图片扩展名列表 """importosifextensionsisNone:extensions=['.jpg','.jpeg','.png','.tiff','.bmp']# 创建输出文件夹os.makedirs(output_folder,exist_ok=True)corrected_count=0total_count=0forfilenameinos.listdir(input_folder):# 检查文件扩展名ifany(filename.lower().endswith(ext)forextinextensions):input_path=os.path.join(input_folder,filename)output_path=os.path.join(output_folder,filename)total_count+=1try:# 获取方向orientation=get_orientation_pil(input_path)iforientationin[3,6,8]:# 需要校正corrected_img=correct_image_orientation_pil(input_path,output_path,save_rotated=True)corrected_count+=1print(f"✓ 已校正:{filename}(方向:{orientation})")else:# 方向正常,直接复制img=Image.open(input_path)img.save(output_path)print(f" 正常方向:{filename}(方向:{orientation})")exceptExceptionase:print(f"✗ 处理失败:{filename}-{str(e)}")print(f"\n批量处理完成!")print(f"总共处理:{total_count}个文件")print(f"校正了:{corrected_count}个文件")# 使用示例if__name__=="__main__":# 示例1: 校正单个图片input_image="path/to/your/image.jpg"output_image="path/to/your/image_corrected.jpg"corrected_img=correct_image_orientation_pil(input_image,output_image,save_rotated=True)# 显示图片信息print(f"\n校正后的图片信息:")print(f" 尺寸:{corrected_img.size}")print(f" 模式:{corrected_img.mode}")print(f" 格式:{corrected_img.format}")# 示例2: 批量处理# batch_correct_orientation("input_folder", "output_folder")# 示例3: 查看方向标记说明print("\n"+"="*50)print("方向标记说明:")print("="*50)print("1: 正常 (无旋转)")print("3: 旋转 180 度")print("6: 顺时针 90 度 (相机逆时针旋转90度拍摄)")print("8: 逆时针 90 度 (相机顺时针旋转90度拍摄)")

在处理数据之前,用上面代码跑一跑,可以将图片转到应该的方向上,避免标签处理失误的情况。原来遇到过一张图,图片方向是看着没问题,然后使用opencv测试也没问题,但是一在部署的平台上(使用了其他图像库)测试结果就不一样了。搞了好久,发现是图片方向问题。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/5 15:01:56

鸣潮ue4崩溃怎么办 教你五招快速恢复

《鸣潮》作为基于 UE4 的大型开放世界游戏,对系统环境、显卡驱动及运行库要求较高,因此部分玩家在进入游戏或加载场景时会遇到 UE4 崩溃、报错或闪退等问题。针对常见根源,以下提供五个相对最有效、最可操作的解决方案,帮助玩家快…

作者头像 李华
网站建设 2026/6/6 19:11:06

app逆向(1)

由于初学,找的无反frida,无加壳的app 一、绕过强制更新 直接使用JADX反编译源码,搜索关键字:更新APP程序。 发现只要让mUpgradeBean.getUpdateType不等于1就可以绕过强制更新 右键跳转到声明 那么就可以编写hook脚本了&a…

作者头像 李华
网站建设 2026/6/5 13:45:44

PowerShell 7.5启动崩溃问题:从诊断到根治的完整解决方案

PowerShell 7.5启动崩溃问题:从诊断到根治的完整解决方案 【免费下载链接】PowerShell PowerShell/PowerShell: PowerShell 是由微软开发的命令行外壳程序和脚本环境,支持任务自动化和配置管理。它包含了丰富的.NET框架功能,适用于Windows和多…

作者头像 李华
网站建设 2026/6/2 16:25:43

29、深入探索GDB调试工具

深入探索GDB调试工具 1. 为GDB编译程序 调试程序时,为了创建增强的符号表,需要使用 -g 选项编译源代码。例如,使用以下命令编译程序: $ gcc -g file1.c file2.c -o prog此命令会使 prog 程序的符号表中包含调试符号。如果需要生成更多(特定于GDB)的调试信息,可以…

作者头像 李华
网站建设 2026/6/3 21:00:42

GLM-4-9B完全指南:如何快速上手智谱AI最强开源大模型

GLM-4-9B完全指南:如何快速上手智谱AI最强开源大模型 【免费下载链接】glm-4-9b 项目地址: https://ai.gitcode.com/zai-org/glm-4-9b 想要在本地部署一个功能强大的中文大语言模型,却担心硬件要求和部署复杂度?智谱AI推出的GLM-4-9B…

作者头像 李华