visualizer.py 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. # -*- coding: UTF-8 -*-
  2. ################################################################################
  3. #
  4. # Copyright (c) 2024 Baidu.com, Inc. All Rights Reserved
  5. #
  6. ################################################################################
  7. """
  8. Author: PaddlePaddle Authors
  9. """
  10. import os
  11. import numpy as np
  12. import json
  13. from pathlib import Path
  14. from PIL import Image, ImageDraw, ImageFont
  15. from pycocotools.coco import COCO
  16. from ......utils.fonts import PINGFANG_FONT_FILE_PATH
  17. from ......utils import logging
  18. def colormap(rgb=False):
  19. """
  20. Get colormap
  21. The code of this function is copied from https://github.com/facebookresearch/Detectron/blob/main/detectron/\
  22. utils/colormap.py
  23. """
  24. color_list = np.array([
  25. 0xFF, 0x00, 0x00, 0xCC, 0xFF, 0x00, 0x00, 0xFF, 0x66, 0x00, 0x66, 0xFF,
  26. 0xCC, 0x00, 0xFF, 0xFF, 0x4D, 0x00, 0x80, 0xff, 0x00, 0x00, 0xFF, 0xB2,
  27. 0x00, 0x1A, 0xFF, 0xFF, 0x00, 0xE5, 0xFF, 0x99, 0x00, 0x33, 0xFF, 0x00,
  28. 0x00, 0xFF, 0xFF, 0x33, 0x00, 0xFF, 0xff, 0x00, 0x99, 0xFF, 0xE5, 0x00,
  29. 0x00, 0xFF, 0x1A, 0x00, 0xB2, 0xFF, 0x80, 0x00, 0xFF, 0xFF, 0x00, 0x4D
  30. ]).astype(np.float32)
  31. color_list = (color_list.reshape((-1, 3)))
  32. if not rgb:
  33. color_list = color_list[:, ::-1]
  34. return color_list.astype('int32')
  35. def font_colormap(color_index):
  36. """
  37. Get font color according to the index of colormap
  38. """
  39. dark = np.array([0x14, 0x0E, 0x35])
  40. light = np.array([0xFF, 0xFF, 0xFF])
  41. light_indexs = [0, 3, 4, 8, 9, 13, 14, 18, 19]
  42. if color_index in light_indexs:
  43. return light.astype('int32')
  44. else:
  45. return dark.astype('int32')
  46. def draw_bbox(image, coco_info: COCO, img_id):
  47. """
  48. Draw bbox on image
  49. """
  50. try:
  51. image_info = coco_info.loadImgs(img_id)[0]
  52. font_size = int(0.024 * int(image_info['width'])) + 2
  53. except:
  54. font_size = 12
  55. font = ImageFont.truetype(
  56. PINGFANG_FONT_FILE_PATH, font_size, encoding="utf-8")
  57. image = image.convert('RGB')
  58. draw = ImageDraw.Draw(image)
  59. image_size = image.size
  60. width = int(max(image_size) * 0.005)
  61. catid2color = {}
  62. catid2fontcolor = {}
  63. catid_num_dict = {}
  64. color_list = colormap(rgb=True)
  65. annotations = coco_info.loadAnns(coco_info.getAnnIds(imgIds=img_id))
  66. for ann in annotations:
  67. catid = ann['category_id']
  68. catid_num_dict[catid] = catid_num_dict.get(catid, 0) + 1
  69. for i, (catid, _) in enumerate(
  70. sorted(
  71. catid_num_dict.items(), key=lambda x: x[1], reverse=True)):
  72. if catid not in catid2color:
  73. color_index = i % len(color_list)
  74. catid2color[catid] = color_list[color_index]
  75. catid2fontcolor[catid] = font_colormap(color_index)
  76. for ann in annotations:
  77. catid, bbox = ann['category_id'], ann['bbox']
  78. color = tuple(catid2color[catid])
  79. font_color = tuple(catid2fontcolor[catid])
  80. if len(bbox) == 4:
  81. # draw bbox
  82. xmin, ymin, w, h = bbox
  83. xmax = xmin + w
  84. ymax = ymin + h
  85. draw.line(
  86. [(xmin, ymin), (xmin, ymax), (xmax, ymax), (xmax, ymin),
  87. (xmin, ymin)],
  88. width=width,
  89. fill=color)
  90. elif len(bbox) == 8:
  91. x1, y1, x2, y2, x3, y3, x4, y4 = bbox
  92. draw.line(
  93. [(x1, y1), (x2, y2), (x3, y3), (x4, y4), (x1, y1)],
  94. width=width,
  95. fill=color)
  96. xmin = min(x1, x2, x3, x4)
  97. ymin = min(y1, y2, y3, y4)
  98. else:
  99. logging.info('Error: The shape of bbox must be [M, 4] or [M, 8]!')
  100. # draw label
  101. label = coco_info.loadCats(catid)[0]['name']
  102. text = "{}".format(label)
  103. tw, th = draw.textsize(text, font=font)
  104. if ymin < th:
  105. draw.rectangle(
  106. [(xmin, ymin), (xmin + tw + 4, ymin + th + 1)], fill=color)
  107. draw.text((xmin + 2, ymin - 2), text, fill=font_color, font=font)
  108. else:
  109. draw.rectangle(
  110. [(xmin, ymin - th), (xmin + tw + 4, ymin + 1)], fill=color)
  111. draw.text(
  112. (xmin + 2, ymin - th - 2), text, fill=font_color, font=font)
  113. return image