news 2026/2/18 12:08:53

使用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/2/15 13:06:52

39M参数撬动百亿市场:Whisper-Tiny.en引领嵌入式语音交互革命

39M参数撬动百亿市场:Whisper-Tiny.en引领嵌入式语音交互革命 【免费下载链接】whisper-tiny.en 项目地址: https://ai.gitcode.com/hf_mirrors/openai/whisper-tiny.en 导语 OpenAI推出的Whisper-Tiny.en模型以3900万参数实现8.44%的英语语音识别错误率&a…

作者头像 李华
网站建设 2026/2/14 6:24:44

终极指南:M3 Pro芯片运行CosyVoice性能优化技巧

想要在M3 Pro芯片的MacBook上流畅运行CosyVoice多语言语音生成模型吗?本文将为你揭示从卡顿到丝滑的完整性能优化方案,让Apple Silicon发挥最大潜能,实现语音合成效率的显著提升。 【免费下载链接】CosyVoice Multi-lingual large voice gene…

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

Citybound道路规划系统深度解析:从新手到专家的进阶指南

在城市模拟游戏的世界里,道路系统往往决定了整个城市的命运。Citybound作为一款开源的多玩家城市模拟游戏,其道路规划系统以其智能化和易用性而著称。本文将带您深入探索这一系统的奥秘,掌握从基础操作到高级技巧的全套技能。 【免费下载链接…

作者头像 李华
网站建设 2026/2/18 1:49:45

容器和进程,自动化的关系概论

容器化技术(如Docker)与进程、自动化之间有着密切的关系。容器本质上是进程的隔离环境,而自动化则是容器技术的重要应用场景和优势所在。 一、容器与进程的关系 容器是进程的扩展 容器实际上是一个或多个进程的集合,这些进程运行在…

作者头像 李华
网站建设 2026/2/4 8:01:28

放弃30万年薪后,他用AI求职中介精准匹配海外岗位?

“放弃30万年薪,他靠AI求职中介‘越级匹配’英国算法岗,回国反而‘水土不服’?”“不是所有30万的‘体面’,都抵得上一次被看见的精准对焦。”引言 最近,一位服务超过5年、帮助超百名留学生进入顶尖科技公司的资深算法…

作者头像 李华
网站建设 2026/2/7 4:32:24

31、创建程序文档:man 页面与 SGML 文档的实践指南

创建程序文档:man 页面与 SGML 文档的实践指南 在软件开发过程中,为程序创建清晰、准确的文档是至关重要的。它不仅有助于其他开发者理解和使用你的程序,还能在后续的维护和扩展中提供重要的参考。本文将介绍如何使用 groff 创建 man 页面,以及如何利用功能更强大、更灵活的…

作者头像 李华