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.

368 lines
17KB

  1. import cv2,os,time,json
  2. from models.experimental import attempt_load
  3. from segutils.segmodel import SegModel,get_largest_contours
  4. from segutils.trtUtils import segtrtEval,yolov5Trtforward,OcrTrtForward
  5. from segutils.trafficUtils import trafficPostProcessing,colour_code_segmentation,get_label_info,trafficPostProcessingV2
  6. from utils.torch_utils import select_device
  7. from utilsK.queRiver import get_labelnames,get_label_arrays,post_process_,img_pad,draw_painting_joint
  8. from utils.datasets import letterbox
  9. import numpy as np
  10. import torch
  11. import math
  12. from PIL import Image
  13. import torch.nn.functional as F
  14. from copy import deepcopy
  15. def xywh2xyxy(box,iW=None,iH=None):
  16. xc,yc,w,h = box[0:4]
  17. x0 =max(0, xc-w/2.0)
  18. x1 =min(1, xc+w/2.0)
  19. y0=max(0, yc-h/2.0)
  20. y1=min(1,yc+h/2.0)
  21. if iW: x0,x1 = x0*iW,x1*iW
  22. if iH: y0,y1 = y0*iH,y1*iH
  23. return [x0,y0,x1,y1]
  24. def get_ms(t2,t1):
  25. return (t2-t1)*1000.0
  26. def get_postProcess_para(parfile):
  27. with open(parfile) as fp:
  28. par = json.load(fp)
  29. assert 'post_process' in par.keys(), ' parfile has not key word:post_process'
  30. parPost=par['post_process']
  31. return parPost["conf_thres"],parPost["iou_thres"],parPost["classes"],parPost["rainbows"]
  32. def AI_process(im0s,model,segmodel,names,label_arraylist,rainbows,objectPar={ 'half':True,'device':'cuda:0' ,'conf_thres':0.25,'iou_thres':0.45,'allowedList':[0,1,2,3],'slopeIndex':[5,6,7],'segRegionCnt':1, 'trtFlag_det':False,'trtFlag_seg':False }, font={ 'line_thickness':None, 'fontSize':None,'boxLine_thickness':None,'waterLineColor':(0,255,255),'waterLineWidth':3} ,segPar={'modelSize':(640,360),'mean':(0.485, 0.456, 0.406),'std' :(0.229, 0.224, 0.225),'numpy':False, 'RGB_convert_first':True},mode='others',postPar=None):
  33. #输入参数
  34. # im0s---原始图像列表
  35. # model---检测模型,segmodel---分割模型(如若没有用到,则为None)
  36. #
  37. #输出:两个元素(列表,字符)构成的元组,[im0s[0],im0,det_xywh,iframe],strout
  38. # [im0s[0],im0,det_xywh,iframe]中,
  39. # im0s[0]--原始图像,im0--AI处理后的图像,iframe--帧号/暂时不需用到。
  40. # det_xywh--检测结果,是一个列表。
  41. # 其中每一个元素表示一个目标构成如:[float(cls_c), xc,yc,w,h, float(conf_c)]
  42. # #cls_c--类别,如0,1,2,3; xc,yc,w,h--中心点坐标及宽;conf_c--得分, 取值范围在0-1之间
  43. # #strout---统计AI处理个环节的时间
  44. # Letterbox
  45. half,device,conf_thres,iou_thres,allowedList = objectPar['half'],objectPar['device'],objectPar['conf_thres'],objectPar['iou_thres'],objectPar['allowedList']
  46. slopeIndex, trtFlag_det,trtFlag_seg,segRegionCnt = objectPar['slopeIndex'],objectPar['trtFlag_det'],objectPar['trtFlag_seg'],objectPar['segRegionCnt']
  47. time0=time.time()
  48. if trtFlag_det:
  49. img, padInfos = img_pad(im0s[0], size=(640,640,3)) ;img = [img]
  50. else:
  51. img = [letterbox(x, 640, auto=True, stride=32)[0] for x in im0s];padInfos=None
  52. # Stack
  53. img = np.stack(img, 0)
  54. # Convert
  55. img = img[:, :, :, ::-1].transpose(0, 3, 1, 2) # BGR to RGB, to bsx3x416x416
  56. img = np.ascontiguousarray(img)
  57. img = torch.from_numpy(img).to(device)
  58. img = img.half() if half else img.float() # uint8 to fp16/32
  59. time01=time.time()
  60. img /= 255.0 # 0 - 255 to 0.0 - 1.0
  61. if segmodel:
  62. if trtFlag_seg:
  63. seg_pred,segstr = segtrtEval(segmodel,im0s[0],par=segPar)
  64. else:
  65. seg_pred,segstr = segmodel.eval(im0s[0] )
  66. segFlag=True
  67. else:
  68. seg_pred = None;segFlag=False;segstr='Not implemented'
  69. if mode=='highWay3.0':
  70. seg_pred_mulcls = seg_pred.copy()
  71. seg_pred = (seg_pred==1).astype(np.uint8) ###把路提取出来,路的类别是1
  72. time1=time.time()
  73. if trtFlag_det:
  74. pred = yolov5Trtforward(model,img)
  75. else:
  76. pred = model(img,augment=False)[0]
  77. time2=time.time()
  78. datas = [[''], img, im0s, None,pred,seg_pred,10]
  79. ObjectPar={ 'object_config':allowedList, 'slopeIndex':slopeIndex ,'segmodel':segFlag,'segRegionCnt':segRegionCnt }
  80. p_result,timeOut = post_process_(datas,conf_thres, iou_thres,names,label_arraylist,rainbows,10,ObjectPar=ObjectPar,font=font,padInfos=padInfos)
  81. if mode=='highWay3.0':
  82. assert postPar , ' postPar not implemented'
  83. label_info = get_label_info(postPar['label_csv'])
  84. seg_pred=cv2.resize(seg_pred_mulcls,( segPar['modelSize'][0] , segPar['modelSize'] [1]) )
  85. imH,imW = im0s[0].shape[0:2]
  86. mmH,mmW = seg_pred.shape[0:2]
  87. fx=mmW/imW;fy=mmH/imH
  88. det_coords=[]
  89. det_coords_original=[]
  90. for box in p_result[2]:
  91. b_0 = box[1:5]
  92. b_0.insert(0,box[0]);b_0.append(box[5] )
  93. det_coords_original.append( b_0 )
  94. if int(box[0]) != 1: continue
  95. b=box[1:5]
  96. b[0],b[2] = b[0]*fx,b[2]*fx
  97. b[1],b[3] = b[1]*fy,b[3]*fy
  98. b=[int(x) for x in b]
  99. det_coords.append( (b[0],b[1])); det_coords.append( (b[2],b[3]) )
  100. postPar['ZoomFactor']={'x':mmW/imW ,'y':mmH/imH}
  101. postPar['mask']=seg_pred;postPar['det']=deepcopy(det_coords_original)
  102. postPar['label_info']=label_info
  103. tlist = list(postPar.keys()); tlist.sort()
  104. if len(det_coords_original)> 0:
  105. list8, image,time_infos = trafficPostProcessingV2(postPar)
  106. Accident_results = np.array(list8,dtype=object)
  107. acc_det=[]
  108. for bpoints in list8:
  109. if bpoints[9]>conf_thres:
  110. xyxy=bpoints[1:5];xyxy=[int(x) for x in xyxy]
  111. cls=9;conf=bpoints[9];
  112. box_acc = [cls,*xyxy,conf]
  113. acc_det.append(box_acc)
  114. if cls in allowedList:
  115. p_result[1] = draw_painting_joint(xyxy,p_result[1],label_arraylist[int(cls)],score=conf,color=rainbows[int(cls)%20],font=font,socre_location="leftBottom")
  116. det_coords_original.extend(acc_det)
  117. p_result[2]= deepcopy(det_coords_original)
  118. #print( ' time:',time_infos,' results.shape:',Accident_results.shape, p_result[2])
  119. time_info = 'letterbox:%.1f, seg:%.1f , infer:%.1f,%s, seginfo:%s'%( (time01-time0)*1000, (time1-time01)*1000 ,(time2-time1)*1000,timeOut , segstr )
  120. if mode=='highWay3.0':
  121. p_result.append(seg_pred_mulcls)
  122. return p_result,time_info
  123. def AI_Seg_process(im0s,segmodel,digitWordFont,trtFlag_seg=True,segPar={'modelSize':(640,360),'mean':(0.485, 0.456, 0.406),'std' :(0.229, 0.224, 0.225),'numpy':False, 'RGB_convert_first':True},postPar= {'label_csv': './AIlib2/weights/conf/trafficAccident/class_dict.csv', 'speedRoadArea': 5100, 'vehicleArea': 100, 'speedRoadVehicleAngleMin': 15, 'speedRoadVehicleAngleMax': 75, 'vehicleLengthWidthThreshold': 4, 'vehicleSafeDistance': 7}):
  124. '''
  125. 输入参数
  126. im0s---原始图像列表
  127. segmodel---分割模型,segmodel---分割模型(如若没有用到,则为None)
  128. digitWordFont--显示字体,数字等参数
  129. trtFlag_seg--模型是否是TRT格式
  130. segPar--分割模型的参数
  131. postPar--后处理参数
  132. 输出
  133. seg_pred--返回语义分割的结果图(0,1,2...表示)
  134. img_draw--原图上带有矩形框的图
  135. segstr-----文本数据包括时间信息
  136. list1-----返回目标的坐标结果,每一个目标用[ cls, x0,y0,x1,y1,conf ]
  137. '''
  138. time1=time.time()
  139. H,W=im0s[0].shape[0:2]
  140. img_draw=im0s[0].copy()
  141. if trtFlag_seg:
  142. seg_pred,segstr = segtrtEval(segmodel,im0s[0],par=segPar)
  143. else:
  144. seg_pred,segstr = segmodel.eval(im0s[0] )
  145. time2 = time.time()
  146. label_info = get_label_info(postPar['label_csv'])
  147. postPar['CCS']=colour_code_segmentation(seg_pred.copy(), label_info)
  148. postPar['sourceImageSize'] = im0s[0].shape[0:2]
  149. postPar['seg_pred_size'] = seg_pred.shape[0:2]
  150. list1,post_time_infos = trafficPostProcessing(postPar)
  151. list2=[]
  152. cls=0
  153. label_arraylist=digitWordFont['label_arraylist']
  154. rainbows=digitWordFont['rainbows']
  155. for bpoints in list1:
  156. #print('###line104:',bpoints)
  157. bpoints=np.array(bpoints)
  158. x0=np.min( bpoints[:,0] )
  159. y0=np.min( bpoints[:,1] )
  160. x1=np.max( bpoints[:,0] )
  161. y1=np.max( bpoints[:,1] )
  162. conf= ((x0+x1)/W + (y0+y1)/H)/4.0;
  163. conf=1.0 - math.fabs((conf-0.5)/0.5)
  164. xyxy=[x0,y0,x1,y1]
  165. xyxy=[int(x+0.5) for x in xyxy]
  166. #float(cls_c), *xywh, float(conf_c)]
  167. list2.append( [ cls, x0,y0,x1,y1,conf ] )
  168. img_draw = draw_painting_joint(xyxy,img_draw,label_arraylist[int(cls)],score=conf,color=rainbows[int(cls)%20],font=digitWordFont)
  169. segstr = 'segInfer:%.2f %s '%( (time2-time1)*1000.0,post_time_infos )
  170. return seg_pred,img_draw,segstr,list2
  171. def AI_process_v2(im0s,model,segmodel,names,label_arraylist,rainbows,half=True,device=' cuda:0',conf_thres=0.25, iou_thres=0.45,allowedList=[0,1,2,3], font={ 'line_thickness':None, 'fontSize':None,'boxLine_thickness':None,'waterLineColor':(0,255,255),'waterLineWidth':3} ):
  172. #输入参数
  173. # im0s---原始图像列表
  174. # model---检测模型,segmodel---分割模型(如若没有用到,则为None)
  175. #输出:两个元素(列表,字符)构成的元组,[im0s[0],im0,det_xywh,iframe],strout
  176. # [im0s[0],im0,det_xywh,iframe]中,
  177. # im0s[0]--原始图像,im0--AI处理后的图像,iframe--帧号/暂时不需用到。
  178. # det_xywh--检测结果,是一个列表。
  179. # 其中每一个元素表示一个目标构成如:[float(cls_c), xc,yc,w,h, float(conf_c)]
  180. # #cls_c--类别,如0,1,2,3; xc,yc,w,h--中心点坐标及宽;conf_c--得分, 取值范围在0-1之间
  181. # #strout---统计AI处理个环节的时间
  182. # Letterbox
  183. time0=time.time()
  184. #img = [letterbox(x, 640, auto=True, stride=32)[0] for x in im0s]
  185. img, padInfos = img_pad(im0s[0], size=(640,640,3)) ;img = [img]
  186. # Stack
  187. img = np.stack(img, 0)
  188. # Convert
  189. img = img[:, :, :, ::-1].transpose(0, 3, 1, 2) # BGR to RGB, to bsx3x416x416
  190. img = np.ascontiguousarray(img)
  191. img = torch.from_numpy(img).to(device)
  192. img = img.half() if half else img.float() # uint8 to fp16/32
  193. time01=time.time()
  194. img /= 255.0 # 0 - 255 to 0.0 - 1.0
  195. if segmodel:
  196. seg_pred,segstr = segmodel.eval(im0s[0] )
  197. segFlag=True
  198. else:
  199. seg_pred = None;segFlag=False
  200. time1=time.time()
  201. pred = model(img,augment=False)
  202. time2=time.time()
  203. datas = [[''], img, im0s, None,pred,seg_pred,10]
  204. p_result,timeOut = post_process_(datas,conf_thres, iou_thres,names,label_arraylist,rainbows,10,object_config=allowedList,segmodel=segFlag,font=font,padInfos=padInfos)
  205. time_info = 'letterbox:%.1f, seg:%.1f , infer:%.1f,%s, seginfo:%s'%( (time01-time0)*1000, (time1-time01)*1000 ,(time2-time1)*1000,timeOut , segstr )
  206. return p_result,time_info
  207. def AI_process_forest(im0s,model,segmodel,names,label_arraylist,rainbows,half=True,device=' cuda:0',conf_thres=0.25, iou_thres=0.45,allowedList=[0,1,2,3], font={ 'line_thickness':None, 'fontSize':None,'boxLine_thickness':None,'waterLineColor':(0,255,255),'waterLineWidth':3} ,trtFlag_det=False):
  208. #输入参数
  209. # im0s---原始图像列表
  210. # model---检测模型,segmodel---分割模型(如若没有用到,则为None)
  211. #输出:两个元素(列表,字符)构成的元组,[im0s[0],im0,det_xywh,iframe],strout
  212. # [im0s[0],im0,det_xywh,iframe]中,
  213. # im0s[0]--原始图像,im0--AI处理后的图像,iframe--帧号/暂时不需用到。
  214. # det_xywh--检测结果,是一个列表。
  215. # 其中每一个元素表示一个目标构成如:[float(cls_c), xc,yc,w,h, float(conf_c)]
  216. # #cls_c--类别,如0,1,2,3; xc,yc,w,h--中心点坐标及宽;conf_c--得分, 取值范围在0-1之间
  217. # #strout---统计AI处理个环节的时间
  218. # Letterbox
  219. time0=time.time()
  220. if trtFlag_det:
  221. img, padInfos = img_pad(im0s[0], size=(640,640,3)) ;img = [img]
  222. else:
  223. img = [letterbox(x, 640, auto=True, stride=32)[0] for x in im0s];padInfos=None
  224. #img = [letterbox(x, 640, auto=True, stride=32)[0] for x in im0s]
  225. # Stack
  226. img = np.stack(img, 0)
  227. # Convert
  228. img = img[:, :, :, ::-1].transpose(0, 3, 1, 2) # BGR to RGB, to bsx3x416x416
  229. img = np.ascontiguousarray(img)
  230. img = torch.from_numpy(img).to(device)
  231. img = img.half() if half else img.float() # uint8 to fp16/32
  232. img /= 255.0 # 0 - 255 to 0.0 - 1.0
  233. if segmodel:
  234. seg_pred,segstr = segmodel.eval(im0s[0] )
  235. segFlag=True
  236. else:
  237. seg_pred = None;segFlag=False
  238. time1=time.time()
  239. pred = yolov5Trtforward(model,img) if trtFlag_det else model(img,augment=False)[0]
  240. time2=time.time()
  241. datas = [[''], img, im0s, None,pred,seg_pred,10]
  242. ObjectPar={ 'object_config':allowedList, 'slopeIndex':[] ,'segmodel':segFlag,'segRegionCnt':0 }
  243. p_result,timeOut = post_process_(datas,conf_thres, iou_thres,names,label_arraylist,rainbows,10,ObjectPar=ObjectPar,font=font,padInfos=padInfos)
  244. #p_result,timeOut = post_process_(datas,conf_thres, iou_thres,names,label_arraylist,rainbows,10,object_config=allowedList,segmodel=segFlag,font=font,padInfos=padInfos)
  245. time_info = 'letterbox:%.1f, infer:%.1f, '%( (time1-time0)*1000,(time2-time1)*1000 )
  246. return p_result,time_info+timeOut
  247. def ocr_process(pars):
  248. img_patch,engine,context,converter,AlignCollate_normal,device=pars[0:6]
  249. time1 = time.time()
  250. img_tensor = AlignCollate_normal([ Image.fromarray(img_patch,'L') ])
  251. img_input = img_tensor.to('cuda:0')
  252. time2 = time.time()
  253. preds,trtstr=OcrTrtForward(engine,[img_input],context)
  254. time3 = time.time()
  255. batch_size = preds.size(0)
  256. preds_size = torch.IntTensor([preds.size(1)] * batch_size)
  257. ######## filter ignore_char, rebalance
  258. preds_prob = F.softmax(preds, dim=2)
  259. preds_prob = preds_prob.cpu().detach().numpy()
  260. pred_norm = preds_prob.sum(axis=2)
  261. preds_prob = preds_prob/np.expand_dims(pred_norm, axis=-1)
  262. preds_prob = torch.from_numpy(preds_prob).float().to(device)
  263. _, preds_index = preds_prob.max(2)
  264. preds_index = preds_index.view(-1)
  265. time4 = time.time()
  266. preds_str = converter.decode_greedy(preds_index.data.cpu().detach().numpy(), preds_size.data)
  267. time5 = time.time()
  268. info_str= ('pre-process:%.2f TRTforward:%.2f (%s) postProcess:%2.f decoder:%.2f, Total:%.2f , pred:%s'%(get_ms(time2,time1 ),get_ms(time3,time2 ),trtstr, get_ms(time4,time3 ), get_ms(time5,time4 ), get_ms(time5,time1 ), preds_str ) )
  269. return preds_str,info_str
  270. def main():
  271. ##预先设置的参数
  272. device_='1' ##选定模型,可选 cpu,'0','1'
  273. ##以下参数目前不可改
  274. Detweights = "weights/yolov5/class5/best_5classes.pt"
  275. seg_nclass = 2
  276. Segweights = "weights/BiSeNet/checkpoint.pth"
  277. conf_thres,iou_thres,classes= 0.25,0.45,5
  278. labelnames = "weights/yolov5/class5/labelnames.json"
  279. rainbows = [ [0,0,255],[0,255,0],[255,0,0],[255,0,255],[255,255,0],[255,129,0],[255,0,127],[127,255,0],[0,255,127],[0,127,255],[127,0,255],[255,127,255],[255,255,127],[127,255,255],[0,255,255],[255,127,255],[127,255,255], [0,127,0],[0,0,127],[0,255,255]]
  280. allowedList=[0,1,2,3]
  281. ##加载模型,准备好显示字符
  282. device = select_device(device_)
  283. names=get_labelnames(labelnames)
  284. label_arraylist = get_label_arrays(names,rainbows,outfontsize=40,fontpath="conf/platech.ttf")
  285. half = device.type != 'cpu' # half precision only supported on CUDA
  286. model = attempt_load(Detweights, map_location=device) # load FP32 model
  287. if half: model.half()
  288. segmodel = SegModel(nclass=seg_nclass,weights=Segweights,device=device)
  289. ##图像测试
  290. #url='images/examples/20220624_响水河_12300_1621.jpg'
  291. impth = 'images/examples/'
  292. outpth = 'images/results/'
  293. folders = os.listdir(impth)
  294. for i in range(len(folders)):
  295. imgpath = os.path.join(impth, folders[i])
  296. im0s=[cv2.imread(imgpath)]
  297. time00 = time.time()
  298. p_result,timeOut = AI_process(im0s,model,segmodel,names,label_arraylist,rainbows,half,device,conf_thres, iou_thres,allowedList,fontSize=1.0)
  299. time11 = time.time()
  300. image_array = p_result[1]
  301. cv2.imwrite( os.path.join( outpth,folders[i] ) ,image_array )
  302. print('----process:%s'%(folders[i]), (time.time() - time11) * 1000)
  303. if __name__=="__main__":
  304. main()