You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

137 lines
6.5KB

  1. import cv2
  2. import numpy as np
  3. from PIL import Image, ImageDraw, ImageFont
  4. def get_label_array(color=None, label=None, font=None, fontSize=40):
  5. x, y, width, height = font.getbbox(label)
  6. text_image = np.zeros((height, width, 3), dtype=np.uint8)
  7. text_image = Image.fromarray(text_image)
  8. draw = ImageDraw.Draw(text_image)
  9. draw.rectangle((0, 0, width, height), fill=tuple(color))
  10. draw.text((0, -1), label, fill=(255, 255, 255), font=font)
  11. im_array = np.asarray(text_image)
  12. # scale = fontSize / height
  13. # im_array = cv2.resize(im_array, (0, 0), fx=scale, fy=scale)
  14. scale = height / fontSize
  15. im_array = cv2.resize(im_array, (0, 0), fx=scale, fy=scale)
  16. return im_array
  17. def get_label_arrays(labelNames, colors, fontSize=40, fontPath="platech.ttf"):
  18. font = ImageFont.truetype(fontPath, fontSize, encoding='utf-8')
  19. label_arraylist = [get_label_array(colors[i % 20], label_name, font, fontSize) for i, label_name in
  20. enumerate(labelNames)]
  21. return label_arraylist
  22. def xywh2xyxy(box):
  23. if not isinstance(box[0], (list, tuple, np.ndarray)):
  24. xc, yc, w, h = int(box[0]), int(box[1]), int(box[2]), int(box[3])
  25. bw, bh = int(w / 2), int(h / 2)
  26. lt, yt, rt, yr = xc - bw, yc - bh, xc + bw, yc + bh
  27. box = [(lt, yt), (rt, yt), (rt, yr), (lt, yr)]
  28. return box
  29. def xywh2xyxy2(param):
  30. if not isinstance(param[0], (list, tuple, np.ndarray)):
  31. xc, yc, x2, y2 = int(param[0]), int(param[1]), int(param[2]), int(param[3])
  32. return [(xc, yc), (x2, yc), (x2, y2), (xc, y2)], float(param[4]), int(param[5])
  33. # bw, bh = int(w / 2), int(h / 2)
  34. # lt, yt, rt, yr = xc - bw, yc - bh, xc + bw, yc + bh
  35. # return [(lt, yt), (rt, yt), (rt, yr), (lt, yr)]
  36. return np.asarray(param[0][0:4], np.int32), float(param[1]), int(param[2])
  37. def draw_painting_joint(box, img, label_array, score=0.5, color=None, config=None):
  38. # 识别问题描述图片的高、宽
  39. lh, lw = label_array.shape[0:2]
  40. # 图片的长度和宽度
  41. imh, imw = img.shape[0:2]
  42. box = xywh2xyxy(box)
  43. # 框框左上的位置
  44. x0, y1 = box[0][0], box[0][1]
  45. # if score_location == 'leftTop':
  46. # x0, y1 = box[0][0], box[0][1]
  47. # # 框框左下的位置
  48. # elif score_location == 'leftBottom':
  49. # x0, y1 = box[3][0], box[3][1]
  50. # else:
  51. # x0, y1 = box[0][0], box[0][1]
  52. # x1 框框左上x位置 + 描述的宽
  53. # y0 框框左上y位置 - 描述的高
  54. x1, y0 = x0 + lw, y1 - lh
  55. # 如果y0小于0, 说明超过上边框
  56. if y0 < 0:
  57. y0 = 0
  58. # y1等于文字高度
  59. y1 = y0 + lh
  60. # 如果y1框框的高大于图片高度
  61. if y1 > imh:
  62. # y1等于图片高度
  63. y1 = imh
  64. # y0等于y1减去文字高度
  65. y0 = y1 - lh
  66. # 如果x0小于0
  67. if x0 < 0:
  68. x0 = 0
  69. x1 = x0 + lw
  70. if x1 > imw:
  71. x1 = imw
  72. x0 = x1 - lw
  73. # box_tl = max(int(round(imw / 1920 * 3)), 1) or round(0.002 * (imh + imw) / 2) + 1
  74. '''
  75. 1. img(array) 为ndarray类型(可以为cv.imread)直接读取的数据
  76. 2. box(array):为所画多边形的顶点坐标
  77. 3. 所画四边形是否闭合,通常为True
  78. 4. color(tuple):BGR三个通道的值
  79. 5. thickness(int):画线的粗细
  80. 6. shift:顶点坐标中小数的位数
  81. '''
  82. tl = config[0]
  83. box1 = np.asarray(box, np.int32)
  84. cv2.polylines(img, [box1], True, color, tl)
  85. img[y0:y1, x0:x1, :] = label_array
  86. pts_cls = [(x0, y0), (x1, y1)]
  87. # 把英文字符score画到类别旁边
  88. # tl = max(int(round(imw / 1920 * 3)), 1) or round(0.002 * (imh + imw) / 2) + 1
  89. label = ' %.2f' % score
  90. # tf = max(tl, 1)
  91. # fontScale = float(format(imw / 1920 * 1.1, '.2f')) or tl * 0.33
  92. # fontScale = tl * 0.33
  93. '''
  94. 1. text:要计算大小的文本内容,类型为字符串。
  95. 2. fontFace:字体类型,例如cv2.FONT_HERSHEY_SIMPLEX等。
  96. 3. fontScale:字体大小的缩放因子,例如1.2表示字体大小增加20%。
  97. 4. thickness:文本线条的粗细,以像素为单位。
  98. 5. (text_width, text_height):给定文本在指定字体、字体大小、线条粗细下所占用的像素宽度和高度。
  99. '''
  100. # t_size = cv2.getTextSize(label, 0, fontScale=fontScale, thickness=tf)[0]
  101. t_size = (config[1], config[2])
  102. # if socre_location=='leftTop':
  103. p1, p2 = (pts_cls[1][0], pts_cls[0][1]), (pts_cls[1][0] + t_size[0], pts_cls[1][1])
  104. '''
  105. 1. img:要绘制矩形的图像
  106. 2. pt1:矩形框的左上角坐标,可以是一个包含两个整数的元组或列表,例如(x1, y1)或[x1, y1]。
  107. 3. pt2:矩形框的右下角坐标,可以是一个包含两个整数的元组或列表,例如(x2, y2)或[x2, y2]。
  108. 4. color:矩形框的颜色,可以是一个包含三个整数的元组或列表,例如(255, 0, 0)表示蓝色,或一个标量值,例如255表示白色。颜色顺序为BGR。
  109. 5. thickness:线条的粗细,以像素为单位。如果为负值,则表示要绘制填充矩形。默认值为1。
  110. 6. lineType:线条的类型,可以是cv2.LINE_AA表示抗锯齿线条,或cv2.LINE_4表示4连通线条,或cv2.LINE_8表示8连通线条。默认值为cv2.LINE_8。
  111. 7. shift:坐标点小数点位数。默认值为0。
  112. '''
  113. cv2.rectangle(img, p1, p2, color, -1, cv2.LINE_AA)
  114. p3 = pts_cls[1][0], pts_cls[1][1] - (lh - t_size[1]) // 2
  115. '''
  116. 1. img:要在其上绘制文本的图像
  117. 2. text:要绘制的文本内容,类型为字符串
  118. 3. org:文本起始位置的坐标,可以是一个包含两个整数的元组或列表,例如(x, y)或[x, y]。
  119. 4. fontFace:字体类型,例如cv2.FONT_HERSHEY_SIMPLEX等。
  120. 5. fontScale:字体大小的缩放因子,例如1.2表示字体大小增加20%。
  121. 6. color:文本的颜色,可以是一个包含三个整数的元组或列表,例如(255, 0, 0)表示蓝色,或一个标量值,例如255表示白色。颜色顺序为BGR。
  122. 7. thickness:文本线条的粗细,以像素为单位。默认值为1。
  123. 8. lineType:线条的类型,可以是cv2.LINE_AA表示抗锯齿线条,或cv2.LINE_4表示4连通线条,或cv2.LINE_8表示8连通线条。默认值为cv2.LINE_8。
  124. 9. bottomLeftOrigin:文本起始位置是否为左下角。如果为True,则文本起始位置为左下角,否则为左上角。默认值为False。
  125. '''
  126. cv2.putText(img, label, p3, 0, config[3], [225, 255, 255], thickness=config[4], lineType=cv2.LINE_AA)
  127. return img, box