东方耀AI技术分享

 找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
热搜: 活动 交友 discuz
查看: 14083|回复: 20

[课堂笔记] 目标检测之coco与voc格式的数据相互转换,并验证coco格式的...

[复制链接]

1365

主题

1856

帖子

1万

积分

管理员

Rank: 10Rank: 10Rank: 10

积分
14429
QQ
发表于 2020-12-1 15:58:52 | 显示全部楼层 |阅读模式
目标检测之coco与voc格式的数据相互转换,并验证coco格式的脚本




  1. # -*- coding: utf-8 -*-
  2. __author__ = u'江锦炬 微信:dfy_88888'
  3. __date__ = '2020/12/1 上午11:27'
  4. __product__ = 'PyCharm'
  5. __filename__ = '08_coco_to_voc'


  6. # import os, cv2, sys, shutil
  7. import cv2
  8. import shutil
  9. import glob
  10. import os
  11. from xml.dom.minidom import Document
  12. # 将coco和yolo格式的目标检测数据集转换为voc格式的,方便进行anchor的k-means聚类

  13. train_dir_coco = "/media/jiang/AI_DataSets/DataSets/person_vehicle_coco/person_vehicle_yolo_train"
  14. val_dir_coco = "/media/jiang/AI_DataSets/DataSets/person_vehicle_coco/person_vehicle_yolo_val"
  15. label_dict = {"0": "person", "1": "car", "2": "motorbike", "3": "bus", "4": "truck"}

  16. output_dir_voc = "/media/jiang/AI_DataSets/DataSets/person_vehicle_voc"


  17. def writexml(img_path, ori_hw, bboxes, xmlpath):
  18.     doc = Document()
  19.     # 根节点
  20.     annotation = doc.createElement('annotation')
  21.     doc.appendChild(annotation)

  22.     folder = doc.createElement('folder')
  23.     # 注意:widerface_voc voc格式数据的文件夹名字
  24.     folder_name = doc.createTextNode('person_vehicle_voc')
  25.     folder.appendChild(folder_name)
  26.     annotation.appendChild(folder)

  27.     filenamenode = doc.createElement('filename')
  28.     filename_name = doc.createTextNode(img_path)
  29.     filenamenode.appendChild(filename_name)
  30.     annotation.appendChild(filenamenode)

  31.     source = doc.createElement('source')
  32.     annotation.appendChild(source)

  33.     database = doc.createElement('database')
  34.     database.appendChild(doc.createTextNode('coco Database'))
  35.     source.appendChild(database)

  36.     annotation_s = doc.createElement('annotation')
  37.     annotation_s.appendChild(doc.createTextNode('jjj VOC2020'))
  38.     source.appendChild(annotation_s)

  39.     image = doc.createElement('image')
  40.     image.appendChild(doc.createTextNode('flickr'))
  41.     source.appendChild(image)

  42.     flickrid = doc.createElement('flickrid')
  43.     flickrid.appendChild(doc.createTextNode('-1'))
  44.     source.appendChild(flickrid)

  45.     owner = doc.createElement('owner')
  46.     annotation.appendChild(owner)

  47.     flickrid_o = doc.createElement('flickrid')
  48.     flickrid_o.appendChild(doc.createTextNode('jjj_88888'))
  49.     owner.appendChild(flickrid_o)

  50.     name_o = doc.createElement('name')
  51.     name_o.appendChild(doc.createTextNode('jjj_88888'))
  52.     owner.appendChild(name_o)

  53.     size = doc.createElement('size')
  54.     annotation.appendChild(size)

  55.     width = doc.createElement('width')
  56.     width.appendChild(doc.createTextNode(str(ori_hw[1])))
  57.     height = doc.createElement('height')
  58.     height.appendChild(doc.createTextNode(str(ori_hw[0])))
  59.     depth = doc.createElement('depth')
  60.     depth.appendChild(doc.createTextNode("3"))
  61.     size.appendChild(width)
  62.     size.appendChild(height)
  63.     size.appendChild(depth)

  64.     segmented = doc.createElement('segmented')
  65.     segmented.appendChild(doc.createTextNode('0'))
  66.     annotation.appendChild(segmented)

  67.     for i in range(len(bboxes)):
  68.         # bbox = ['person', 412, 157, 465, 295]
  69.         bbox = bboxes[i]
  70.         objects = doc.createElement('object')
  71.         annotation.appendChild(objects)

  72.         object_name = doc.createElement('name')
  73.         #
  74.         object_name.appendChild(doc.createTextNode(bbox[0]))
  75.         objects.appendChild(object_name)

  76.         pose = doc.createElement('pose')
  77.         pose.appendChild(doc.createTextNode('Unspecified'))
  78.         objects.appendChild(pose)

  79.         truncated = doc.createElement('truncated')
  80.         truncated.appendChild(doc.createTextNode('1'))
  81.         objects.appendChild(truncated)

  82.         difficult = doc.createElement('difficult')
  83.         difficult.appendChild(doc.createTextNode('0'))
  84.         objects.appendChild(difficult)

  85.         bndbox = doc.createElement('bndbox')
  86.         objects.appendChild(bndbox)
  87.         # xmin ymin 就是标记框 左上角的坐标
  88.         xmin = doc.createElement('xmin')
  89.         xmin.appendChild(doc.createTextNode(str(bbox[1])))
  90.         bndbox.appendChild(xmin)
  91.         ymin = doc.createElement('ymin')
  92.         ymin.appendChild(doc.createTextNode(str(bbox[2])))
  93.         bndbox.appendChild(ymin)
  94.         # xmax ymax 就是标记框 右下角的坐标
  95.         xmax = doc.createElement('xmax')
  96.         xmax.appendChild(doc.createTextNode(str(bbox[3])))
  97.         bndbox.appendChild(xmax)
  98.         ymax = doc.createElement('ymax')
  99.         ymax.appendChild(doc.createTextNode(str(bbox[4])))
  100.         bndbox.appendChild(ymax)

  101.     with open(xmlpath, 'w') as f:
  102.         f.write(doc.toprettyxml(indent=''))


  103. def convert_imgset(img_set_type, dir_coco):
  104.     """
  105.     转换数据集(WiderFace---> VOC)
  106.     :param img_set_type: train or val
  107.     :return:
  108.     """
  109.     img_num = len(glob.glob(os.path.join(dir_coco, "*.jpg")))
  110.     txt_label_num = len(glob.glob(os.path.join(dir_coco, "*.txt")))
  111.     assert img_num == txt_label_num, "必须一致!"
  112.     print("数据集:{};图片数量={};标签txt文件数:{}".format(img_set_type, img_num, txt_label_num))
  113.     output_set_txt = os.path.join(output_dir_voc, "ImageSets", "Main", "%s.txt" % img_set_type)
  114.     output_set_txt_writer = open(output_set_txt, "w")

  115.     for img_path in glob.glob(os.path.join(dir_coco, "*.jpg")):
  116.         shutil.copy2(img_path, os.path.join(output_dir_voc, "JPEGImages"))
  117.         ori_h, ori_w = cv2.imread(img_path).shape[:2]
  118.         img_name = img_path.strip().split("/")[-1].split(".")[0]
  119.         txt_path = img_path.strip().replace("jpg", "txt")
  120.         print("图片的宽={},高={},name={}, txt_path={}".format(ori_w, ori_h, img_name, txt_path))
  121.         output_set_txt_writer.write("%s\n" % img_name)
  122.         # os.path.join(output_dir_voc, "Annotations")
  123.         # "%d %.6f %.6f %.6f %.6f\n" % (class_id, cx, cy, w, h)
  124.         bboxes = []
  125.         with open(txt_path, "r") as f:
  126.             lines = f.readlines()
  127.             for line in lines:
  128.                 class_id, cx, cy, w, h = line.strip().split(" ")
  129.                 x1 = float(cx) - float(w) / 2
  130.                 x2 = float(cx) + float(w) / 2
  131.                 y1 = float(cy) - float(h) / 2
  132.                 y2 = float(cy) + float(h) / 2
  133.                 x1_int = int(x1 * ori_w)
  134.                 y1_int = int(y1 * ori_h)
  135.                 x2_int = int(x2 * ori_w)
  136.                 y2_int = int(y2 * ori_h)
  137.                 bbox = [label_dict[class_id], x1_int, y1_int, x2_int, y2_int]
  138.                 bboxes.append(bbox)

  139.         if len(bboxes) == 0:
  140.             print('txt的标注文件 没有任何目标类')
  141.             continue
  142.         print("该图片={}的所有box标注:{}".format(img_name, bboxes))
  143.         annotation_xml_path = os.path.join(output_dir_voc, "Annotations", "%s.xml" % img_name)
  144.         writexml(img_path, (ori_h, ori_w), bboxes, annotation_xml_path)
  145.         # assert 0 == 1, "停"
  146.     output_set_txt_writer.close()


  147. if __name__ == '__main__':
  148.     # convert_imgset('val', val_dir_coco)
  149.     convert_imgset('train', train_dir_coco)


复制代码



  1. # -*- coding: utf-8 -*-
  2. from __future__ import division, print_function
  3. __author__ = u'江锦炬 微信:dfy_88888'
  4. __date__ = '2020/11/3 下午4:04'
  5. __product__ = 'PyCharm'
  6. __filename__ = 'dfy_voc_2_yolo_format'

  7. import cv2
  8. import os
  9. import shutil
  10. import glob
  11. # import xml.etree.ElementTree as ET
  12. from xml.dom.minidom import parse
  13. import numpy as np
  14. import time
  15. import math
  16. import logging as log
  17. import glob
  18. from PIL import ImageFont
  19. from PIL import Image
  20. from PIL import ImageDraw

  21. fontC = ImageFont.truetype("./Font/platech.ttf", 16, 0)

  22. # 打上boundingbox和标签
  23. def drawRectBox(image, rect, addText, color=(0, 0, 255)):
  24.     cv2.rectangle(image, (int(rect[0]), int(rect[1])), (int(rect[2]), int(rect[3])), color, 2,
  25.                   cv2.LINE_AA)
  26.     # 这个矩形是 文本的边框  高度=18 宽度=115  -1是填充?  红色底
  27.     cv2.rectangle(image, (int(rect[0] - 1), int(rect[1]) - 18), (int(rect[0] + 115), int(rect[1])), color, -1,
  28.                   cv2.LINE_AA)

  29.     img = Image.fromarray(image)
  30.     draw = ImageDraw.Draw(img)
  31.     # draw.text((int(rect[0]+1), int(rect[1]-16)), addText.decode("utf-8"), (255, 255, 255), font=fontC)
  32.     # 字体颜色是白色
  33.     draw.text((int(rect[0] + 1), int(rect[1] - 16)), addText, (255, 255, 255), font=fontC)
  34.     imagex = np.array(img)

  35.     return imagex


  36. voc_imgs_dir = "/media/jiang/AI_DataSets/DataSets/person_vehicle_voc/JPEGImages"

  37. voc_annotations = "/media/jiang/AI_DataSets/DataSets/person_vehicle_voc/Annotations"


  38. output_dir = "/media/jiang/AI_DataSets/DataSets/person_vehicle_voc/temp"
  39. # 需要一张一张的检查啊
  40. # yolo 格式: .jpg  .txt  train.txt  val.txt
  41. label_dict = {"0": "person", "1": "car", "2": "motorbike", "3": "bus", "4": "truck"}

  42. total_img_num = len(glob.glob(os.path.join(voc_imgs_dir, "*.jpg")))
  43. print("共有多少张jpg图片:", total_img_num)
  44. total_xml_anno_num = len(glob.glob(os.path.join(voc_annotations, "*.xml")))
  45. print("共有多少个xml的标注:", total_xml_anno_num)

  46. assert total_img_num == total_xml_anno_num, "图片和xml标注数量必须一致!"
  47. # 共有多少张jpg图片: 2059
  48. # 共有多少个xml的标注: 2059

  49. for idx, img_path in enumerate(glob.glob(os.path.join(voc_imgs_dir, "*.jpg"))):
  50.     ori_img = cv2.imread(img_path)
  51.     ori_h, ori_w = ori_img.shape[:2]
  52.     ori_img_name = img_path.strip().split("/")[-1].split(".")[0]
  53.     # print("图片链接:", img_path, ori_img_name)
  54.     xml_annotation_path = os.path.join(voc_annotations, "%s.xml" % ori_img_name)
  55.     if not os.path.isfile(xml_annotation_path):
  56.         print("找不到xml标注啊:", xml_annotation_path)
  57.         continue
  58.     else:
  59.         pass
  60.         # print("找到了xml标注:", xml_annotation_path)
  61.     # 读取文件
  62.     # xml_annotation_path = "*.xml"  from xml.dom.minidom import parse
  63.     dom = parse(xml_annotation_path)
  64.     # 获取文档元素对象
  65.     data = dom.documentElement
  66.     objs = data.getElementsByTagName('object')
  67.     shutil.copy2(img_path, output_dir)
  68.     new_text_file_writer = open(os.path.join(output_dir, "%s.txt" % ori_img_name), "w")
  69.     # 0 0.622266 0.552778 0.289844 0.483333  fire
  70.     # # <x_center> <y_center> <width> <height>
  71.     for obj in objs:
  72.         # 获取标签中内容
  73.         name = obj.getElementsByTagName('name')[0].childNodes[0].nodeValue
  74.         x1 = obj.getElementsByTagName('bndbox')[0].getElementsByTagName('xmin')[0].childNodes[0].nodeValue
  75.         y1 = obj.getElementsByTagName('bndbox')[0].getElementsByTagName('ymin')[0].childNodes[0].nodeValue
  76.         x2 = obj.getElementsByTagName('bndbox')[0].getElementsByTagName('xmax')[0].childNodes[0].nodeValue
  77.         y2 = obj.getElementsByTagName('bndbox')[0].getElementsByTagName('ymax')[0].childNodes[0].nodeValue
  78.         # print('name:', name, ', box:[{},{},{},{}]'.format(x1, y1, x2, y2))
  79.         rect_box = [int(x1), int(y1), int(x2), int(y2)]

  80.         # ori_img = drawRectBox(ori_img, rect_fire_smoke, name, color=(0, 0, 255))
  81.         box_width = max(0, (int(x2) - int(x1)) * 1.0 / ori_w)
  82.         box_height = max(0, (int(y2) - int(y1)) * 1.0 / ori_h)
  83.         box_cx = max(0, (int(x2) + int(x1)) / (ori_w * 2.0))
  84.         box_cy = max(0, (int(y2) + int(y1)) / (ori_h * 2.0))

  85.         if label_dict["0"] == name:
  86.             new_text_file_writer.write("0 %.6f %.6f %.6f %.6f\n" % (box_cx, box_cy, box_width, box_height))
  87.         elif label_dict["1"] == name:
  88.             new_text_file_writer.write("1 %.6f %.6f %.6f %.6f\n" % (box_cx, box_cy, box_width, box_height))
  89.         elif label_dict["2"] == name:
  90.             new_text_file_writer.write("2 %.6f %.6f %.6f %.6f\n" % (box_cx, box_cy, box_width, box_height))
  91.         elif label_dict["3"] == name:
  92.             new_text_file_writer.write("3 %.6f %.6f %.6f %.6f\n" % (box_cx, box_cy, box_width, box_height))
  93.         elif label_dict["4"] == name:
  94.             new_text_file_writer.write("4 %.6f %.6f %.6f %.6f\n" % (box_cx, box_cy, box_width, box_height))

  95.     new_text_file_writer.close()

  96.     # cv2.imshow("ori", ori_img)
  97.     # cv2.waitKey(0)
  98.     # if idx == 9:
  99.     #     assert 0 == 1, "停"




复制代码



  1. # -*- coding: utf-8 -*-
  2. __author__ = u'江锦炬 微信:dfy_88888'
  3. __date__ = '2020/11/3 下午2:52'
  4. __product__ = 'PyCharm'
  5. __filename__ = 'dfy_demo01'

  6. import cv2
  7. import os
  8. import glob

  9. import cv2
  10. import os
  11. import shutil
  12. # import xml.etree.ElementTree as ET
  13. from xml.dom.minidom import parse
  14. import numpy as np
  15. import time
  16. import math
  17. import logging as log
  18. import glob
  19. from PIL import ImageFont
  20. from PIL import Image
  21. from PIL import ImageDraw

  22. fontC = ImageFont.truetype("./Font/platech.ttf", 16, 0)

  23. # 打上boundingbox和标签
  24. def drawRectBox(image, rect, addText, color=(0, 0, 255)):
  25.     cv2.rectangle(image, (int(rect[0]), int(rect[1])), (int(rect[2]), int(rect[3])), color, 2,
  26.                   cv2.LINE_AA)
  27.     # 这个矩形是 文本的边框  高度=18 宽度=115  -1是填充?  红色底
  28.     cv2.rectangle(image, (int(rect[0] - 1), int(rect[1]) - 18), (int(rect[0] + 115), int(rect[1])), color, -1,
  29.                   cv2.LINE_AA)

  30.     img = Image.fromarray(image)
  31.     draw = ImageDraw.Draw(img)
  32.     # draw.text((int(rect[0]+1), int(rect[1]-16)), addText.decode("utf-8"), (255, 255, 255), font=fontC)
  33.     # 字体颜色是白色
  34.     draw.text((int(rect[0] + 1), int(rect[1] - 16)), addText, (255, 255, 255), font=fontC)
  35.     imagex = np.array(img)

  36.     return imagex


  37. # 验证一下 yolo格式的标注数据  数据来源:yolo-mark标注的 或 其他格式转换过来的  *.jpg  *.txt
  38. input_imgs_dir = "/media/jiang/AI_DataSets/DataSets/person_vehicle_voc/temp"

  39. # label_dict = {"0": "fire", "1": "smoke"}
  40. label_dict = {"0": "person", "1": "car", "2": "motorbike", "3": "bus", "4": "truck"}
  41. img_num = len(glob.glob(os.path.join(input_imgs_dir, "*.jpg")))
  42. txt_num = len(glob.glob(os.path.join(input_imgs_dir, "*.txt")))
  43. assert img_num == txt_num, "图片和标注文件个数必须一致!"

  44. for idx, img_path in enumerate(glob.glob(os.path.join(input_imgs_dir, "*.jpg"))):
  45.     ori_img = cv2.imread(img_path)
  46.     ori_h, ori_w = ori_img.shape[:2]
  47.     txt_file_path = img_path.strip().split(".")[0] + ".txt"
  48.     ori_img_name = img_path.strip().split("/")[-1].split(".")[0]
  49.     with open(txt_file_path, "r") as f:
  50.         lines = f.readlines()
  51.         for line in lines:
  52.             class_id, cx, cy, w, h = line.strip().split()
  53.             cx = float(cx) * ori_w
  54.             cy = float(cy) * ori_h
  55.             w = float(w) * ori_w
  56.             h = float(h) * ori_h

  57.             x1 = int(cx - w / 2)
  58.             y1 = int(cy - h / 2)
  59.             x2 = int(cx + w / 2)
  60.             y2 = int(cy + h / 2)
  61.             rect_fire_smoke = [x1, y1, x2, y2]
  62.             ori_img = drawRectBox(ori_img, rect_fire_smoke, label_dict[class_id], color=(0, 0, 255))
  63.             # cv2.rectangle(ori_img, (x1, y1), (x2, y2), (0, 0, 255), thickness=2)
  64.     print("当前正在查看的图片:", ori_img_name)
  65.     cv2.imshow("ori", ori_img)
  66.     cv2.waitKey(0)

  67.     if idx == 300:
  68.         assert 0 == 1, "停"

复制代码









让天下人人学会人工智能!人工智能的前景一片大好!
回复

使用道具 举报

0

主题

102

帖子

208

积分

中级会员

Rank: 3Rank: 3

积分
208
发表于 2020-12-5 21:25:30 | 显示全部楼层
感谢分享
回复

使用道具 举报

0

主题

102

帖子

208

积分

中级会员

Rank: 3Rank: 3

积分
208
发表于 2020-12-5 21:26:26 | 显示全部楼层
干货满满
回复

使用道具 举报

0

主题

102

帖子

208

积分

中级会员

Rank: 3Rank: 3

积分
208
发表于 2020-12-5 23:40:36 | 显示全部楼层
566666666666666666666
回复

使用道具 举报

0

主题

102

帖子

208

积分

中级会员

Rank: 3Rank: 3

积分
208
发表于 2020-12-6 09:15:38 | 显示全部楼层
Python高级编程与AI数据分析课程
回复

使用道具 举报

0

主题

102

帖子

208

积分

中级会员

Rank: 3Rank: 3

积分
208
发表于 2020-12-6 09:18:33 | 显示全部楼层
Python高级编程与AI数据分析课程
回复

使用道具 举报

0

主题

102

帖子

208

积分

中级会员

Rank: 3Rank: 3

积分
208
发表于 2020-12-6 09:19:16 | 显示全部楼层
Python高级编程与AI数据分析课程
回复

使用道具 举报

0

主题

102

帖子

208

积分

中级会员

Rank: 3Rank: 3

积分
208
发表于 2020-12-6 09:20:34 | 显示全部楼层
Python高级编程与AI数据分析课程
回复

使用道具 举报

0

主题

102

帖子

208

积分

中级会员

Rank: 3Rank: 3

积分
208
发表于 2020-12-6 09:25:47 | 显示全部楼层

笔记写的挺好的,点个赞
回复

使用道具 举报

0

主题

102

帖子

208

积分

中级会员

Rank: 3Rank: 3

积分
208
发表于 2020-12-6 09:29:28 | 显示全部楼层

笔记写的挺好的,点个赞
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|小黑屋|人工智能工程师的摇篮 ( 湘ICP备2020019608号-1 )

GMT+8, 2024-4-18 13:05 , Processed in 0.182129 second(s), 20 queries .

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表