标签图片的方法与实作 - Day 12

标签图片的方法与实作 - Day 12

资料增量 (Data Augmentation) 的部份因为 YOLOV3 可以透过 cfg 档的设定来自动进行资料增量,所以我们就不在这边进行资料增量的前置处理。

接着进行的是图片标签 (Labeling/Annotation) 的动作,这是一个很乏味的动作,主要就是把原始图片中要训练的图片标示出来,并说明标示物件标签,而把这些资讯存成文字档。光是标签就可以分成三类需要考虑的因素:

  1. 图片标注的类型 (Image Annotation Types):可以是边界框 (Bounding boxes),多边形分割 (Polygonal Segmentation),语义分割 (Semantic Segmentation),3D 长方体 (3D cuboids),关键点和界标 (Key-Point and Landmark),直线和样条 (Lines and Splines)。下图显示边界框与关键点和界标的图型。使用边界框来标注物件是很常见的标注方式,将目标物件用矩型标注出来,YOLOV3也是使用这种方式。

https://ithelp.ithome.com.tw/upload/images/20210912/2012951080AIf55DGN.png
图 1、 使用边界框来标注物件 (Original Photo by Patricia Jekki on Unsplash)

很明显的,使用关键点和界标的标注对於检测面部特徵、面部表情、情绪、人体部位和姿势很有用。

https://ithelp.ithome.com.tw/upload/images/20210912/20129510TX3JWOqvrE.jpg
图 2、 使用关键点和界标来标注物件 (Original Photo from COCO dataset)

  1. 图片标注的格式 (Image Annotation Formats):可以分成 COCO,Pascal VOC 与 YOLO 三种不同的格式。简单来区分是 COCO 使用的是 JSON 的格式;Pascal VOC 使用 XML 格式;而 YOLO 则是一般文字格式,可以说是类似 CSV 格式,只是都是以空白来进行不同栏位。以下分别是他们的简单样板。

COCO format

annotation{
"id" : int,
"image_id": int,
"category_id": int,
"segmentation": RLE or [polygon],
"area": float,
"bbox": [x,y,width,height],
"iscrowd": 0 or 1,
}
categories[{
"id": int,
"name": str,
"supercategory": str,
}]

Pascal VOC

<annotation> 
  <folder>Train</folder> 
  <filename>01.png</filename>      
  <path>/path/Train/01.png</path> 
  <source>  
    <database>Unknown</database> 
  </source>
  <size>  
    <width>224</width>  
    <height>224</height>  
    <depth>3</depth>   
  </size> 
  <segmented>0</segmented> 
  <object>  
    <name>36</name>  
    <pose>Frontal</pose>  
    <truncated>0</truncated>  
    <difficult>0</difficult>  
    <occluded>0</occluded>  
    <bndbox>   
      <xmin>90</xmin>   
      <xmax>190</xmax>   
      <ymin>54</ymin>   
      <ymax>70</ymax>  
    </bndbox> 
  </object>
</annotation>

而 YOLO 的格式如下所示,每一行代表一个物件,分别表示物件名称 (object-class),物件中心 x 位在整张图片宽 (image_width) 的比例,物件中心 y 位在整张图片高 (image_height) 的比例,物件宽度 (target_width) 占整张图片宽度 (image_width) 的比例,物件长度 (target_height) 占整张图片长度 (image_height) 的比例。物件中心点座标 (x,y),物件的

<object-class> <x_iw_ratio> <y_ih_ratio> <tw_iw_ratio> <th_ih_ratio>

两者的换算公式如下:

# Pascal VOC
ymin, xmin, ymax, xmax, image_w, image_h = PascalVOC

# 将 Pascal VOC 中的资料转换成 YOLO 格式 
(x_iw_ratio, y_ih_ratio) = ( ( (xmin + xmax) * 0.5 ) / image_w, ((ymin + ymax) * 0.5 ) / image_h)
tw_iw_ratio = (xmax - xmin) * 1. / image_w
th_ih_ratio = (ymax - ymin) * 1. / image_h
  1. 标签工具:标签工作可以简单的分成半自动跟手动,半自动的标签工具有:Anno-Mage,显示出来的自动标示功能还不错,只是已经 1,2 年没有继续维护了;而大多数是用手动工具 labelImg

这边就不介绍如何使用 labelImg,可以参阅 目标检测使用LabelImg标注VOC数据格式和YOLO数据格式——LabelImg使用详细教程,这边先测试当取得标签档时,如何确认标签档是否可以正确的在图片上生成边界框。

下图是我们标签了下方的两只鱼,而 YOLO 标签内容如下,通常我们不会把物件名称直接打出来,因为这只是对应之用,所以我们给定标签为 0。

00-frame-0001.txt

0 0.962963 0.447917 0.414815 0.137500
0 0.263889 0.422917 0.416667 0.122917

https://ithelp.ithome.com.tw/upload/images/20210912/20129510ydwT8TNrva.png
图 3、标签後的图片

接着我们试着根据 YOLO 的标签内容,将 YOLO 格式转换成边界框的左上角 (min_x, min_y) 和右下角 (max_x, max_y),重新画上边界框,以确保标签内容的正确性。

./utils/yoloDrawLabel.py

import cv2

# 设定输入与输出
inputLabelPath = '../labels/00-frame-0001.txt'
inputImgPath = '../images/00-frame-608x608-0001.jpg'
outputImgPath = '../labels/00-frame-608x608-0001.jpg'
# 图片大小固定为 608*608
img_w= img_h = 608
# 载入图片
cv2image = cv2.imread(inputImgPath)

with open(inputLabelPath) as f:
  for line in f:
    line = line.strip() # 删除多余的空白
    data = line.split() # 将 YOLO 一列的内容转成一维阵列
    # 将 YOLO 格式转换为边界框的左上角和右下角座标
    bbox_width = float(data[3]) * img_w
    bbox_height = float(data[4]) * img_h
    center_x = float(data[1]) * img_w
    center_y = float(data[2]) * img_h
    min_x, min_y = center_x - (bbox_width / 2), center_y - (bbox_height / 2)
    max_x, max_y = center_x + (bbox_width / 2), center_y + (bbox_height / 2)
    print(min_x,min_y,max_x,max_y)
    # 在图片上写上物件名称
    cv2.putText(cv2image, 'Altolamprologus compressiceps', (int(min_x), int(min_y-6)), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (255, 255, 255), 1, cv2.LINE_AA)
    # 画出边界框
    cv2.rectangle(cv2image, (int(min_x),int(min_y)), (int(max_x),int(max_y)), (0,255,255), 2)
    # 将档案另存新图片档
    cv2.imwrite(r'{}'.format(outputImgPath), cv2image)
  f.close()

下图为输出结果,可以确认 YOLO 文字档中的内容是正确的。

https://ithelp.ithome.com.tw/upload/images/20210912/20129510HJeCW3I2W8.jpg
图 4、读取 YOLO 文件档验证标签是否正确的图片

参考资料


<<:  Day 8 - 拯救落後的专案能撑一天是一天(後端篇)

>>:  新新新手阅读 Angular 文件 - Get data from a server(3) - Day12

[DAY23]安装PGAdmin(01)

直接安装postgres 选择电脑系统,我这边使用win10 按下紫字 选择最新版本 开始安装一直按...

Day 21 Arraylist

在Java程序设计中,有一个较为快速创造阵列的方法ArrayList,有别於固定大小的Array,A...

如何把Jcenter或macenCenter等网路开源依赖库搬迁至本地依赖

缘由: 因Jcenter将不再对一般客户端提供服务,官方建议将远程仓库迁移至mavenCenter,...

Windows影片损毁後影片档案如何修复?

影片损毁发生的原因很多,尤其是在视频拷贝和视频录制的过程中,意外总是偷偷的就发生了。一般情况下,一但...

DAY27-如何与人协同工作与好好沟通-实习生篇

所有的问题都不简单 在你所有认为很基本的问题,对实习生来说都不简单。想想我之所以会认为理所当然很简单...