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.

drownUtils.py 9.0KB

1 year ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. import numpy as np
  2. import time,cv2
  3. def ms(t1,t0):
  4. return (t1-t0)*1000.0
  5. def center_coordinate(boundbxs):
  6. '''
  7. 输入:两个对角坐标xyxy
  8. 输出:矩形框重点坐标xy
  9. '''
  10. boundbxs_x1=boundbxs[0]
  11. boundbxs_y1=boundbxs[1]
  12. boundbxs_x2=boundbxs[2]
  13. boundbxs_y2=boundbxs[3]
  14. center_x=0.5*(boundbxs_x1+boundbxs_x2)
  15. center_y=0.5*(boundbxs_y1+boundbxs_y2)
  16. return center_x,center_y
  17. def fourcorner_coordinate(boundbxs):
  18. '''
  19. 输入:两个对角坐标xyxy
  20. 输出:矩形框四个角点坐标,以contours顺序。
  21. '''
  22. boundbxs_x1=boundbxs[0]
  23. boundbxs_y1=boundbxs[1]
  24. boundbxs_x2=boundbxs[2]
  25. boundbxs_y2=boundbxs[3]
  26. wid=boundbxs_x2-boundbxs_x1
  27. hei=boundbxs_y2-boundbxs_y1
  28. boundbxs_x3=boundbxs_x1+wid
  29. boundbxs_y3=boundbxs_y1
  30. boundbxs_x4=boundbxs_x1
  31. boundbxs_y4 = boundbxs_y1+hei
  32. contours_rec=[[boundbxs_x1,boundbxs_y1],[boundbxs_x3,boundbxs_y3],[boundbxs_x2,boundbxs_y2],[boundbxs_x4,boundbxs_y4]]
  33. return contours_rec
  34. def remove_simivalue(list1,list2):
  35. '''
  36. 将list1中属于list2的元素都删除。
  37. 输入:两个嵌套列表
  38. 返回:嵌套列表
  39. '''
  40. list33=list1.copy()
  41. for i in range(len(list1)):
  42. for j in range(len(list2)):
  43. if list2[j] == list1[i]:
  44. # list33.pop(list1[i])
  45. list33.remove(list1[i])
  46. return list33
  47. def remove_sameeleme_inalist(list3):
  48. '''
  49. 将list3中重复嵌套列表元素删除。
  50. 输入:嵌套列表
  51. 返回:嵌套列表
  52. '''
  53. list3=list3
  54. list4=[]
  55. list4.append(list3[0])
  56. for dict in list3:
  57. k=0
  58. for item in list4:
  59. if dict!=item:
  60. k=k+1
  61. else:
  62. break
  63. if k==len(list4):
  64. list4.append(dict)
  65. return list4
  66. def order_points(pts):
  67. ''' sort rectangle points by clockwise '''
  68. sort_x = pts[np.argsort(pts[:, 0]), :]
  69. Left = sort_x[:2, :]
  70. Right = sort_x[2:, :]
  71. # Left sort
  72. Left = Left[np.argsort(Left[:, 1])[::-1], :]
  73. # Right sort
  74. Right = Right[np.argsort(Right[:, 1]), :]
  75. return np.concatenate((Left, Right), axis=0)
  76. def mixDrowing_water_postprocess(preds,_mask_cv,pars ):
  77. '''考虑船上人过滤'''
  78. '''输入:落水人员的结果(类别+坐标)、原图、mask图像
  79. 过程:获得mask的轮廓,判断人员是否在轮廓内。
  80. 在,则保留且绘制;不在,舍弃。
  81. 返回:最终绘制的结果图、最终落水人员(坐标、类别、置信度),
  82. '''
  83. '''1、最大分割水域作为判断依据'''
  84. #zoom_factor=4 #缩小因子设置为4,考虑到numpy中分别遍历xy进行缩放耗时大。
  85. original_height = _mask_cv.shape[0]
  86. original_width=_mask_cv.shape[1]
  87. zoom_factor = original_width/480.0
  88. zoom_height=int(original_height/zoom_factor)
  89. zoom_width=int(original_width/zoom_factor)
  90. _mask_cv = cv2.resize(_mask_cv, (zoom_width,zoom_height)) #缩小原图,宽在前,高在后
  91. t4 = time.time()
  92. img_gray = cv2.cvtColor(_mask_cv, cv2.COLOR_BGR2GRAY) if len(_mask_cv.shape)==3 else _mask_cv #
  93. t5 = time.time()
  94. contours, thresh = cv2.threshold(img_gray, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
  95. # 寻找轮廓(多边界)
  96. contours, hierarchy = cv2.findContours(thresh, cv2.RETR_LIST, 2)
  97. contour_info = []
  98. for c in contours:
  99. contour_info.append((
  100. c,
  101. cv2.isContourConvex(c),
  102. cv2.contourArea(c),
  103. ))
  104. contour_info = sorted(contour_info, key=lambda c: c[2], reverse=True)
  105. t6 = time.time()
  106. '''新增模块::如果水域为空,则返回原图、无落水人员等。'''
  107. if contour_info==[]:
  108. # final_img=_img_cv
  109. final_head_person_filterwater=[]
  110. timeInfos=0
  111. # return final_img, final_head_person_filterwater
  112. return final_head_person_filterwater,timeInfos
  113. else:
  114. max_contour = contour_info[0]
  115. max_contour=max_contour[0]*zoom_factor# contours恢复原图尺寸
  116. max_contour = max_contour.astype(np.int32)
  117. #print(max_contour)
  118. t7 = time.time()
  119. '''2.1、preds中head+person取出,boat取出。'''
  120. init_head_person=[]
  121. init_boat = []
  122. for i in range(len(preds)):
  123. if preds[i][5]==0 or preds[i][5]==1:
  124. init_head_person.append(preds[i])
  125. else:
  126. init_boat.append(preds[i])
  127. t8 = time.time()
  128. '''新增模块:2.2、preds中head+person取出,过滤掉head与person中指向同一人的部分,保留同一人的person标签。'''
  129. init_head=[]
  130. init_person=[]
  131. #head与person标签分开
  132. for i in range(len(init_head_person)):
  133. if init_head_person[i][5]==0:
  134. init_head.append(init_head_person[i])
  135. else:
  136. init_person.append(init_head_person[i])
  137. # person的框形成contours
  138. person_contour=[]
  139. for i in range(len(init_person)):
  140. boundbxs_temp=[init_person[i][0],init_person[i][1],init_person[i][2],init_person[i][3]]
  141. contour_temp_person=fourcorner_coordinate(boundbxs_temp) #得到person预测框的顺序contour
  142. contour_temp_person=np.array(contour_temp_person)
  143. contour_temp_person=np.float32(contour_temp_person)
  144. person_contour.append(np.array(contour_temp_person))
  145. # head是否在person的contours内,在说明是同一人,过滤掉。
  146. list_head=[]
  147. for i in range(len(init_head)):
  148. for j in range(len(person_contour)):
  149. center_x, center_y=center_coordinate(init_head[i])
  150. flag = cv2.pointPolygonTest(person_contour[j], (center_x, center_y), False) #若为False,会找点是否在内,外,或轮廓上(相应返回+1, -1, 0)。
  151. if flag==1:
  152. pass
  153. else:
  154. list_head.append(init_head[i])
  155. # person和最终head合并起来
  156. init_head_person_temp=init_person+list_head
  157. '''3、preds中head+person,通过1中水域过滤'''
  158. init_head_person_filterwater=init_head_person_temp
  159. final_head_person_filterwater=[]
  160. for i in range(len(init_head_person_filterwater)):
  161. center_x, center_y=center_coordinate(init_head_person_filterwater[i])
  162. #print('#'*20,'line176:',len(max_contour),np.array(max_contour).shape,(center_x, center_y))
  163. flag = cv2.pointPolygonTest(max_contour, (int(center_x), int(center_y)), False) #若为False,会找点是否在内,外,或轮廓上(相应返回+1, -1, 0)。
  164. if flag==1:
  165. final_head_person_filterwater.append(init_head_person_filterwater[i])
  166. else:
  167. pass
  168. t9 = time.time()
  169. '''4、水域过滤后的head+person,再通过船舶范围过滤'''
  170. init_head_person_filterboat=final_head_person_filterwater
  171. # final_head_person_filterboat=[]
  172. #获取船舶范围
  173. boat_contour=[]
  174. for i in range(len(init_boat)):
  175. boundbxs1=[init_boat[i][0],init_boat[i][1],init_boat[i][2],init_boat[i][3]]
  176. contour_temp=fourcorner_coordinate(boundbxs1) #得到boat预测框的顺序contour
  177. contour_temp_=np.array(contour_temp)
  178. contour_temp_=np.float32(contour_temp_)
  179. boat_contour.append(np.array(contour_temp_))
  180. t10 = time.time()
  181. # 遍历船舶范围,取出在船舶范围内的head和person(可能有重复元素)
  182. list_headperson_inboat=[]
  183. for i in range(len(init_head_person_filterboat)):
  184. for j in range(len(boat_contour)):
  185. center_x, center_y=center_coordinate(init_head_person_filterboat[i])
  186. # yyyyyyyy=boat_contour[j]
  187. flag = cv2.pointPolygonTest(boat_contour[j], (center_x, center_y), False) #若为False,会找点是否在内,外,或轮廓上(相应返回+1, -1, 0)。
  188. if flag==1:
  189. list_headperson_inboat.append(init_head_person_filterboat[i])
  190. else:
  191. pass
  192. # print('list_headperson_inboat',list_headperson_inboat)
  193. if len(list_headperson_inboat)==0:
  194. pass
  195. else:
  196. list_headperson_inboat=remove_sameeleme_inalist(list_headperson_inboat) #将重复嵌套列表元素删除
  197. # 过滤船舶范围内的head和person
  198. final_head_person_filterboat=remove_simivalue(init_head_person_filterboat,list_headperson_inboat)
  199. final_output_luoshui=final_head_person_filterboat
  200. t11 = time.time()
  201. #timeInfos=('存图:%s, 过滤标签:%s ,遍历船舶范围:%s,水域过滤后的head+person:%s,水域过滤:%s,head+person、boat取出:%s,新增如果水域为空:%s,找contours:%s,图像改变:%s'
  202. # %((t11-t10) * 1000,(t10-t9) * 1000,(t9-t8) * 1000,(t8-t7) * 1000,(t7-t6) * 1000,(t6-t5) * 1000,(t5-t4) * 1000 ) )
  203. timeInfos=' findMaxWater:%.1f releJudge:%.1f'%( ms(t6,t4) ,ms(t11,t6) )
  204. return final_output_luoshui,timeInfos #返回最终绘制的结果图、最终落水人员(坐标、类别、置信度)