IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 人工智能 -> yolov5踩坑记录:标签错位(PIL读取图片方向异常) -> 正文阅读

[人工智能]yolov5踩坑记录:标签错位(PIL读取图片方向异常)

PIL踩坑记录:读取图片方向异常(yolov5标签错位)

奇怪的现象

今天用 YOLOv5 做项目时,对数据集的标记出现了奇怪的现象,在下述测试用例中可明显看到,标记框偏离了物体,故发文阐述原因和解决方法. ——?? Sylvan Ding 转载需注明出处

在这里插入图片描述

下载了一份数据集UNIMIB2016,使用 PIL 读取其中一张照片并标记 bbox.

from PIL import Image

img_name = '20151127_120643.jpg'
img = Image.open(img_name)
img.show()

在这里插入图片描述

from PIL import ImageDraw
from PIL import ImageFont

label_name = '20151127_120643.txt'
with open(label_name) as file:
    items = file.readlines()
    
draw = ImageDraw.Draw(img)
for item in items:
  
    item = item.split()
    
    # convert str to int
    item[1:] = list(map(int, item[1:]))
    
    # draw bbox
    draw.rectangle([item[1], item[2], item[5], item[6]],
                       outline="red", width=20)
    
    # add text about order of the points
    for j, i in enumerate([1, 3, 5, 7]):
        j = j + 1
        draw.text([item[i], item[i + 1]], str(j))

img.show()
        
# items
# ['pane 2008 404 2713 404 2713 915 2008 915\n',
#  'pizzoccheri 1502 1104 2500 1104 2500 1984 1502 1984\n',
#  'arrosto 634 602 1193 602 1193 1371 634 1371\n',
#  'patate/pure 271 539 708 539 708 1408 271 1408\n']

# the lash item, whose form is [cls, x1, y1, x2, y2, x3, y3, x4, y4]
# ['patate/pure', 271, 539, 708, 539, 708, 1408, 271, 1408]

在这里插入图片描述

bbox 正确,但整张图片好似被旋转了一样。接着使用 cv2 进行相同操作,并观察结果。

import cv2
from matplotlib import pyplot as plt

img = cv2.imread(img_name)
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)

for item in items:

    item = item.split()

    # convert str to int
    item[1:] = list(map(int, item[1:]))

    # draw bbox
    cv2.rectangle( img,
                  (item[1], item[2]),
                  (item[5], item[6]),
                  (0, 255, 0), 30)

plt.imshow(img)
plt.show()

在这里插入图片描述

不难发现,draw bbox 中使用的坐标均为 [x1,y1], [x3, y3],即对角坐标(left-top、right-bottom),但 PILcv2 的结果不同。cv2 中 bbox 错位了,而 PIL 中 text 发生了旋转.

😯 为什么会产生这种现象呢?从 EXIT 说起:

什么是EXIF?

EXIF(Exchangeable Image File)是"可交换图像文件"的缩写,当中包含了专门为数码相机的照片而定制的元数据,可以记录数码照片的拍摄参数、缩略图及其他属性信息。Exif 文件实际是JPEG文件的一种,遵从JPEG标准,只是在文件头信息中增加了有关拍摄信息的内容和索引图。

简单来说,Exif 信息就是由数码相机在拍摄过程中采集一系列的信息,然后把信息放置在我们熟知的 JPEG/TIFF 文件的头部,也就是说 Exif信息是镶嵌在 JPEG/TIFF 图像文件格式内的一组拍摄参数,它就好像是傻瓜相机的日期打印功能一样,只不过 Exif信息所记录的资讯更为详尽和完备。

EXIF Orientation tag

EXIF Orientation tag(EXIF方向参数)让你随便照像但都可以看到正确方向的照片而无需手动旋转(前提要图片浏览器支持,Windows 自带的不支持).

在这里插入图片描述

?? 原因解释

造成第一目中“奇怪现象”的原因,我将其归纳为:在标记数据集时,不关注图像的 EXIF Orientation tag,而图像本身是含有 EXIF Orientation tag 的。在 PIL 读取图片时,创建了 Image 对象,其中存有 EXIF Orientation tag,根据该标记,不仅旋转了图像,还旋转了图像的参考系。而 cv2 读取图片时,直接生成 numpy.ndarray 数组,只根据 EXIF Orientation tag 对图像进行了旋转,但并没有旋转图像的参考系

PIL

在这里插入图片描述

在这里插入图片描述

cv2

在这里插入图片描述

在绘制矩形框时,二者依赖的参考系不同,导致标记的错位。而 yolov5 使用的正是 cv2,故读取含 EXIF Orientation tag 的图片时,会造成 labels 和 图片的错位。

原因证实

PIL 的 PIL.ImageOps.exif_transpose(image)方法,可以在读取图片后,清除 Image 对象内的 EXIF Orientation tag,从而让坐标系不受该 tag 的影响.

from PIL import ImageOps

img = Image.open(img_name)
img = ImageOps.exif_transpose(img)

# draw bbox
...

1

可见,清除 EXIF 旋转信息后,PIL 所得结果和 cv2 结果一致!

?? 解决方法

?? 当然,如果你有更好的方法欢迎在评论区留言告诉我哦!

from os import listdir
from PIL import Image
import numpy as np

img = './images/'
if __name__ == '__main__':
    for img_name in listdir(img_path):
        img = Image.open(img_path + img_name)
        img_rectified = Image.fromarray(np.asarray(img))
        img_rectified.save(img_path + img_name)

上述代码对 ./images/文件夹下所有图片进行了“修正”,核心是 img_rectified = Image.fromarray(np.asarray(img)),(1). 将 img 转化为 ndarray,(2). 再将该ndarray转化为Image并保存.

(1)、(2) 等同于去除了图片所有的 EXIF 信息,这样图片就不会再发生“自动旋转”的现象了.

在这里插入图片描述

转载请注明出处:?? Sylvan Ding

参考文献

  1. PIL thumbnail is rotating my image?
  2. 图片元信息Exif,给你详细讲讲
  3. EXIF 方向参数 Orientation
  人工智能 最新文章
2022吴恩达机器学习课程——第二课(神经网
第十五章 规则学习
FixMatch: Simplifying Semi-Supervised Le
数据挖掘Java——Kmeans算法的实现
大脑皮层的分割方法
【翻译】GPT-3是如何工作的
论文笔记:TEACHTEXT: CrossModal Generaliz
python从零学(六)
详解Python 3.x 导入(import)
【答读者问27】backtrader不支持最新版本的
上一篇文章      下一篇文章      查看所有文章
加:2022-04-28 11:50:53  更:2022-04-28 11:53:57 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 8:49:28-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码