当前位置: 首页 > news >正文

使用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测试也没问题,但是一在部署的平台上(使用了其他图像库)测试结果就不一样了。搞了好久,发现是图片方向问题。

http://www.cnnetsun.cn/news/24387.html

相关文章:

  • 8GB显存也能玩转电影级视频生成:WAN2.2-14B-Rapid-AllInOne完全指南
  • Xiaomusic网络歌单转换实战手册:3分钟搞定m3u转json
  • 极速上手MineContext:Docker容器化部署完整攻略
  • kanass全面介绍(8) - 如何进行任务管理
  • 2026年软考软件设计师考试题型有哪些?
  • 如何在5分钟内完成AI语音工具部署:GPU与CPU双版本零配置指南
  • Qwen-Image-Edit-Rapid-AIO V10:新手也能驾驭的AI图像编辑神器
  • 27、OpenGL/Mesa与GNU bash编程入门
  • 28、安全编程:保障程序与数据安全的关键策略
  • 程序员:微软的技术面试主要考察方向探讨
  • ZLToolKit模块(三)ResourcePool(对象池)
  • Tensor2Tensor深度学习框架终极安装配置指南
  • Day27:I2C 协议基础
  • SAP批量修改SPRO配置(针对按公司代码的配置项)
  • 以前我手动砌 DOM,现在 Vue 给我盖别墅
  • 祛湿妙招:中医教你赶走湿气
  • 52.事件驱动架构-利用异步事件解耦微服务-代码实操附消息队列集成
  • 开源波斯阿拉伯文字体设计原理与多语言排版实践
  • vmware中Centos虚拟机使用virt-manager创建虚拟机
  • FITC-Gentamicin,FITC-庆大霉素,生物分子标记、细胞成像
  • FITC-SH,异硫氰酸荧光素标记巯基,细胞成像、免疫分析和分子研究
  • 掌握偏振镜使用方法,解决反光难题
  • 智慧农业的“数据大脑”:无人机搭载近红外光谱+ChatGPT分析,实现作物长势精准监测、病虫害早期预警、变量施肥智能决策的完整闭环系统
  • Kimi-VL-A3B-Thinking-2506:多模态大模型实现“思考效率与视觉能力“双重突破
  • 81、使用 Linux 进行云计算的详细指南
  • 前端如何通过JavaScript实现视频文件的分段上传?
  • 深度解析:智谱GLM-4.5如何用3大创新突破AGI技术瓶颈
  • TinyMCE4粘贴ppt幻灯片转存网页兼容
  • 23、Linux Web服务器综合指南
  • 3小时精通Halo仪表盘组件开发:从零到一的完整实战手册