news 2026/6/10 14:21:50

使用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/10 14:42:54

Llama-Factory模型评估模块全面解读:准确率、困惑度一键生成

Llama-Factory模型评估模块全面解读:准确率、困惑度一键生成 在大模型落地越来越密集的今天,一个现实问题摆在开发者面前:如何快速判断一次微调是否“有效”?不是看训练损失下降了多少,而是真正回答——这个模型现在能…

作者头像 李华
网站建设 2026/6/9 23:53:01

kanass实战教程系列(9) - 如何进行缺陷管理

上一篇文章主要介绍了如何进行Kanass任务管理,本文将介绍在事项模块中如何创建、管理、跟踪缺陷。1、添加缺陷进入kanass项目,页面会自动定位到事项页面。点击添加事项->缺陷,填写缺陷标题与描述,选择缺陷类型等信息添加缺陷属…

作者头像 李华
网站建设 2026/6/10 13:04:47

电气消防器具-图形识别精准计量

电气消防器具-图形识别精准计量 电气消防器具如同遍布每个角落的“数字哨兵”,时刻守护着人员与财产安全。本文将聚焦火灾自动报警系统的关键设备,深入解读其工程计量规范,并重点剖析如何运用CAD快速看图的【图形识别】,对各类消…

作者头像 李华
网站建设 2026/6/10 13:04:49

17、UDP与组播IP编程:原理、示例与应用

UDP与组播IP编程:原理、示例与应用 1. UDP协议概述 UDP(User Data Protocol)是一种比TCP更低级的协议。与TCP不同,UDP不保证消息的可靠传递,也不保证消息按发送顺序到达,且不提供传递失败的通知。 1.1 TCP与UDP的对比 通常认为,对于大多数应用程序而言,使用TCP套接…

作者头像 李华
网站建设 2026/6/10 13:06:41

告别复杂金融预测:5分钟上手Kronos实现市场趋势预判

告别复杂金融预测:5分钟上手Kronos实现市场趋势预判 【免费下载链接】Kronos Kronos: A Foundation Model for the Language of Financial Markets 项目地址: https://gitcode.com/GitHub_Trending/kronos14/Kronos 你是否还在为金融数据预测的复杂流程而困扰…

作者头像 李华
网站建设 2026/6/10 13:04:30

云手机哪个性价比高,稳定与价低兼得才是首选!

云手机哪个性价比高,稳定与价低兼得才是首选!当今市面上云手机品牌众多,用户们挑得都眼花缭乱了。云手机到底要怎么选?是看谁最便宜?看谁性能最优?还是谁的性价比最高?今天就来盘点四款云手机&a…

作者头像 李华