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.

224 lines
10KB

  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=None):
  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, -3), 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. return im_array
  15. def get_label_arrays(labelNames, colors, fontSize=40, fontPath="platech.ttf"):
  16. font = ImageFont.truetype(fontPath, fontSize, encoding='utf-8')
  17. label_arraylist = []
  18. for i, label_name in enumerate(labelNames):
  19. color = colors[i % 20]
  20. label_arraylist.append(get_label_array(color, label_name, font, fontSize))
  21. return label_arraylist
  22. def draw_painting_joint(box, img, label_array, score=0.5, color=None, score_location="leftTop"):
  23. # 识别问题描述图片的高、宽
  24. lh, lw = label_array.shape[0:2]
  25. # 图片的长度和宽度
  26. imh, imw = img.shape[0:2]
  27. if not isinstance(box[0], (list, tuple, np.ndarray)):
  28. xc = int(box[0])
  29. yc = int(box[1])
  30. w = int(box[2])
  31. h = int(box[3])
  32. bw = int(w/2)
  33. bh = int(h/2)
  34. tl = (xc - bw, yc - bh)
  35. tr = (xc + bw, yc - bh)
  36. br = (xc + bw, yc + bh)
  37. bl = (xc - bw, yc + bh)
  38. box = [tl, tr, br, bl]
  39. # 框框左上的位置
  40. if score_location == 'leftTop':
  41. x0, y1 = box[0][0], box[0][1]
  42. # 框框左下的位置
  43. elif score_location == 'leftBottom':
  44. x0, y1 = box[3][0], box[3][1]
  45. else:
  46. x0, y1 = box[0][0], box[0][1]
  47. # x1 框框左上x位置 + 描述的宽
  48. # y0 框框左上y位置 - 描述的高
  49. x1, y0 = x0 + lw, y1 - lh
  50. # 如果y0小于0, 说明超过上边框
  51. if y0 < 0:
  52. y0 = 0
  53. # y1等于文字高度
  54. y1 = y0 + lh
  55. # 如果y1框框的高大于图片高度
  56. if y1 > imh:
  57. # y1等于图片高度
  58. y1 = imh
  59. # y0等于y1减去文字高度
  60. y0 = y1 - lh
  61. # 如果x0小于0
  62. if x0 < 0:
  63. x0 = 0
  64. x1 = x0 + lw
  65. if x1 > imw:
  66. x1 = imw
  67. x0 = x1 - lw
  68. img[y0:y1, x0:x1, :] = label_array
  69. pts_cls = [(x0, y0), (x1, y1)]
  70. # 把四边形的框画上
  71. # box_tl = font['boxLine_thickness'] or round(0.002 * (imh + imw) / 2) + 1
  72. box_tl = max(int(round(imw / 1920 * 3)), 1) or round(0.002 * (imh + imw) / 2) + 1
  73. '''
  74. 1. img(array) 为ndarray类型(可以为cv.imread)直接读取的数据
  75. 2. box(array):为所画多边形的顶点坐标
  76. 3. 所画四边形是否闭合,通常为True
  77. 4. color(tuple):BGR三个通道的值
  78. 5. thickness(int):画线的粗细
  79. 6. shift:顶点坐标中小数的位数
  80. '''
  81. box1 = np.asarray(box, np.int32)
  82. cv2.polylines(img, [box1], True, color, box_tl)
  83. # 把英文字符score画到类别旁边
  84. tl = max(int(round(imw / 1920 * 3)), 1) or round(0.002 * (imh + imw) / 2) + 1
  85. label = ' %.2f' % score
  86. tf = max(tl, 1)
  87. fontScale = float(format(imw / 1920 * 1.1, '.2f')) or tl * 0.33
  88. '''
  89. 1. text:要计算大小的文本内容,类型为字符串。
  90. 2. fontFace:字体类型,例如cv2.FONT_HERSHEY_SIMPLEX等。
  91. 3. fontScale:字体大小的缩放因子,例如1.2表示字体大小增加20%。
  92. 4. thickness:文本线条的粗细,以像素为单位。
  93. 5. (text_width, text_height):给定文本在指定字体、字体大小、线条粗细下所占用的像素宽度和高度。
  94. '''
  95. t_size = cv2.getTextSize(label, 0, fontScale=fontScale, thickness=tf)[0]
  96. # if socre_location=='leftTop':
  97. p1, p2 = (pts_cls[1][0], pts_cls[0][1]), (pts_cls[1][0] + t_size[0], pts_cls[1][1])
  98. '''
  99. 1. img:要绘制矩形的图像
  100. 2. pt1:矩形框的左上角坐标,可以是一个包含两个整数的元组或列表,例如(x1, y1)或[x1, y1]。
  101. 3. pt2:矩形框的右下角坐标,可以是一个包含两个整数的元组或列表,例如(x2, y2)或[x2, y2]。
  102. 4. color:矩形框的颜色,可以是一个包含三个整数的元组或列表,例如(255, 0, 0)表示蓝色,或一个标量值,例如255表示白色。颜色顺序为BGR。
  103. 5. thickness:线条的粗细,以像素为单位。如果为负值,则表示要绘制填充矩形。默认值为1。
  104. 6. lineType:线条的类型,可以是cv2.LINE_AA表示抗锯齿线条,或cv2.LINE_4表示4连通线条,或cv2.LINE_8表示8连通线条。默认值为cv2.LINE_8。
  105. 7. shift:坐标点小数点位数。默认值为0。
  106. '''
  107. cv2.rectangle(img, p1, p2, color, -1, cv2.LINE_AA)
  108. p3 = pts_cls[1][0], pts_cls[1][1] - (lh - t_size[1]) // 2
  109. '''
  110. 1. img:要在其上绘制文本的图像
  111. 2. text:要绘制的文本内容,类型为字符串
  112. 3. org:文本起始位置的坐标,可以是一个包含两个整数的元组或列表,例如(x, y)或[x, y]。
  113. 4. fontFace:字体类型,例如cv2.FONT_HERSHEY_SIMPLEX等。
  114. 5. fontScale:字体大小的缩放因子,例如1.2表示字体大小增加20%。
  115. 6. color:文本的颜色,可以是一个包含三个整数的元组或列表,例如(255, 0, 0)表示蓝色,或一个标量值,例如255表示白色。颜色顺序为BGR。
  116. 7. thickness:文本线条的粗细,以像素为单位。默认值为1。
  117. 8. lineType:线条的类型,可以是cv2.LINE_AA表示抗锯齿线条,或cv2.LINE_4表示4连通线条,或cv2.LINE_8表示8连通线条。默认值为cv2.LINE_8。
  118. 9. bottomLeftOrigin:文本起始位置是否为左下角。如果为True,则文本起始位置为左下角,否则为左上角。默认值为False。
  119. '''
  120. cv2.putText(img, label, p3, 0, fontScale, [225, 255, 255], thickness=tf, lineType=cv2.LINE_AA)
  121. return img, box
  122. # def draw_painting_joint(box,img,label_array,score=0.5,color=None,font={ 'line_thickness':None,'boxLine_thickness':None, 'fontSize':None},socre_location="leftTop"):
  123. # #如果box[0]不是list or 元组,则box是[ (x0,y0),(x1,y1),(x2,y2),(x3,y3)]四点格式
  124. # if isinstance(box[0], (list, tuple,np.ndarray ) ):
  125. # ###先把中文类别字体赋值到img中
  126. # lh, lw, lc = label_array.shape
  127. # imh, imw, imc = img.shape
  128. # if socre_location=='leftTop':
  129. # x0 , y1 = box[0][0],box[0][1]
  130. # elif socre_location=='leftBottom':
  131. # x0,y1=box[3][0],box[3][1]
  132. # else:
  133. # print('plot.py line217 ,label_location:%s not implemented '%( socre_location ))
  134. # sys.exit(0)
  135. #
  136. # x1 , y0 = x0 + lw , y1 - lh
  137. # if y0<0:y0=0;y1=y0+lh
  138. # if y1>imh: y1=imh;y0=y1-lh
  139. # if x0<0:x0=0;x1=x0+lw
  140. # if x1>imw:x1=imw;x0=x1-lw
  141. # img[y0:y1,x0:x1,:] = label_array
  142. # pts_cls=[(x0,y0),(x1,y1) ]
  143. #
  144. # #把四边形的框画上
  145. # box_tl= font['boxLine_thickness'] or round(0.002 * (imh + imw) / 2) + 1
  146. # cv2.polylines(img, [box], True,color , box_tl)
  147. #
  148. # ####把英文字符score画到类别旁边
  149. # tl = font['line_thickness'] or round(0.002*(imh+imw)/2)+1#line/font thickness
  150. # label = ' %.2f'%(score)
  151. # tf = max(tl , 1) # font thickness
  152. # fontScale = font['fontSize'] or tl * 0.33
  153. # t_size = cv2.getTextSize(label, 0, fontScale=fontScale , thickness=tf)[0]
  154. #
  155. #
  156. # #if socre_location=='leftTop':
  157. # p1,p2= (pts_cls[1][0], pts_cls[0][1]),(pts_cls[1][0]+t_size[0],pts_cls[1][1])
  158. # cv2.rectangle(img, p1 , p2, color, -1, cv2.LINE_AA)
  159. # p3 = pts_cls[1][0],pts_cls[1][1]-(lh-t_size[1])//2
  160. #
  161. # cv2.putText(img, label,p3, 0, fontScale, [225, 255, 255], thickness=tf, lineType=cv2.LINE_AA)
  162. # return img
  163. # else:####两点格式[x0,y0,x1,y1]
  164. # try:
  165. # box = [int(xx.cpu()) for xx in box]
  166. # except:
  167. # box=[ int(x) for x in box]
  168. # ###先把中文类别字体赋值到img中
  169. # lh, lw, lc = label_array.shape
  170. # imh, imw, imc = img.shape
  171. # if socre_location=='leftTop':
  172. # x0 , y1 = box[0:2]
  173. # elif socre_location=='leftBottom':
  174. # x0,y1=box[0],box[3]
  175. # else:
  176. # print('plot.py line217 ,socre_location:%s not implemented '%( socre_location ))
  177. # sys.exit(0)
  178. # x1 , y0 = x0 + lw , y1 - lh
  179. # if y0<0:y0=0;y1=y0+lh
  180. # if y1>imh: y1=imh;y0=y1-lh
  181. # if x0<0:x0=0;x1=x0+lw
  182. # if x1>imw:x1=imw;x0=x1-lw
  183. # img[y0:y1,x0:x1,:] = label_array
  184. #
  185. #
  186. #
  187. # ###把矩形框画上,指定颜色和线宽
  188. # tl = font['line_thickness'] or round(0.002 * (img.shape[0] + img.shape[1]) / 2) + 1 # line/font thickness
  189. # box_tl= font['boxLine_thickness'] or round(0.002 * (img.shape[0] + img.shape[1]) / 2) + 1
  190. # c1, c2 = (int(box[0]), int(box[1])), (int(box[2]), int(box[3]))
  191. # cv2.rectangle(img, c1, c2, color, thickness=box_tl, lineType=cv2.LINE_AA)
  192. #
  193. # ###把英文字符score画到类别旁边
  194. # label = ' %.2f'%(score)
  195. # tf = max(tl , 1) # font thickness
  196. # fontScale = font['fontSize'] or tl * 0.33
  197. # t_size = cv2.getTextSize(label, 0, fontScale=fontScale , thickness=tf)[0]
  198. #
  199. # if socre_location=='leftTop':
  200. # c2 = c1[0]+ lw + t_size[0], c1[1] - lh
  201. # cv2.rectangle(img, (int(box[0])+lw,int(box[1])) , c2, color, -1, cv2.LINE_AA) # filled
  202. # cv2.putText(img, label, (c1[0]+lw, c1[1] - (lh-t_size[1])//2 ), 0, fontScale, [225, 255, 255], thickness=tf, lineType=cv2.LINE_AA)
  203. # elif socre_location=='leftBottom':
  204. # c2 = box[0]+ lw + t_size[0], box[3] - lh
  205. # cv2.rectangle(img, (int(box[0])+lw,int(box[3])) , c2, color, -1, cv2.LINE_AA) # filled
  206. # cv2.putText(img, label, ( box[0] + lw, box[3] - (lh-t_size[1])//2 ), 0, fontScale, [225, 255, 255], thickness=tf, lineType=cv2.LINE_AA)
  207. #
  208. # #print('#####line224 fontScale:',fontScale,' thickness:',tf,' line_thickness:',font['line_thickness'],' boxLine thickness:',box_tl)
  209. # return img