This commit is contained in:
th 2025-04-26 10:35:59 +08:00
commit fc460a740b
544 changed files with 105812 additions and 0 deletions

734
AI.py Normal file
View File

@ -0,0 +1,734 @@
import cv2,os,time,json
from models.experimental import attempt_load
from segutils.segmodel import SegModel,get_largest_contours
from segutils.trtUtils import segtrtEval,yolov5Trtforward,OcrTrtForward
from segutils.trafficUtils import tracfficAccidentMixFunction
from utils.torch_utils import select_device
from utilsK.queRiver import get_labelnames,get_label_arrays,post_process_,img_pad,draw_painting_joint,detectDraw,getDetections,getDetectionsFromPreds
from trackUtils.sort import moving_average_wang
from utils.datasets import letterbox
import numpy as np
import torch
import math
from PIL import Image
import torch.nn.functional as F
from copy import deepcopy
from scipy import interpolate
import glob
from loguru import logger
def get_images_videos(impth, imageFixs=['.jpg','.JPG','.PNG','.png'],videoFixs=['.MP4','.mp4','.avi']):
imgpaths=[];###获取文件里所有的图像
videopaths=[]###获取文件里所有的视频
if os.path.isdir(impth):
for postfix in imageFixs:
imgpaths.extend(glob.glob('%s/*%s'%(impth,postfix )) )
for postfix in videoFixs:
videopaths.extend(glob.glob('%s/*%s'%(impth,postfix )) )
else:
postfix = os.path.splitext(impth)[-1]
if postfix in imageFixs: imgpaths=[ impth ]
if postfix in videoFixs: videopaths = [impth ]
print('%s: test Images:%d , test videos:%d '%(impth, len(imgpaths), len(videopaths)))
return imgpaths,videopaths
def xywh2xyxy(box,iW=None,iH=None):
xc,yc,w,h = box[0:4]
x0 =max(0, xc-w/2.0)
x1 =min(1, xc+w/2.0)
y0=max(0, yc-h/2.0)
y1=min(1,yc+h/2.0)
if iW: x0,x1 = x0*iW,x1*iW
if iH: y0,y1 = y0*iH,y1*iH
return [x0,y0,x1,y1]
def get_ms(t2,t1):
return (t2-t1)*1000.0
def get_postProcess_para(parfile):
with open(parfile) as fp:
par = json.load(fp)
assert 'post_process' in par.keys(), ' parfile has not key word:post_process'
parPost=par['post_process']
return parPost["conf_thres"],parPost["iou_thres"],parPost["classes"],parPost["rainbows"]
def get_postProcess_para_dic(parfile):
with open(parfile) as fp:
par = json.load(fp)
parPost=par['post_process']
return parPost
def score_filter_byClass(pdetections,score_para_2nd):
ret=[]
for det in pdetections:
score,cls = det[4],det[5]
if int(cls) in score_para_2nd.keys():
score_th = score_para_2nd[int(cls)]
elif str(int(cls)) in score_para_2nd.keys():
score_th = score_para_2nd[str(int(cls))]
else:
score_th = 0.7
if score > score_th:
ret.append(det)
return ret
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],'segRegionCnt':1, 'trtFlag_det':False,'trtFlag_seg':False,'score_byClass':{x:0.1 for x in range(30)} }, 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):
#输入参数
# im0s---原始图像列表
# model---检测模型segmodel---分割模型如若没有用到则为None
#
#输出:两个元素(列表,字符)构成的元组,[im0s[0],im0,det_xywh,iframe],strout
# [im0s[0],im0,det_xywh,iframe]中,
# im0s[0]--原始图像im0--AI处理后的图像,iframe--帧号/暂时不需用到。
# det_xywh--检测结果,是一个列表。
# 其中每一个元素表示一个目标构成如:[ xc,yc,w,h, float(conf_c),float(cls_c) ] ,2023.08.03修改输出格式
# #cls_c--类别如0,1,2,3; xc,yc,w,h--中心点坐标及宽conf_c--得分, 取值范围在0-1之间
# #strout---统计AI处理个环节的时间
# Letterbox
half,device,conf_thres,iou_thres,allowedList = objectPar['half'],objectPar['device'],objectPar['conf_thres'],objectPar['iou_thres'],objectPar['allowedList']
trtFlag_det,trtFlag_seg,segRegionCnt = objectPar['trtFlag_det'],objectPar['trtFlag_seg'],objectPar['segRegionCnt']
if 'ovlap_thres_crossCategory' in objectPar.keys(): ovlap_thres = objectPar['ovlap_thres_crossCategory']
else: ovlap_thres = None
if 'score_byClass' in objectPar.keys(): score_byClass = objectPar['score_byClass']
else: score_byClass = None
time0=time.time()
if trtFlag_det:
img, padInfos = img_pad(im0s[0], size=(640,640,3)) ;img = [img]
else:
#print('####line72:',im0s[0][10:12,10:12,2])
img = [letterbox(x, 640, auto=True, stride=32)[0] for x in im0s];padInfos=None
#print('####line74:',img[0][10:12,10:12,2])
# Stack
img = np.stack(img, 0)
# Convert
img = img[:, :, :, ::-1].transpose(0, 3, 1, 2) # BGR to RGB, to bsx3x416x416
img = np.ascontiguousarray(img)
img = torch.from_numpy(img).to(device)
img = img.half() if half else img.float() # uint8 to fp16/32
img /= 255.0
time01=time.time()
if segmodel:
seg_pred,segstr = segmodel.eval(im0s[0] )
segFlag=True
else:
seg_pred = None;segFlag=False;segstr='Not implemented'
time1=time.time()
if trtFlag_det:
pred = yolov5Trtforward(model,img)
else:
#print('####line96:',img[0,0,10:12,10:12])
pred = model(img,augment=False)[0]
time2=time.time()
p_result, timeOut = getDetectionsFromPreds(pred,img,im0s[0],conf_thres=conf_thres,iou_thres=iou_thres,ovlap_thres=ovlap_thres,padInfos=padInfos)
#logger.info("获取视频p_result :{}, requestId:{}, names:{}", '+++' * 10, p_result[2],names)
if score_byClass:
p_result[2] = score_filter_byClass(p_result[2],score_byClass)
#print('-'*10,p_result[2])
#if mode=='highWay3.0':
#if segmodel:
if segPar and segPar['mixFunction']['function']:
mixFunction = segPar['mixFunction']['function'];H,W = im0s[0].shape[0:2]
parMix = segPar['mixFunction']['pars'];#print('###line117:',parMix,p_result[2])
parMix['imgSize'] = (W,H)
#print(' -----------line149: ',p_result[2] ,'\n', seg_pred, parMix ,' sumpSeg:',np.sum(seg_pred))
p_result[2] , timeMixPost= mixFunction(p_result[2], seg_pred, pars=parMix )
#print(' -----------line112: ',p_result[2] )
p_result.append(seg_pred)
else:
timeMixPost=':0 ms'
#print('#### line121: segstr:%s timeMixPost:%s timeOut:%s'%( segstr.strip(), timeMixPost,timeOut ))
time_info = 'letterbox:%.1f, seg:%.1f , infer:%.1f,%s, seginfo:%s ,timeMixPost:%s '%( (time01-time0)*1000, (time1-time01)*1000 ,(time2-time1)*1000,timeOut , segstr.strip(),timeMixPost )
#if mode=='highWay3.0':
#print('line159:','-'*10,p_result[2])
return p_result,time_info
def default_mix(predlist,par):
return predlist[0],''
def AI_process_N(im0s,modelList,postProcess):
#输入参数
## im0s---原始图像列表
## modelList--所有的模型
# postProcess--字典{},包括后处理函数,及其参数
#输出参数
##ret[0]--检测结果;
##ret[1]--时间信息
#modelList包括模型每个模型是一个类里面的eval函数可以输出该模型的推理结果
modelRets=[ model.eval(im0s[0]) for model in modelList]
timeInfos = [ x[1] for x in modelRets]
timeInfos=''.join(timeInfos)
timeInfos=timeInfos
#postProcess['function']--后处理函数,输入的就是所有模型输出结果
mixFunction =postProcess['function']
predsList = [ modelRet[0] for modelRet in modelRets ]
H,W = im0s[0].shape[0:2]
postProcess['pars']['imgSize'] = (W,H)
#ret就是混合处理后的结果
ret = mixFunction( predsList, postProcess['pars'])
return ret[0],timeInfos+ret[1]
def getMaxScoreWords(detRets0):
maxScore=-1;maxId=0
for i,detRet in enumerate(detRets0):
if detRet[4]>maxScore:
maxId=i
maxScore = detRet[4]
return maxId
def AI_process_C(im0s,modelList,postProcess):
#函数定制的原因:
## 之前模型处理流是
## 图片---> 模型1-->result1图片---> 模型2->result2[result1,result2]--->后处理函数
## 本函数的处理流程是
## 图片---> 模型1-->result1[图片,result1]---> 模型2->result2[result1,result2]--->后处理函数
## 模型2的输入是有模型1的输出决定的。如模型2是ocr模型需要将模型1检测出来的船名抠图出来输入到模型2.
## 之前的模型流都是模型2是分割模型输入就是原始图片与模型1的输出无关。
#输入参数
## im0s---原始图像列表
## modelList--所有的模型
# postProcess--字典{},包括后处理函数,及其参数
#输出参数
##ret[0]--检测结果;
##ret[1]--时间信息
#modelList包括模型每个模型是一个类里面的eval函数可以输出该模型的推理结果
t0=time.time()
detRets0 = modelList[0].eval(im0s[0])
#detRets0=[[12, 46, 1127, 1544, 0.2340087890625, 2.0], [1884, 1248, 2992, 1485, 0.64208984375, 1.0]]
detRets0 = detRets0[0]
parsIn=postProcess['pars']
_detRets0_obj = list(filter(lambda x: x[5] in parsIn['objs'], detRets0 ))
_detRets0_others = list(filter(lambda x: x[5] not in parsIn['objs'], detRets0 ))
_detRets0 = []
if postProcess['name']=='channel2':
if len(_detRets0_obj)>0:
maxId=getMaxScoreWords(_detRets0_obj)
_detRets0 = _detRets0_obj[maxId:maxId+1]
else: _detRets0 = detRets0
t1=time.time()
imagePatches = [ im0s[0][int(x[1]):int(x[3] ) ,int(x[0]):int(x[2])] for x in _detRets0 ]
detRets1 = [modelList[1].eval(patch) for patch in imagePatches]
print('###line240:',detRets1)
if postProcess['name']=='crackMeasurement':
detRets1 = [x[0]*255 for x in detRets1]
t2=time.time()
mixFunction =postProcess['function']
crackInfos = [mixFunction(patchMask,par=parsIn) for patchMask in detRets1]
rets = [ _detRets0[i]+ crackInfos[i] for i in range(len(imagePatches)) ]
t3=time.time()
outInfos='total:%.1f (det:%.1f %d次segs:%.1f mixProcess:%.1f) '%( (t3-t0)*1000, (t1-t0)*1000, len(detRets1),(t2-t1)*1000, (t3-t2)*1000 )
elif postProcess['name']=='channel2':
H,W = im0s[0].shape[0:2];parsIn['imgSize'] = (W,H)
mixFunction =postProcess['function']
_detRets0_others = mixFunction([_detRets0_others], parsIn)
ocrInfo='no ocr'
if len(_detRets0_obj)>0:
res_real = detRets1[0][0]
res_real="".join( list(filter(lambda x:(ord(x) >19968 and ord(x)<63865 ) or (ord(x) >47 and ord(x)<58 ),res_real)))
#detRets1[0][0]="".join( list(filter(lambda x:(ord(x) >19968 and ord(x)<63865 ) or (ord(x) >47 and ord(x)<58 ),detRets1[0][0])))
_detRets0_obj[maxId].append(res_real )
_detRets0_obj = [_detRets0_obj[maxId]]##只输出有OCR的那个船名结果
ocrInfo=detRets1[0][1]
print( ' _detRets0_obj:{} _detRets0_others:{} '.format( _detRets0_obj, _detRets0_others ) )
rets=_detRets0_obj+_detRets0_others
t3=time.time()
outInfos='total:%.1f ,where det:%.1f, ocr:%s'%( (t3-t0)*1000, (t1-t0)*1000, ocrInfo)
#print('###line233:',detRets1,detRets0 )
return rets,outInfos
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,SecNms=None):
#输入参数
# im0s---原始图像列表
# model---检测模型segmodel---分割模型如若没有用到则为None
#输出:两个元素(列表,字符)构成的元组,[im0s[0],im0,det_xywh,iframe],strout
# [im0s[0],im0,det_xywh,iframe]中,
# im0s[0]--原始图像im0--AI处理后的图像,iframe--帧号/暂时不需用到。
# det_xywh--检测结果,是一个列表。
# 其中每一个元素表示一个目标构成如:[ xc,yc,w,h, float(conf_c),float(cls_c)],#2023.08.03,修改输出格式
# #cls_c--类别如0,1,2,3; xc,yc,w,h--中心点坐标及宽conf_c--得分, 取值范围在0-1之间
# #strout---统计AI处理个环节的时间
# Letterbox
time0=time.time()
if trtFlag_det:
img, padInfos = img_pad(im0s[0], size=(640,640,3)) ;img = [img]
else:
img = [letterbox(x, 640, auto=True, stride=32)[0] for x in im0s];padInfos=None
#img = [letterbox(x, 640, auto=True, stride=32)[0] for x in im0s]
# Stack
img = np.stack(img, 0)
# Convert
img = img[:, :, :, ::-1].transpose(0, 3, 1, 2) # BGR to RGB, to bsx3x416x416
img = np.ascontiguousarray(img)
img = torch.from_numpy(img).to(device)
img = img.half() if half else img.float() # uint8 to fp16/32
img /= 255.0 # 0 - 255 to 0.0 - 1.0
if segmodel:
seg_pred,segstr = segmodel.eval(im0s[0] )
segFlag=True
else:
seg_pred = None;segFlag=False
time1=time.time()
pred = yolov5Trtforward(model,img) if trtFlag_det else model(img,augment=False)[0]
time2=time.time()
datas = [[''], img, im0s, None,pred,seg_pred,10]
ObjectPar={ 'object_config':allowedList, 'slopeIndex':[] ,'segmodel':segFlag,'segRegionCnt':0 }
p_result,timeOut = post_process_(datas,conf_thres, iou_thres,names,label_arraylist,rainbows,10,ObjectPar=ObjectPar,font=font,padInfos=padInfos,ovlap_thres=SecNms)
#print('###line274:',p_result[2])
#p_result,timeOut = post_process_(datas,conf_thres, iou_thres,names,label_arraylist,rainbows,10,object_config=allowedList,segmodel=segFlag,font=font,padInfos=padInfos)
time_info = 'letterbox:%.1f, infer:%.1f, '%( (time1-time0)*1000,(time2-time1)*1000 )
return p_result,time_info+timeOut
def AI_det_track( im0s_in,modelPar,processPar,sort_tracker,segPar=None):
im0s,iframe=im0s_in[0],im0s_in[1]
model = modelPar['det_Model']
segmodel = modelPar['seg_Model']
half,device,conf_thres, iou_thres,trtFlag_det = processPar['half'], processPar['device'], processPar['conf_thres'], processPar['iou_thres'],processPar['trtFlag_det']
if 'score_byClass' in processPar.keys(): score_byClass = processPar['score_byClass']
else: score_byClass = None
iou2nd = processPar['iou2nd']
time0=time.time()
if trtFlag_det:
img, padInfos = img_pad(im0s[0], size=(640,640,3)) ;img = [img]
else:
img = [letterbox(x, 640, auto=True, stride=32)[0] for x in im0s];padInfos=None
img = np.stack(img, 0)
# Convert
img = img[:, :, :, ::-1].transpose(0, 3, 1, 2) # BGR to RGB, to bsx3x416x416
img = np.ascontiguousarray(img)
img = torch.from_numpy(img).to(device)
img = img.half() if half else img.float() # uint8 to fp16/32
img /= 255.0 # 0 - 255 to 0.0 - 1.0
seg_pred = None;segFlag=False
time1=time.time()
pred = yolov5Trtforward(model,img) if trtFlag_det else model(img,augment=False)[0]
time2=time.time()
#p_result,timeOut = getDetections(datas,conf_thres, iou_thres,names,label_arraylist,rainbows,10,ObjectPar=ObjectPar,font=font,padInfos=padInfos)
p_result, timeOut = getDetectionsFromPreds(pred,img,im0s[0],conf_thres=conf_thres,iou_thres=iou_thres,ovlap_thres=iou2nd,padInfos=padInfos)
if score_byClass:
p_result[2] = score_filter_byClass(p_result[2],score_byClass)
if segmodel:
seg_pred,segstr = segmodel.eval(im0s[0] )
segFlag=True
else:
seg_pred = None;segFlag=False;segstr='No segmodel'
if segPar and segPar['mixFunction']['function']:
mixFunction = segPar['mixFunction']['function']
H,W = im0s[0].shape[0:2]
parMix = segPar['mixFunction']['pars'];#print('###line117:',parMix,p_result[2])
parMix['imgSize'] = (W,H)
p_result[2],timeInfos_post = mixFunction(p_result[2], seg_pred, pars=parMix )
timeInfos_seg_post = 'segInfer:%s ,postMixProcess:%s'%( segstr, timeInfos_post )
else:
timeInfos_seg_post = ' '
'''
if segmodel:
timeS1=time.time()
#seg_pred,segstr = segtrtEval(segmodel,im0s[0],par=segPar) if segPar['trtFlag_seg'] else segmodel.eval(im0s[0] )
seg_pred,segstr = segmodel.eval(im0s[0] )
timeS2=time.time()
mixFunction = segPar['mixFunction']['function']
p_result[2],timeInfos_post = mixFunction(p_result[2], seg_pred, pars=segPar['mixFunction']['pars'] )
timeInfos_seg_post = 'segInfer:%.1f ,postProcess:%s'%( (timeS2-timeS1)*1000, timeInfos_post )
else:
timeInfos_seg_post = ' '
#print('######line341:',seg_pred.shape,np.max(seg_pred),np.min(seg_pred) , len(p_result[2]) )
'''
time_info = 'letterbox:%.1f, detinfer:%.1f, '%( (time1-time0)*1000,(time2-time1)*1000 )
if sort_tracker:
#在这里增加设置调用追踪器的频率
#..................USE TRACK FUNCTION....................
#pass an empty array to sort
dets_to_sort = np.empty((0,7), dtype=np.float32)
# NOTE: We send in detected object class too
#for detclass,x1,y1,x2,y2,conf in p_result[2]:
for x1,y1,x2,y2,conf, detclass in p_result[2]:
#print('#######line342:',x1,y1,x2,y2,img.shape,[x1, y1, x2, y2, conf, detclass,iframe])
dets_to_sort = np.vstack((dets_to_sort,
np.array([x1, y1, x2, y2, conf, detclass,iframe],dtype=np.float32) ))
# Run SORT
tracked_dets = deepcopy(sort_tracker.update(dets_to_sort) )
tracks =sort_tracker.getTrackers()
p_result.append(tracked_dets) ###index=4
p_result.append(tracks) ###index=5
return p_result,time_info+timeOut+timeInfos_seg_post
def AI_det_track_batch(imgarray_list, iframe_list ,modelPar,processPar,sort_tracker,trackPar,segPar=None):
'''
输入
imgarray_list--图像列表
iframe_list -- 帧号列表
modelPar--模型参数,字典,modelPar={'det_Model':,'seg_Model':}
processPar--字典存放检测相关参数'half', 'device', 'conf_thres', 'iou_thres','trtFlag_det'
sort_tracker--对象初始化的跟踪对象为了保持一致即使是单帧也要有
trackPar--跟踪参数关键字包括det_cntwindowsize
segPar--None,分割模型相关参数如果用不到则为None
输入retResults,timeInfos
retResultslist
retResults[0]--imgarray_list
retResults[1]--所有结果用numpy格式所有的检测结果包括8类每列分别是x1, y1, x2, y2, conf, detclass,iframe,trackId
retResults[2]--所有结果用list表示,其中每一个元素为一个list表示每一帧的检测结果每一个结果是由多个list构成每个list表示一个框格式为[ x0 ,y0 ,x1 ,y1 ,conf, cls ,ifrmae,trackId ] retResults[2][j][k]表示第j帧的第k个框2023.08.03,修改输出格式
'''
det_cnt,windowsize = trackPar['det_cnt'] ,trackPar['windowsize']
trackers_dic={}
index_list = list(range( 0, len(iframe_list) ,det_cnt ));
if len(index_list)>1 and index_list[-1]!= iframe_list[-1]:
index_list.append( len(iframe_list) - 1 )
if len(imgarray_list)==1: #如果是单帧图片,则不用跟踪
retResults = []
p_result,timeOut = AI_det_track( [ [imgarray_list[0]] ,iframe_list[0] ],modelPar,processPar,None,segPar )
##下面4行内容只是为了保持格式一致
detArray = np.array(p_result[2])
#print('##line371:',detArray)
if len(p_result[2])==0:res=[]
else:
cnt = detArray.shape[0];trackIds=np.zeros((cnt,1));iframes = np.zeros((cnt,1)) + iframe_list[0]
#detArray = np.hstack( (detArray[:,1:5], detArray[:,5:6] ,detArray[:,0:1],iframes, trackIds ) )
detArray = np.hstack( (detArray[:,0:4], detArray[:,4:6] ,iframes, trackIds ) ) ##2023.08.03 修改输入格式
res = [[ b[0],b[1],b[2],b[3],b[4],b[5],b[6],b[7] ] for b in detArray ]
retResults=[imgarray_list,detArray,res ]
#print('##line380:',retResults[2])
return retResults,timeOut
else:
t0 = time.time()
timeInfos_track=''
for iframe_index, index_frame in enumerate(index_list):
p_result,timeOut = AI_det_track( [ [imgarray_list[index_frame]] ,iframe_list[index_frame] ],modelPar,processPar,sort_tracker,segPar )
timeInfos_track='%s:%s'%(timeInfos_track,timeOut)
for tracker in p_result[5]:
trackers_dic[tracker.id]=deepcopy(tracker)
t1 = time.time()
track_det_result = np.empty((0,8))
for trackId in trackers_dic.keys():
tracker = trackers_dic[trackId]
bbox_history = np.array(tracker.bbox_history)
if len(bbox_history)<2: continue
###把(x0,y0,x1,y1)转换成(xc,yc,w,h)
xcs_ycs = (bbox_history[:,0:2] + bbox_history[:,2:4] )/2
whs = bbox_history[:,2:4] - bbox_history[:,0:2]
bbox_history[:,0:2] = xcs_ycs;bbox_history[:,2:4] = whs;
arrays_box = bbox_history[:,0:7].transpose();frames=bbox_history[:,6]
#frame_min--表示该批次图片的起始帧,如该批次是[1,100],则frame_min=1[101,200]--frame_min=101
#frames[0]--表示该目标出现的起始帧,如[1,11,21,31,41],则frames[0]=1frames[0]可能会在frame_min之前出现即一个横跨了多个批次。
##如果要最好化插值范围,则取内区间[frame_min,则frame_max ]和[frames[0],frames[-1] ]的交集
#inter_frame_min = int(max(frame_min, frames[0])); inter_frame_max = int(min( frame_max, frames[-1] )) ##
##如果要求得到完整的目标轨迹,则插值区间要以目标出现的起始点为准
inter_frame_min=int(frames[0]);inter_frame_max=int(frames[-1])
new_frames= np.linspace(inter_frame_min,inter_frame_max,inter_frame_max-inter_frame_min+1 )
f_linear = interpolate.interp1d(frames,arrays_box); interpolation_x0s = (f_linear(new_frames)).transpose()
move_cnt_use =(len(interpolation_x0s)+1)//2*2-1 if len(interpolation_x0s)<windowsize else windowsize
for im in range(4):
interpolation_x0s[:,im] = moving_average_wang(interpolation_x0s[:,im],move_cnt_use )
cnt = inter_frame_max-inter_frame_min+1; trackIds = np.zeros((cnt,1)) + trackId
interpolation_x0s = np.hstack( (interpolation_x0s, trackIds ) )
track_det_result = np.vstack(( track_det_result, interpolation_x0s) )
#print('#####line116:',trackId,frame_min,frame_max,'----------',interpolation_x0s.shape,track_det_result.shape ,'-----')
##将[xc,yc,w,h]转为[x0,y0,x1,y1]
x0s = track_det_result[:,0] - track_det_result[:,2]/2 ; x1s = track_det_result[:,0] + track_det_result[:,2]/2
y0s = track_det_result[:,1] - track_det_result[:,3]/2 ; y1s = track_det_result[:,1] + track_det_result[:,3]/2
track_det_result[:,0] = x0s; track_det_result[:,1] = y0s;
track_det_result[:,2] = x1s; track_det_result[:,3] = y1s;
detResults=[]
for iiframe in iframe_list:
boxes_oneFrame = track_det_result[ track_det_result[:,6]==iiframe ]
res = [[ b[0],b[1],b[2],b[3],b[4],b[5],b[6],b[7] ] for b in boxes_oneFrame ]
#[ x0 ,y0 ,x1 ,y1 ,conf,cls,ifrmae,trackId ]
#[ifrmae, x0 ,y0 ,x1 ,y1 ,conf,cls,trackId ]
detResults.append( res )
retResults=[imgarray_list,track_det_result,detResults ]
t2 = time.time()
timeInfos = 'detTrack:%.1f TrackPost:%.1f, %s'%(get_ms(t1,t0),get_ms(t2,t1), timeInfos_track )
return retResults,timeInfos
def AI_det_track_N( im0s_in,modelList,postProcess,sort_tracker):
im0s,iframe=im0s_in[0],im0s_in[1]
dets = AI_process_N(im0s,modelList,postProcess)
p_result=[[],[],dets[0],[] ]
if sort_tracker:
#在这里增加设置调用追踪器的频率
#..................USE TRACK FUNCTION....................
#pass an empty array to sort
dets_to_sort = np.empty((0,7), dtype=np.float32)
# NOTE: We send in detected object class too
#for detclass,x1,y1,x2,y2,conf in p_result[2]:
for x1,y1,x2,y2,conf, detclass in p_result[2]:
#print('#######line342:',x1,y1,x2,y2,img.shape,[x1, y1, x2, y2, conf, detclass,iframe])
dets_to_sort = np.vstack((dets_to_sort,
np.array([x1, y1, x2, y2, conf, detclass,iframe],dtype=np.float32) ))
# Run SORT
tracked_dets = deepcopy(sort_tracker.update(dets_to_sort) )
tracks =sort_tracker.getTrackers()
p_result.append(tracked_dets) ###index=4
p_result.append(tracks) ###index=5
return p_result,dets[1]
def get_tracker_cls(boxes,scId=4,clsId=5):
#正常来说一各跟踪链上是一个类别,但是有时目标框检测错误,导致有的跟踪链上有多个类别
#为此,根据跟踪链上每一个类别对应的所有框的置信度之和,作为这个跟踪链上目标的类别
#输入boxes--跟踪是保留的box_history,[[xc,yc,width,height,score,class,iframe],[...],[...]]
## scId=4,score所在的序号; clsId=5;类别所在的序号
#输出类别
##这个跟踪链上目标的类别
ids = list(set(boxes[:,clsId].tolist()))
scores = [np.sum( boxes[:,scId] [ boxes[:,clsId]==x ] ) for x in ids]
maxScoreId = scores.index(np.max(scores))
return int(ids[maxScoreId])
def AI_det_track_batch_N(imgarray_list, iframe_list ,modelList,postProcess,sort_tracker,trackPar):
'''
输入
imgarray_list--图像列表
iframe_list -- 帧号列表
modelPar--模型参数,字典,modelPar={'det_Model':,'seg_Model':}
processPar--字典存放检测相关参数'half', 'device', 'conf_thres', 'iou_thres','trtFlag_det'
sort_tracker--对象初始化的跟踪对象为了保持一致即使是单帧也要有
trackPar--跟踪参数关键字包括det_cntwindowsize
segPar--None,分割模型相关参数如果用不到则为None
输入retResults,timeInfos
retResultslist
retResults[0]--imgarray_list
retResults[1]--所有结果用numpy格式所有的检测结果包括8类每列分别是x1, y1, x2, y2, conf, detclass,iframe,trackId
retResults[2]--所有结果用list表示,其中每一个元素为一个list表示每一帧的检测结果每一个结果是由多个list构成每个list表示一个框格式为[ x0 ,y0 ,x1 ,y1 ,conf, cls ,ifrmae,trackId ] retResults[2][j][k]表示第j帧的第k个框2023.08.03,修改输出格式
'''
det_cnt,windowsize = trackPar['det_cnt'] ,trackPar['windowsize']
trackers_dic={}
index_list = list(range( 0, len(iframe_list) ,det_cnt ));
if len(index_list)>1 and index_list[-1]!= iframe_list[-1]:
index_list.append( len(iframe_list) - 1 )
if len(imgarray_list)==1: #如果是单帧图片,则不用跟踪
retResults = []
p_result,timeOut = AI_det_track_N( [ [imgarray_list[0]] ,iframe_list[0] ],modelList,postProcess,None )
##下面4行内容只是为了保持格式一致
detArray = np.array(p_result[2])
if len(p_result[2])==0:res=[]
else:
cnt = detArray.shape[0];trackIds=np.zeros((cnt,1));iframes = np.zeros((cnt,1)) + iframe_list[0]
#detArray = np.hstack( (detArray[:,1:5], detArray[:,5:6] ,detArray[:,0:1],iframes, trackIds ) )
detArray = np.hstack( (detArray[:,0:4], detArray[:,4:6] ,iframes, trackIds ) ) ##2023.08.03 修改输入格式
res = [[ b[0],b[1],b[2],b[3],b[4],b[5],b[6],b[7] ] for b in detArray ]
retResults=[imgarray_list,detArray,res ]
#print('##line380:',retResults[2])
return retResults,timeOut
else:
t0 = time.time()
timeInfos_track=''
for iframe_index, index_frame in enumerate(index_list):
p_result,timeOut = AI_det_track_N( [ [imgarray_list[index_frame]] ,iframe_list[index_frame] ],modelList,postProcess,sort_tracker )
timeInfos_track='%s:%s'%(timeInfos_track,timeOut)
for tracker in p_result[5]:
trackers_dic[tracker.id]=deepcopy(tracker)
t1 = time.time()
track_det_result = np.empty((0,8))
for trackId in trackers_dic.keys():
tracker = trackers_dic[trackId]
bbox_history = np.array(tracker.bbox_history).copy()
if len(bbox_history)<2: continue
###把(x0,y0,x1,y1)转换成(xc,yc,w,h)
xcs_ycs = (bbox_history[:,0:2] + bbox_history[:,2:4] )/2
whs = bbox_history[:,2:4] - bbox_history[:,0:2]
bbox_history[:,0:2] = xcs_ycs;bbox_history[:,2:4] = whs;
#2023.11.17添加的。目的是修正跟踪链上所有的框的类别一样
chainClsId = get_tracker_cls(bbox_history,scId=4,clsId=5)
bbox_history[:,5] = chainClsId
arrays_box = bbox_history[:,0:7].transpose();frames=bbox_history[:,6]
#frame_min--表示该批次图片的起始帧,如该批次是[1,100],则frame_min=1[101,200]--frame_min=101
#frames[0]--表示该目标出现的起始帧,如[1,11,21,31,41],则frames[0]=1frames[0]可能会在frame_min之前出现即一个横跨了多个批次。
##如果要最好化插值范围,则取内区间[frame_min,则frame_max ]和[frames[0],frames[-1] ]的交集
#inter_frame_min = int(max(frame_min, frames[0])); inter_frame_max = int(min( frame_max, frames[-1] )) ##
##如果要求得到完整的目标轨迹,则插值区间要以目标出现的起始点为准
inter_frame_min=int(frames[0]);inter_frame_max=int(frames[-1])
new_frames= np.linspace(inter_frame_min,inter_frame_max,inter_frame_max-inter_frame_min+1 )
f_linear = interpolate.interp1d(frames,arrays_box); interpolation_x0s = (f_linear(new_frames)).transpose()
move_cnt_use =(len(interpolation_x0s)+1)//2*2-1 if len(interpolation_x0s)<windowsize else windowsize
for im in range(4):
interpolation_x0s[:,im] = moving_average_wang(interpolation_x0s[:,im],move_cnt_use )
cnt = inter_frame_max-inter_frame_min+1; trackIds = np.zeros((cnt,1)) + trackId
interpolation_x0s = np.hstack( (interpolation_x0s, trackIds ) )
track_det_result = np.vstack(( track_det_result, interpolation_x0s) )
#print('#####line116:',trackId,'----------',interpolation_x0s.shape,track_det_result.shape,bbox_history ,'-----')
##将[xc,yc,w,h]转为[x0,y0,x1,y1]
x0s = track_det_result[:,0] - track_det_result[:,2]/2 ; x1s = track_det_result[:,0] + track_det_result[:,2]/2
y0s = track_det_result[:,1] - track_det_result[:,3]/2 ; y1s = track_det_result[:,1] + track_det_result[:,3]/2
track_det_result[:,0] = x0s; track_det_result[:,1] = y0s;
track_det_result[:,2] = x1s; track_det_result[:,3] = y1s;
detResults=[]
for iiframe in iframe_list:
boxes_oneFrame = track_det_result[ track_det_result[:,6]==iiframe ]
res = [[ b[0],b[1],b[2],b[3],b[4],b[5],b[6],b[7] ] for b in boxes_oneFrame ]
#[ x0 ,y0 ,x1 ,y1 ,conf,cls,ifrmae,trackId ]
#[ifrmae, x0 ,y0 ,x1 ,y1 ,conf,cls,trackId ]
detResults.append( res )
retResults=[imgarray_list,track_det_result,detResults ]
t2 = time.time()
timeInfos = 'detTrack:%.1f TrackPost:%.1f, %s'%(get_ms(t1,t0),get_ms(t2,t1), timeInfos_track )
return retResults,timeInfos
def ocr_process(pars):
img_patch,engine,context,converter,AlignCollate_normal,device=pars[0:6]
time1 = time.time()
img_tensor = AlignCollate_normal([ Image.fromarray(img_patch,'L') ])
img_input = img_tensor.to('cuda:0')
time2 = time.time()
preds,trtstr=OcrTrtForward(engine,[img_input],context)
time3 = time.time()
batch_size = preds.size(0)
preds_size = torch.IntTensor([preds.size(1)] * batch_size)
######## filter ignore_char, rebalance
preds_prob = F.softmax(preds, dim=2)
preds_prob = preds_prob.cpu().detach().numpy()
pred_norm = preds_prob.sum(axis=2)
preds_prob = preds_prob/np.expand_dims(pred_norm, axis=-1)
preds_prob = torch.from_numpy(preds_prob).float().to(device)
_, preds_index = preds_prob.max(2)
preds_index = preds_index.view(-1)
time4 = time.time()
preds_str = converter.decode_greedy(preds_index.data.cpu().detach().numpy(), preds_size.data)
time5 = time.time()
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 ) )
return preds_str,info_str
def main():
##预先设置的参数
device_='1' ##选定模型,可选 cpu,'0','1'
##以下参数目前不可改
Detweights = "weights/yolov5/class5/best_5classes.pt"
seg_nclass = 2
Segweights = "weights/BiSeNet/checkpoint.pth"
conf_thres,iou_thres,classes= 0.25,0.45,5
labelnames = "weights/yolov5/class5/labelnames.json"
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]]
allowedList=[0,1,2,3]
##加载模型,准备好显示字符
device = select_device(device_)
names=get_labelnames(labelnames)
label_arraylist = get_label_arrays(names,rainbows,outfontsize=40,fontpath="conf/platech.ttf")
half = device.type != 'cpu' # half precision only supported on CUDA
model = attempt_load(Detweights, map_location=device) # load FP32 model
if half: model.half()
segmodel = SegModel(nclass=seg_nclass,weights=Segweights,device=device)
##图像测试
#url='images/examples/20220624_响水河_12300_1621.jpg'
impth = 'images/examples/'
outpth = 'images/results/'
folders = os.listdir(impth)
for i in range(len(folders)):
imgpath = os.path.join(impth, folders[i])
im0s=[cv2.imread(imgpath)]
time00 = time.time()
p_result,timeOut = AI_process(im0s,model,segmodel,names,label_arraylist,rainbows,half,device,conf_thres, iou_thres,allowedList,fontSize=1.0)
time11 = time.time()
image_array = p_result[1]
cv2.imwrite( os.path.join( outpth,folders[i] ) ,image_array )
#print('----process:%s'%(folders[i]), (time.time() - time11) * 1000)
if __name__=="__main__":
main()

45
DMPR.py Normal file
View File

@ -0,0 +1,45 @@
from DMPRUtils.DMPR_process import DMPR_process
import tensorrt as trt
import sys,os
#from DMPRUtils.model.detector import DirectionalPointDetector
from DMPRUtils.yolo_net import Model
import torch
class DMPRModel(object):
def __init__(self, weights=None,
par={'depth_factor':32,'NUM_FEATURE_MAP_CHANNEL':6,'dmpr_thresh':0.3, 'dmprimg_size':640}
):
self.par = par
self.device = 'cuda:0'
self.half =True
if weights.endswith('.engine'):
self.infer_type ='trt'
elif weights.endswith('.pth') or weights.endswith('.pt') :
self.infer_type ='pth'
else:
print('#########ERROR:',weights,': no registered inference type, exit')
sys.exit(0)
if self.infer_type=='trt':
logger = trt.Logger(trt.Logger.ERROR)
with open(weights, "rb") as f, trt.Runtime(logger) as runtime:
self.model=runtime.deserialize_cuda_engine(f.read())# 输入trt本地文件返回ICudaEngine对象
elif self.infer_type=='pth':
#self.model = DirectionalPointDetector(3, self.par['depth_factor'], self.par['NUM_FEATURE_MAP_CHANNEL']).to(self.device)
confUrl = os.path.join( os.path.dirname(__file__),'DMPRUtils','config','yolov5s.yaml' )
self.model = Model(confUrl, ch=3).to(self.device)
self.model.load_state_dict(torch.load(weights))
print('#######load pt model:%s success '%(weights))
self.par['modelType']=self.infer_type
print('#########加载模型:',weights,' 类型:',self.infer_type)
def eval(self,image):
det,timeInfos = DMPR_process(image, self.model, self.device, self.par)
det = det.cpu().detach().numpy()
return det,timeInfos
def get_ms(self,t1,t0):
return (t1-t0)*1000.0

231
DMPRUtils/DMPR_process.py Normal file
View File

@ -0,0 +1,231 @@
import math
import os
import time
from collections import namedtuple
import cv2
import numpy as np
import torch
from torchvision.transforms import ToTensor
from DMPRUtils.model import DirectionalPointDetector
from utils.datasets import letterbox
from utils.general import clip_coords
from utils.torch_utils import select_device
#from DMPRUtils.trtUtils import TrtForwardCase
#import segutils.trtUtils.segTrtForward as TrtForwardCase
from segutils.trtUtils import segTrtForward
MarkingPoint = namedtuple('MarkingPoint', ['x', 'y', 'direction', 'shape'])
def plot_points(image, pred_points, line_thickness=3):
"""Plot marking points on the image."""
if len(pred_points):
tl = line_thickness or round(0.002 * (image.shape[0] + image.shape[1]) / 2) + 1 # line/font thickness
tf = max(tl - 1, 1) # font thickness
for conf, *point in pred_points:
p0_x, p0_y = int(point[0]), int(point[1])
cos_val = math.cos(point[2])
sin_val = math.sin(point[2])
p1_x = int(p0_x + 20 * cos_val * tl)
p1_y = int(p0_y + 20 * sin_val * tl)
p2_x = int(p0_x - 10 * sin_val * tl)
p2_y = int(p0_y + 10 * cos_val * tl)
p3_x = int(p0_x + 10 * sin_val * tl)
p3_y = int(p0_y - 10 * cos_val * tl)
cv2.line(image, (p0_x, p0_y), (p1_x, p1_y), (0, 0, 255), thickness=tl)
cv2.putText(image, str(float(conf)), (p0_x, p0_y), cv2.FONT_HERSHEY_PLAIN, 1, (0, 0, 0), thickness=tf)
if point[3] > 0.5:
cv2.line(image, (p0_x, p0_y), (p2_x, p2_y), (0, 0, 255), thickness=tl)
else:
cv2.line(image, (p2_x, p2_y), (p3_x, p3_y), (0, 0, 255), thickness=tf)
def preprocess_image(image):
"""Preprocess numpy image to torch tensor."""
if image.shape[0] != 640 or image.shape[1] != 640:
image = cv2.resize(image, (640, 640))
return torch.unsqueeze(ToTensor()(image), 0)
def non_maximum_suppression(pred_points):
"""Perform non-maxmum suppression on marking points."""
t1 = time.time()
suppressed = [False] * len(pred_points)
for i in range(len(pred_points) - 1):
for j in range(i + 1, len(pred_points)):
i_x = pred_points[i][1].x
i_y = pred_points[i][1].y
j_x = pred_points[j][1].x
j_y = pred_points[j][1].y
# 0.0625 = 1 / 16
if abs(j_x - i_x) < 0.0625 and abs(j_y - i_y) < 0.0625:
idx = i if pred_points[i][0] < pred_points[j][0] else j
suppressed[idx] = True
if any(suppressed):
unsupres_pred_points = []
for i, supres in enumerate(suppressed):
if not supres:
unsupres_pred_points.append(pred_points[i])
return unsupres_pred_points
t2 = time.time()
print(f'nms: {t2 - t1:.3f}s')
return pred_points
def ms(t2,t1):
return ('%.1f '%( (t2-t1)*1000 ) )
def get_predicted_points(prediction, thresh):
"""Get marking points from one predicted feature map."""
t1 = time.time()
assert isinstance(prediction, torch.Tensor)
prediction = prediction.permute(1, 2, 0).contiguous() # prediction (20, 20, 6)
height = prediction.shape[0]
width = prediction.shape[1]
j = torch.arange(prediction.shape[1], device=prediction.device).float().repeat(prediction.shape[0], 1).unsqueeze(dim=2)
i = torch.arange(prediction.shape[0], device=prediction.device).float().view(prediction.shape[0], 1).repeat(1,prediction.shape[1]).unsqueeze(dim=2)
prediction = torch.cat((prediction, j, i), dim=2).view(-1, 8).contiguous()
t2 = time.time()
# 过滤小于thresh的置信度
mask = prediction[..., 0] > thresh
t3 = time.time()
prediction = prediction[mask]
t4 = time.time()
prediction[..., 2] = (prediction[..., 2] + prediction[..., 6]) / width
prediction[..., 3] = (prediction[..., 3] + prediction[..., 7]) / height
direction = torch.atan2(prediction[..., 5], prediction[..., 4])
prediction = torch.stack((prediction[..., 0], prediction[..., 2], prediction[..., 3], direction, prediction[..., 1]), dim=1)
t5 = time.time()
timeInfo = 'rerange:%s scoreFilter:%s , getMask:%s stack:%s '%( ms(t2,t1),ms(t3,t2),ms(t4,t3),ms(t5,t4) )
#print('-'*20,timeInfo)
return prediction,timeInfo
def get_predicted_points_np(prediction, thresh):
"""Get marking points from one predicted feature map."""
t1 = time.time()
prediction = prediction.permute(1, 2, 0).contiguous() # prediction (20, 20, 6)
t1_1 = time.time()
prediction = prediction.cpu().detach().numpy()
t1_2 = time.time()
height,width = prediction.shape[0:2]
i,j = np.mgrid[0:height, 0:width]
i = np.expand_dims(i,axis=2);j = np.expand_dims(j,axis=2)
#print('##line112:',i.shape,j.shape,prediction.shape)
prediction = np.concatenate( (prediction,i,j),axis=2 )
prediction = prediction.reshape(-1,8)
t2 = time.time()
mask = prediction[..., 0] > thresh
t3 = time.time()
prediction = prediction[mask]
t4 = time.time()
prediction[..., 2] = (prediction[..., 2] + prediction[..., 6]) / width
prediction[..., 3] = (prediction[..., 3] + prediction[..., 7]) / height
direction = np.arctan(prediction[..., 5:6], prediction[..., 4:5])
#print('-'*20,prediction.shape,direction.shape)
prediction = np.hstack((prediction[:, 0:1], prediction[:, 2:3], prediction[:, 3:4], direction, prediction[:, 1:2]))
#print('-line126:','-'*20,type(prediction),prediction.shape)
t5 = time.time()
timeInfo = 'permute:%s Tocpu:%s rerange:%s scoreFilter:%s , getMask:%s stack:%s '%( ms(t1_1,t1) , ms(t1_2,t1_1),ms(t2,t1_2),ms(t3,t2),ms(t4,t3),ms(t5,t4) )
print('-'*20,timeInfo,prediction.shape)
return prediction
def detect_marking_points(detector, image, thresh, device,modelType='pth'):
"""Given image read from opencv, return detected marking points."""
t1 = time.time()
image_preprocess = preprocess_image(image).to(device)
if modelType=='pth':
prediction = detector(image_preprocess)
#print(prediction)
elif modelType=='trt':
a=0
prediction = segTrtForward(detector,[image_preprocess ])
#print(prediction)
torch.cuda.synchronize(device)
t2 = time.time()
rets,timeInfo = get_predicted_points(prediction[0], thresh)
string_t2 = ' infer:%s postprocess:%s'%(ms(t2,t1),timeInfo)
return rets
def scale_coords2(img1_shape, coords, img0_shape, ratio_pad=None):
# Rescale coords (xy) from img1_shape to img0_shape
if ratio_pad is None: # calculate from img0_shape
gain = min(img1_shape[0] / img0_shape[0], img1_shape[1] / img0_shape[1]) # gain = old / new
pad = (img1_shape[1] - img0_shape[1] * gain) / 2, (img1_shape[0] - img0_shape[0] * gain) / 2 # wh padding
else:
gain = ratio_pad[0][0]
pad = ratio_pad[1]
# 百分比xy转换为实际xy
height, width = img1_shape
if isinstance(coords, torch.Tensor):
coords[:, 0] = torch.round(width * coords[:, 0] - 0.5)
coords[:, 1] = torch.round(height * coords[:, 1] - 0.5)
else:
coords[:, 0] = (width * coords[:, 0] + 0.5).astype(np.int32)
coords[:, 1] = (height * coords[:, 1] + 0.5).astype(np.int32)
coords[:, 0] -= pad[0] # x padding
coords[:, 1] -= pad[1] # y padding
coords[:, :3] /= gain
#恢复成原始图片尺寸
if isinstance(coords, torch.Tensor):
coords[:, 0].clamp_(0, img0_shape[1])
coords[:, 1].clamp_(0, img0_shape[0])
else:
coords[:, 0] = np.clip( coords[:, 0], 0,img0_shape[1] )
coords[:, 1] = np.clip( coords[:, 1], 0,img0_shape[0] )
return coords
def DMPR_process(img0, model, device, DMPRmodelPar):
t0 = time.time()
height, width, _ = img0.shape
img, ratio, (dw, dh) = letterbox(img0, DMPRmodelPar['dmprimg_size'], auto=False)
t1 = time.time()
#print('###line188:', height, width, img.shape)
det = detect_marking_points(model, img, DMPRmodelPar['dmpr_thresh'], device,modelType=DMPRmodelPar['modelType'])
t2 = time.time()
if len(det):
det[:, 1:3] = scale_coords2(img.shape[:2], det[:, 1:3], img0.shape)
t3 = time.time()
timeInfos = 'dmpr:%1.f (lettbox:%.1f dectect:%.1f scaleBack:%.1f) '%( (t3-t0)*1000,(t1-t0)*1000,(t2-t1)*1000,(t3-t2)*1000, )
return det,timeInfos
if __name__ == '__main__':
impath = r'I:\zjc\weiting1\Images'
file = 'DJI_0001_8.jpg'
imgpath = os.path.join(impath, file)
img0 = cv2.imread(imgpath)
device_ = '0'
device = select_device(device_)
args = config.get_parser_for_inference().parse_args()
model = DirectionalPointDetector(3, args.depth_factor, config.NUM_FEATURE_MAP_CHANNEL).to(device)
weights = r"E:\pycharmProject\DMPR-PS\weights\dp_detector_499.pth"
model.load_state_dict(torch.load(weights))
det = DMPR_process(img0, model, device, args)
plot_points(img0, det)
cv2.imwrite(file, img0, [int(cv2.IMWRITE_JPEG_QUALITY), 100])

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,48 @@
# parameters
nc: 80 # number of classes
depth_multiple: 1.0 # model depth multiple
width_multiple: 1.0 # layer channel multiple
# anchors
anchors:
- [10,13, 16,30, 33,23] # P3/8
- [30,61, 62,45, 59,119] # P4/16
- [116,90, 156,198, 373,326] # P5/32
# YOLOv5 backbone
backbone:
# [from, number, module, args]
[[-1, 1, Focus, [64, 3]], # 0-P1/2
[-1, 1, Conv, [128, 3, 2]], # 1-P2/4
[-1, 3, C3, [128]],
[-1, 1, Conv, [256, 3, 2]], # 3-P3/8
[-1, 9, C3, [256]],
[-1, 1, Conv, [512, 3, 2]], # 5-P4/16
[-1, 9, C3, [512]],
[-1, 1, Conv, [1024, 3, 2]], # 7-P5/32
[-1, 1, SPP, [1024, [5, 9, 13]]],
[-1, 3, C3, [1024, False]], # 9
]
# YOLOv5 head
head:
[[-1, 1, Conv, [512, 1, 1]],
[-1, 1, nn.Upsample, [None, 2, 'nearest']],
[[-1, 6], 1, Concat, [1]], # cat backbone P4
[-1, 3, C3, [512, False]], # 13
[-1, 1, Conv, [256, 1, 1]],
[-1, 1, nn.Upsample, [None, 2, 'nearest']],
[[-1, 4], 1, Concat, [1]], # cat backbone P3
[-1, 3, C3, [256, False]], # 17 (P3/8-small)
[-1, 1, Conv, [256, 3, 2]],
[[-1, 14], 1, Concat, [1]], # cat head P4
[-1, 3, C3, [512, False]], # 20 (P4/16-medium)
[-1, 1, Conv, [512, 3, 2]],
[[-1, 10], 1, Concat, [1]], # cat head P5
[-1, 3, C3, [1024, False]], # 23 (P5/32-large)
[[17, 20, 23], 1, Detect, [nc, anchors]], # Detect(P3, P4, P5)
]

View File

@ -0,0 +1,48 @@
# parameters
nc: 80 # number of classes
depth_multiple: 0.67 # model depth multiple
width_multiple: 0.75 # layer channel multiple
# anchors
anchors:
- [10,13, 16,30, 33,23] # P3/8
- [30,61, 62,45, 59,119] # P4/16
- [116,90, 156,198, 373,326] # P5/32
# YOLOv5 backbone
backbone:
# [from, number, module, args]
[[-1, 1, Focus, [64, 3]], # 0-P1/2
[-1, 1, Conv, [128, 3, 2]], # 1-P2/4
[-1, 3, C3, [128]],
[-1, 1, Conv, [256, 3, 2]], # 3-P3/8
[-1, 9, C3, [256]],
[-1, 1, Conv, [512, 3, 2]], # 5-P4/16
[-1, 9, C3, [512]],
[-1, 1, Conv, [1024, 3, 2]], # 7-P5/32
[-1, 1, SPP, [1024, [5, 9, 13]]],
[-1, 3, C3, [1024, False]], # 9
]
# YOLOv5 head
head:
[[-1, 1, Conv, [512, 1, 1]],
[-1, 1, nn.Upsample, [None, 2, 'nearest']],
[[-1, 6], 1, Concat, [1]], # cat backbone P4
[-1, 3, C3, [512, False]], # 13
[-1, 1, Conv, [256, 1, 1]],
[-1, 1, nn.Upsample, [None, 2, 'nearest']],
[[-1, 4], 1, Concat, [1]], # cat backbone P3
[-1, 3, C3, [256, False]], # 17 (P3/8-small)
[-1, 1, Conv, [256, 3, 2]],
[[-1, 14], 1, Concat, [1]], # cat head P4
[-1, 3, C3, [512, False]], # 20 (P4/16-medium)
[-1, 1, Conv, [512, 3, 2]],
[[-1, 10], 1, Concat, [1]], # cat head P5
[-1, 3, C3, [1024, False]], # 23 (P5/32-large)
[[17, 20, 23], 1, Detect, [nc, anchors]], # Detect(P3, P4, P5)
]

View File

@ -0,0 +1,48 @@
# parameters
nc: 80 # number of classes
depth_multiple: 0.33 # model depth multiple
width_multiple: 0.50 # layer channel multiple
# anchors
anchors:
- [10,13, 16,30, 33,23] # P3/8
- [30,61, 62,45, 59,119] # P4/16
- [116,90, 156,198, 373,326] # P5/32
# YOLOv5 backbone
backbone:
# [from, number, module, args]
[[-1, 1, Focus, [64, 3]], # 0-P1/2
[-1, 1, Conv, [128, 3, 2]], # 1-P2/4
[-1, 3, C3, [128]],
[-1, 1, Conv, [256, 3, 2]], # 3-P3/8
[-1, 9, C3, [256]],
[-1, 1, Conv, [512, 3, 2]], # 5-P4/16
[-1, 9, C3, [512]],
[-1, 1, Conv, [1024, 3, 2]], # 7-P5/32
[-1, 1, SPP, [1024, [5, 9, 13]]],
[-1, 3, C3, [1024, False]], # 9
]
# YOLOv5 head
head:
[[-1, 1, Conv, [512, 1, 1]],
[-1, 1, nn.Upsample, [None, 2, 'nearest']],
[[-1, 6], 1, Concat, [1]], # cat backbone P4
[-1, 3, C3, [512, False]], # 13
[-1, 1, Conv, [256, 1, 1]],
[-1, 1, nn.Upsample, [None, 2, 'nearest']],
[[-1, 4], 1, Concat, [1]], # cat backbone P3
[-1, 3, C3, [256, False]], # 17 (P3/8-small)
[-1, 1, Conv, [256, 3, 2]],
[[-1, 14], 1, Concat, [1]], # cat head P4
[-1, 3, C3, [512, False]], # 20 (P4/16-medium)
[-1, 1, Conv, [512, 3, 2]],
[[-1, 10], 1, Concat, [1]], # cat head P5
[-1, 3, C3, [1024, False]], # 23 (P5/32-large)
[[17, 20, 23], 1, Detect, [nc, anchors]], # Detect(P3, P4, P5)
]

View File

@ -0,0 +1,48 @@
# parameters
nc: 80 # number of classes
depth_multiple: 1.33 # model depth multiple
width_multiple: 1.25 # layer channel multiple
# anchors
anchors:
- [10,13, 16,30, 33,23] # P3/8
- [30,61, 62,45, 59,119] # P4/16
- [116,90, 156,198, 373,326] # P5/32
# YOLOv5 backbone
backbone:
# [from, number, module, args]
[[-1, 1, Focus, [64, 3]], # 0-P1/2
[-1, 1, Conv, [128, 3, 2]], # 1-P2/4
[-1, 3, C3, [128]],
[-1, 1, Conv, [256, 3, 2]], # 3-P3/8
[-1, 9, C3, [256]],
[-1, 1, Conv, [512, 3, 2]], # 5-P4/16
[-1, 9, C3, [512]],
[-1, 1, Conv, [1024, 3, 2]], # 7-P5/32
[-1, 1, SPP, [1024, [5, 9, 13]]],
[-1, 3, C3, [1024, False]], # 9
]
# YOLOv5 head
head:
[[-1, 1, Conv, [512, 1, 1]],
[-1, 1, nn.Upsample, [None, 2, 'nearest']],
[[-1, 6], 1, Concat, [1]], # cat backbone P4
[-1, 3, C3, [512, False]], # 13
[-1, 1, Conv, [256, 1, 1]],
[-1, 1, nn.Upsample, [None, 2, 'nearest']],
[[-1, 4], 1, Concat, [1]], # cat backbone P3
[-1, 3, C3, [256, False]], # 17 (P3/8-small)
[-1, 1, Conv, [256, 3, 2]],
[[-1, 14], 1, Concat, [1]], # cat head P4
[-1, 3, C3, [512, False]], # 20 (P4/16-medium)
[-1, 1, Conv, [512, 3, 2]],
[[-1, 10], 1, Concat, [1]], # cat head P5
[-1, 3, C3, [1024, False]], # 23 (P5/32-large)
[[17, 20, 23], 1, Detect, [nc, anchors]], # Detect(P3, P4, P5)
]

149
DMPRUtils/jointUtil.py Normal file
View File

@ -0,0 +1,149 @@
import math
import numpy as np
import torch
import time
def dmpr_yolo( yolo_det, dmpr_det,pars):
#if len(yolo_det)==0 or len(dmpr_det)==0:
#print('line11:\n',yolo_det, dmpr_det,pars)
time1=time.time()
if len(yolo_det)==0:
return yolo_det,' No yolo detections'
img_shape = (pars['imgSize'][1],pars['imgSize'][0])
cls = pars['carCls']; scaleRatio = pars['scaleRatio']
illParkCls = pars['illCls'];border = pars['border']
yolo_det = np.array(yolo_det)
yolo_det_0 = yolo_det.copy()
#print('-'*10,'line17',yolo_det_0)
# 过滤在图像边界的box(防止出现类似一小半车辆的情况)
x_c = (yolo_det[:, 0] + yolo_det[:, 2]) / 2
y_c = (yolo_det[:, 1] + yolo_det[:, 3]) / 2
tmp = (x_c >= border) & (x_c <= (img_shape[1] - border)) & (y_c >= border) & (y_c <= (img_shape[0] - border))
yolo_det = yolo_det[tmp]
# 创建yolo_det_clone内容为x1, y1, x2, y2, conf, cls, unlabel (unlabel代表该类是否需要忽略0不忽略 其他:忽略)
yolo_det_clone = yolo_det.copy()
tmp_0_tensor = np.zeros([len(yolo_det), 1])
yolo_det_clone = np.concatenate([yolo_det_clone, tmp_0_tensor], axis=1)
# cls为需要计算的类别
yolo_det = yolo_det[yolo_det[:, -1] == cls]
# new_yolo_det为膨胀后数据内容为x1, y1, x2, y2, flag (flag代表膨胀后车位内是否包含角点 且 与角点方向差值小于90度, 其值为第一个满足条件的角点索引)
new_yolo_det = np.zeros([len(yolo_det), 7])
# yolo框膨胀长的边两边各膨胀0.4倍总长短的边两边各膨胀0.2倍总长
x_length = yolo_det[:, 2] - yolo_det[:, 0] #x2-x1
y_length = yolo_det[:, 3] - yolo_det[:, 1] #y2-y1
# x, y哪个方向差值大哪个方向膨胀的多
x_dilate_coefficient = ((x_length > y_length) + 1)*scaleRatio
y_dilate_coefficient = ((~(x_length > y_length)) + 1)*scaleRatio
# 原始框中心点x_c, y_c
new_yolo_det[:, 5] = (yolo_det[:, 0] + yolo_det[:, 2]) / 2
new_yolo_det[:, 6] = (yolo_det[:, 1] + yolo_det[:, 3]) / 2
# 膨胀
new_yolo_det[:, 0] = np.round(yolo_det[:, 0] - x_dilate_coefficient * x_length).clip(0, img_shape[1]) #x1 膨胀
new_yolo_det[:, 1] = np.round(yolo_det[:, 1] - y_dilate_coefficient * y_length).clip(0, img_shape[0]) #y1 膨胀
new_yolo_det[:, 2] = np.round(yolo_det[:, 2] + x_dilate_coefficient * x_length).clip(0, img_shape[1]) #x2 膨胀
new_yolo_det[:, 3] = np.round(yolo_det[:, 3] + y_dilate_coefficient * y_length).clip(0, img_shape[0]) #y2 膨胀
m, n = new_yolo_det.size, dmpr_det.size
if not m or not n:
#print('##line47 original yolo_det_clone:',yolo_det_clone)
yolo_det_clone[np.logical_and( yolo_det_clone[:,-1]==0,yolo_det_clone[:,-2]==cls),-2] = illParkCls
#yolo_det_clone[yolo_det_clone[:, -1] == 0 & yolo_det_clone[:, -2==cls] , -2] = illParkCls
return yolo_det_clone[:,0:6], ' no cars or T/L corners'
new_yolo = new_yolo_det[:, np.newaxis, :].repeat(dmpr_det.shape[0], 1) # 扩展为 (m , n, 5)
dmpr_det = dmpr_det[np.newaxis, ...].repeat(new_yolo_det.shape[0], 0)
yolo_dmpr = np.concatenate((new_yolo, dmpr_det), axis=2) # (m, n, 10)
x_p, y_p = yolo_dmpr[..., 8], yolo_dmpr[..., 9]
x1, y1, x2, y2 = yolo_dmpr[..., 0], yolo_dmpr[..., 1], yolo_dmpr[..., 2], yolo_dmpr[..., 3]
x_c, y_c = yolo_dmpr[..., 5], yolo_dmpr[..., 6]
direction1 = np.arctan2(y_c - y_p, x_c - x_p) / math.pi * 180
direction2 = yolo_dmpr[..., 10] / math.pi * 180
direction3 = direction2 + 90 # L形角点另外一个方向
direction3[direction3 > 180] -= 360
ang_diff = direction1 - direction2
ang_diff2 = direction1 - direction3
# 判断膨胀后yolo框包含角点关系 && 包含角点的时候计算水平框中心点与角点的角度关系
# direction ∈ -180 180 若角差大于180需算补角
# T形角点比较一个方向L形角点比较两个方向
mask = (x_p >= x1) & (x_p <= x2) & (y_p >= y1) & (y_p <= y2) & \
(((yolo_dmpr[..., 11] <= 0.5) & # T形角点情况
(((ang_diff >= -90) & (ang_diff <= 90)) | ((ang_diff > 180) & ((360 - ang_diff) <= 90)) |
(((ang_diff) < -180) & ((360 + ang_diff) <= 90)))) |
((yolo_dmpr[..., 11] > 0.5) & # L形角点情况
(((ang_diff >= -90) & (ang_diff <= 90)) | ((ang_diff > 180) & ((360 - ang_diff) <= 90)) |
(((ang_diff) < -180) & ((360 + ang_diff) <= 90))) &
(((ang_diff2 >= -90) & (ang_diff2 <= 90)) | ((ang_diff2 > 180) & ((360 - ang_diff2) <= 90)) |
(((ang_diff2) < -180) & ((360 + ang_diff2) <= 90)))))
res = np.sum(mask, axis=1)
yolo_det_clone[yolo_det_clone[:, -2] == cls, -1] = res
#print('##line69 original yolo_det_clone:',yolo_det_clone)
#yolo_det_clone[yolo_det_clone[:, -1] == 0, -2] = illParkCls
#print('-'*20,'--line78',yolo_det_clone)
yolo_det_clone[ np.logical_and( yolo_det_clone[:,-1]==0,yolo_det_clone[:,-2]==cls) ,-2 ] = illParkCls
#print('-'*20,'--line80:',yolo_det_clone)
yolo_det_clone = yolo_det_clone[:,0:6]
time2=time.time()
return np.array(yolo_det_clone), 'dmpr_yolo:%.1f'%( (time2-time1)*1000 )
def stdc_yolo(stdc_det, yolo_det,pars):
is_car = yolo_det[:, -1] == pars['carCls'] # 获取最后一列判断是否等于0
car = yolo_det[is_car] # 筛选出最后一列等于0的行
no_car = yolo_det[~is_car] # 筛选出最后一列不等于0的行
im = np.uint8(stdc_det)
x_c = ((car[:, 0] + car[:, 2]) // 2).astype(int)
y_c = ((car[:, 1] + car[:, 3]) // 2).astype(int)
car_filted = car[im[y_c, x_c] == 0]
#yolo_filted = yolo_det
yolo_filted = np.concatenate((car_filted, no_car), axis=0)
return yolo_filted
def dmpr_yolo_stdc(predsList,pars):
if len(predsList)==2:
yolo_det, dmpr_det = predsList[0:2]
else:
yolo_det, dmpr_det,stdc_det = predsList[0:3]
if len(yolo_det)==0:
return yolo_det,' No yolo detections'
if isinstance(yolo_det,list):
yolo_det = np.array(yolo_det)
if len(predsList)>2:
yolo_det = stdc_yolo(stdc_det, yolo_det,pars)
rets = dmpr_yolo(yolo_det, dmpr_det,pars)
for i,ret in enumerate(rets[0]):
#print(ret,'\n ',rets,pars['classReindex'])
ret[5] = pars['classReindex'][ret[5]]
#rets[i][5] = pars['classReindex'][ret[5]]
return rets

142
DMPRUtils/jointUtilbak.py Normal file
View File

@ -0,0 +1,142 @@
import math
import numpy as np
import torch
import time
from loguru import logger
def dmpr_yolo( yolo_det, dmpr_det,pars):
#if len(yolo_det)==0 or len(dmpr_det)==0:
#print('line11:\n',yolo_det, dmpr_det,pars)
time1=time.time()
if len(yolo_det)==0:
return yolo_det,' No yolo detections'
img_shape = (pars['imgSize'][1],pars['imgSize'][0])
cls = pars['carCls']; scaleRatio = pars['scaleRatio']
illParkCls = pars['illCls'];border = pars['border']
yolo_det = np.array(yolo_det)
yolo_det_0 = yolo_det.copy()
#print('-'*10,'line17',yolo_det_0)
# 过滤在图像边界的box(防止出现类似一小半车辆的情况)
x_c = (yolo_det[:, 0] + yolo_det[:, 2]) / 2
y_c = (yolo_det[:, 1] + yolo_det[:, 3]) / 2
tmp = (x_c >= border) & (x_c <= (img_shape[1] - border)) & (y_c >= border) & (y_c <= (img_shape[0] - border))
yolo_det = yolo_det[tmp]
# 创建yolo_det_clone内容为x1, y1, x2, y2, conf, cls, unlabel (unlabel代表该类是否需要忽略0不忽略 其他:忽略)
logger.info("标记 :{}, yolo_det:{}, dmpr_det:{}", '+++'* 10, yolo_det, dmpr_det)
yolo_det_clone = yolo_det.copy()
tmp_0_tensor = np.zeros([len(yolo_det), 1])
yolo_det_clone = np.concatenate([yolo_det_clone, tmp_0_tensor], axis=1)
# cls为需要计算的类别
yolo_det = yolo_det[yolo_det[:, -1] == cls]
# new_yolo_det为膨胀后数据内容为x1, y1, x2, y2, flag (flag代表膨胀后车位内是否包含角点 且 与角点方向差值小于90度, 其值为第一个满足条件的角点索引)
new_yolo_det = np.zeros([len(yolo_det), 7])
# yolo框膨胀长的边两边各膨胀0.4倍总长短的边两边各膨胀0.2倍总长
x_length = yolo_det[:, 2] - yolo_det[:, 0] #x2-x1
y_length = yolo_det[:, 3] - yolo_det[:, 1] #y2-y1
# x, y哪个方向差值大哪个方向膨胀的多
x_dilate_coefficient = ((x_length > y_length) + 1)*scaleRatio
y_dilate_coefficient = ((~(x_length > y_length)) + 1)*scaleRatio
logger.info("膨胀前标记 :{}, yolo_det:{}", '+++'*10, new_yolo_det)
# 原始框中心点x_c, y_c
new_yolo_det[:, 5] = (yolo_det[:, 0] + yolo_det[:, 2]) / 2
new_yolo_det[:, 6] = (yolo_det[:, 1] + yolo_det[:, 3]) / 2
# 膨胀
new_yolo_det[:, 0] = np.round(yolo_det[:, 0] - x_dilate_coefficient * x_length).clip(0, img_shape[1]) #x1 膨胀
new_yolo_det[:, 1] = np.round(yolo_det[:, 1] - y_dilate_coefficient * y_length).clip(0, img_shape[0]) #y1 膨胀
new_yolo_det[:, 2] = np.round(yolo_det[:, 2] + x_dilate_coefficient * x_length).clip(0, img_shape[1]) #x2 膨胀
new_yolo_det[:, 3] = np.round(yolo_det[:, 3] + y_dilate_coefficient * y_length).clip(0, img_shape[0]) #y2 膨胀
m, n = new_yolo_det.size, dmpr_det.size
logger.info("膨胀后标记 :{}, yolo_det:{} m:{}, n:{}", '+++'*10, new_yolo_det,m,n)
if not m or not n:
#print('##line47 original yolo_det_clone:',yolo_det_clone)
yolo_det_clone[np.logical_and( yolo_det_clone[:,-1]==0,yolo_det_clone[:,-2]==cls),-2] = illParkCls
#yolo_det_clone[yolo_det_clone[:, -1] == 0 & yolo_det_clone[:, -2==cls] , -2] = illParkCls
return yolo_det_clone[:,0:6], ' no cars or T/L corners'
new_yolo = new_yolo_det[:, np.newaxis, :].repeat(dmpr_det.shape[0], 1) # 扩展为 (m , n, 5)
dmpr_det = dmpr_det[np.newaxis, ...].repeat(new_yolo_det.shape[0], 0)
yolo_dmpr = np.concatenate((new_yolo, dmpr_det), axis=2) # (m, n, 10)
logger.info("膨胀后标记 :{}, yolo_dmpr:{}", '+++' * 10, yolo_dmpr)
x_p, y_p = yolo_dmpr[..., 8], yolo_dmpr[..., 9]
x1, y1, x2, y2 = yolo_dmpr[..., 0], yolo_dmpr[..., 1], yolo_dmpr[..., 2], yolo_dmpr[..., 3]
x_c, y_c = yolo_dmpr[..., 5], yolo_dmpr[..., 6]
direction1 = np.arctan2(y_c - y_p, x_c - x_p) / math.pi * 180
direction2 = yolo_dmpr[..., 10] / math.pi * 180
direction3 = direction2 + 90 # L形角点另外一个方向
direction3[direction3 > 180] -= 360
ang_diff = direction1 - direction2
ang_diff2 = direction1 - direction3
# 判断膨胀后yolo框包含角点关系 && 包含角点的时候计算水平框中心点与角点的角度关系
# direction ∈ -180 180 若角差大于180需算补角
# T形角点比较一个方向L形角点比较两个方向
mask = (x_p >= x1) & (x_p <= x2) & (y_p >= y1) & (y_p <= y2) & \
(((yolo_dmpr[..., 11] <= 0.5) & # T形角点情况
(((ang_diff >= -90) & (ang_diff <= 90)) | ((ang_diff > 180) & ((360 - ang_diff) <= 90)) |
(((ang_diff) < -180) & ((360 + ang_diff) <= 90)))) |
((yolo_dmpr[..., 11] > 0.5) & # L形角点情况
(((ang_diff >= -90) & (ang_diff <= 90)) | ((ang_diff > 180) & ((360 - ang_diff) <= 90)) |
(((ang_diff) < -180) & ((360 + ang_diff) <= 90))) &
(((ang_diff2 >= -90) & (ang_diff2 <= 90)) | ((ang_diff2 > 180) & ((360 - ang_diff2) <= 90)) |
(((ang_diff2) < -180) & ((360 + ang_diff2) <= 90)))))
logger.info("省略 :{}, mask1:{}", '+++' * 10, mask)
res = np.sum(mask, axis=1)
logger.info("省略 :{}, mask2:{}", '+++' * 10, res)
logger.info("省略 :{}, yolo_det_clone:{}", '+++' * 10, yolo_det_clone)
yolo_det_clone[yolo_det_clone[:, -2] == cls, -1] = res
#print('##line69 original yolo_det_clone:',yolo_det_clone)
#yolo_det_clone[yolo_det_clone[:, -1] == 0, -2] = illParkCls
logger.info("省略:{}, yolo_det_clone:{}", '+++' * 10, yolo_det_clone)
#print('-'*20,'--line78',yolo_det_clone)
yolo_det_clone[ np.logical_and( yolo_det_clone[:,-1]==0,yolo_det_clone[:,-2]==cls) ,-2 ] = illParkCls
#print('-'*20,'--line80:',yolo_det_clone)
yolo_det_clone = yolo_det_clone[:,0:6]
time2=time.time()
return np.array(yolo_det_clone), 'dmpr_yolo:%.1f'%( (time2-time1)*1000 )
def stdc_yolo(stdc_det, yolo_det):
im = np.uint8(stdc_det)
x_c = ((yolo_det[:, 0] + yolo_det[:, 2]) // 2).astype(int)
y_c = ((yolo_det[:, 1] + yolo_det[:, 3]) // 2).astype(int)
yolo_filted = yolo_det[im[y_c, x_c] == 0]
return yolo_filted
def dmpr_yolo_stdc(predsList,pars):
if len(predsList)==2:
yolo_det, dmpr_det = predsList[0:2]
else:
yolo_det, dmpr_det,stdc_det = predsList[0:3]
if len(yolo_det)==0:
return yolo_det,' No yolo detections'
if isinstance(yolo_det,list):
yolo_det = np.array(yolo_det)
if len(predsList)>2:
yolo_det = stdc_yolo(stdc_det, yolo_det)
return dmpr_yolo(yolo_det, dmpr_det,pars)

View File

@ -0,0 +1,2 @@
"""Network model related package."""
from .detector import DirectionalPointDetector

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,64 @@
"""Defines the detector network structure."""
import torch
from torch import nn
from DMPRUtils.model.network import define_halve_unit, define_detector_block
class YetAnotherDarknet(nn.modules.Module):
"""Yet another darknet, imitating darknet-53 with depth of darknet-19."""
def __init__(self, input_channel_size, depth_factor):
super(YetAnotherDarknet, self).__init__()
layers = []
# 0
layers += [nn.Conv2d(input_channel_size, depth_factor, kernel_size=3,
stride=1, padding=1, bias=False)]
layers += [nn.BatchNorm2d(depth_factor)]
layers += [nn.LeakyReLU(0.1)]
# 1
layers += define_halve_unit(depth_factor)
layers += define_detector_block(depth_factor)
# 2
depth_factor *= 2
layers += define_halve_unit(depth_factor)
layers += define_detector_block(depth_factor)
# 3
depth_factor *= 2
layers += define_halve_unit(depth_factor)
layers += define_detector_block(depth_factor)
layers += define_detector_block(depth_factor)
# 4
depth_factor *= 2
layers += define_halve_unit(depth_factor)
layers += define_detector_block(depth_factor)
layers += define_detector_block(depth_factor)
# 5
depth_factor *= 2
layers += define_halve_unit(depth_factor)
layers += define_detector_block(depth_factor)
self.model = nn.Sequential(*layers)
def forward(self, *x):
return self.model(x[0])
class DirectionalPointDetector(nn.modules.Module):
"""Detector for point with direction."""
def __init__(self, input_channel_size, depth_factor, output_channel_size):
super(DirectionalPointDetector, self).__init__()
self.extract_feature = YetAnotherDarknet(input_channel_size,
depth_factor)
layers = []
layers += define_detector_block(16 * depth_factor)
layers += define_detector_block(16 * depth_factor)
layers += [nn.Conv2d(32 * depth_factor, output_channel_size,
kernel_size=1, stride=1, padding=0, bias=False)]
self.predict = nn.Sequential(*layers)
def forward(self, *x):
prediction = self.predict(self.extract_feature(x[0]))
# 4 represents that there are 4 value: confidence, shape, offset_x,
# offset_y, whose range is between [0, 1].
point_pred, angle_pred = torch.split(prediction, 4, dim=1)
point_pred = torch.sigmoid(point_pred)
angle_pred = torch.tanh(angle_pred)
return torch.cat((point_pred, angle_pred), dim=1)

View File

@ -0,0 +1,54 @@
"""Universal network struture unit definition."""
from torch import nn
def define_squeeze_unit(basic_channel_size):
"""Define a 1x1 squeeze convolution with norm and activation."""
conv = nn.Conv2d(2 * basic_channel_size, basic_channel_size, kernel_size=1,
stride=1, padding=0, bias=False)
norm = nn.BatchNorm2d(basic_channel_size)
relu = nn.LeakyReLU(0.1)
layers = [conv, norm, relu]
return layers
def define_expand_unit(basic_channel_size):
"""Define a 3x3 expand convolution with norm and activation."""
conv = nn.Conv2d(basic_channel_size, 2 * basic_channel_size, kernel_size=3,
stride=1, padding=1, bias=False)
norm = nn.BatchNorm2d(2 * basic_channel_size)
relu = nn.LeakyReLU(0.1)
layers = [conv, norm, relu]
return layers
def define_halve_unit(basic_channel_size):
"""Define a 4x4 stride 2 expand convolution with norm and activation."""
conv = nn.Conv2d(basic_channel_size, 2 * basic_channel_size, kernel_size=4,
stride=2, padding=1, bias=False)
norm = nn.BatchNorm2d(2 * basic_channel_size)
relu = nn.LeakyReLU(0.1)
layers = [conv, norm, relu]
return layers
def define_depthwise_expand_unit(basic_channel_size):
"""Define a 3x3 expand convolution with norm and activation."""
conv1 = nn.Conv2d(basic_channel_size, 2 * basic_channel_size,
kernel_size=1, stride=1, padding=0, bias=False)
norm1 = nn.BatchNorm2d(2 * basic_channel_size)
relu1 = nn.LeakyReLU(0.1)
conv2 = nn.Conv2d(2 * basic_channel_size, 2 * basic_channel_size, kernel_size=3,
stride=1, padding=1, bias=False, groups=2 * basic_channel_size)
norm2 = nn.BatchNorm2d(2 * basic_channel_size)
relu2 = nn.LeakyReLU(0.1)
layers = [conv1, norm1, relu1, conv2, norm2, relu2]
return layers
def define_detector_block(basic_channel_size):
"""Define a unit composite of a squeeze and expand unit."""
layers = []
layers += define_squeeze_unit(basic_channel_size)
layers += define_expand_unit(basic_channel_size)
return layers

47
DMPRUtils/toTrt.py Normal file
View File

@ -0,0 +1,47 @@
import os
import time,argparse
import cv2
import torch
import sys
sys.path.extend(['..' ])
from DMPRUtils.model.detector import DirectionalPointDetector
from pathlib import Path
from segutils.trtUtils import toONNX,ONNXtoTrt
from DMPRUtils.yolo_net import Model
def main(opt):
pars={'depth_factor':32,'NUM_FEATURE_MAP_CHANNEL':6,'dmpr_thresh':0.3, 'dmprimg_size':640,
'mWidth':640,'mHeight':640
}
##以下参数目前不可改
#DMPRweights = "weights/urbanManagement/DMPR/dp_detector_499.pth"
DMPRweights = opt.weights.strip()
DMPR_pthFile = Path(DMPRweights)
inputShape =(1, 3, pars['mHeight'],pars['mWidth'])#(bs,channels,height,width)
DMPR_onnxFile = str(DMPR_pthFile.with_suffix('.onnx'))
DMPR_trtFile = DMPR_onnxFile.replace('.onnx','.engine' )
##加载模型,准备好显示字符
device = 'cuda:0'
# DMPR model
#DMPRmodel = DirectionalPointDetector(3, pars['depth_factor'], pars['NUM_FEATURE_MAP_CHANNEL']).to(device)
confUrl = os.path.join( os.path.dirname(__file__),'config','yolov5s.yaml' )
DMPRmodel = Model(confUrl, ch=3).to(device)
DMPRmodel.load_state_dict(torch.load(DMPRweights))
toONNX(DMPRmodel,DMPR_onnxFile,inputShape=inputShape,device=device,dynamic=True)
ONNXtoTrt(DMPR_onnxFile,DMPR_trtFile)
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument('--weights', type=str, default='/mnt/thsw2/DSP2/weights/cityMangement2/weights/urbanManagement/DMPR/dp_detector_499.pth', help='model path(s)')
opt = parser.parse_args()
main(opt)

5
DMPRUtils/toTrt.sh Normal file
View File

@ -0,0 +1,5 @@
weights=/mnt/thsw2/DSP2/weights/cityMangement3/dmpr
#weights=/mnt/thsw2/DSP2/weights/cityMangement2_0916/weights/urbanManagement/DMPR/dp_detector_299
gpu=2080Ti
python toTrt.py --weights ${weights}.pth
mv ${weights}.engine ${weights}_${gpu}.engine

284
DMPRUtils/yolo_net.py Normal file
View File

@ -0,0 +1,284 @@
# YOLOv5 YOLO-specific modules
import argparse
import logging
import sys
from copy import deepcopy
import torch
sys.path.append('./') # to run '$ python *.py' files in subdirectories
logger = logging.getLogger(__name__)
from models.common import *
from models.experimental import *
from utils.autoanchor import check_anchor_order
from utils.general import make_divisible, check_file, set_logging
from utils.torch_utils import time_synchronized, fuse_conv_and_bn, model_info, scale_img, initialize_weights, \
select_device, copy_attr
try:
import thop # for FLOPS computation
except ImportError:
thop = None
class Detect(nn.Module):
stride = None # strides computed during build
export = False # onnx export
def __init__(self, nc=80, anchors=(), ch=()): # detection layers
super(Detect, self).__init__()
self.no = 6
self.nl = 3
self.na = len(anchors[0]) // 2 # number of anchors
self.grid = [torch.zeros(1)] * self.nl # init grid
a = torch.tensor(anchors).float().view(self.nl, -1, 2)
self.register_buffer('anchors', a) # shape(nl,na,2)
self.register_buffer('anchor_grid', a.clone().view(self.nl, 1, -1, 1, 1, 2)) # shape(nl,1,na,1,1,2)
self.m = nn.ModuleList(nn.Conv2d(x, self.no, 1) for x in ch) # output conv
def forward(self, x):
# x = x.copy() # for profiling
# z = [] # inference output
# # self.training |= self.export
# for i in range(self.nl):
# x[i] = self.m[i](x[i]) # conv
# bs, _, ny, nx = x[i].shape # x(bs,255,20,20) to x(bs,3,20,20,85)
# x[i] = x[i].view(bs, self.na, self.no, ny, nx).permute(0, 1, 3, 4, 2).contiguous()
#
# if not self.training: # inference
# if self.grid[i].shape[2:4] != x[i].shape[2:4]:
# self.grid[i] = self._make_grid(nx, ny).to(x[i].device)
#
# y = x[i].sigmoid()
# y[..., 0:2] = (y[..., 0:2] * 2. - 0.5 + self.grid[i]) * self.stride[i] # xy
# y[..., 2:4] = (y[..., 2:4] * 2) ** 2 * self.anchor_grid[i] # wh
# z.append(y.view(bs, -1, self.no))
prediction = self.m[1](x[1])
point_pred, angle_pred = torch.split(prediction, 4, dim=1)
point_pred = torch.sigmoid(point_pred)
angle_pred = torch.tanh(angle_pred)
return torch.cat((point_pred, angle_pred), dim=1)
@staticmethod
def _make_grid(nx=20, ny=20):
yv, xv = torch.meshgrid([torch.arange(ny), torch.arange(nx)])
return torch.stack((xv, yv), 2).view((1, 1, ny, nx, 2)).float()
class Model(nn.Module):
def __init__(self, cfg='yolov5s.yaml', ch=3, nc=None, anchors=None): # model, input channels, number of classes
super(Model, self).__init__()
if isinstance(cfg, dict):
self.yaml = cfg # model dict
else: # is *.yaml
import yaml # for torch hub
self.yaml_file = Path(cfg).name
with open(cfg) as f:
self.yaml = yaml.load(f, Loader=yaml.SafeLoader) # model dict
# Define model
ch = self.yaml['ch'] = self.yaml.get('ch', ch) # input channels
if nc and nc != self.yaml['nc']:
logger.info(f"Overriding model.yaml nc={self.yaml['nc']} with nc={nc}")
self.yaml['nc'] = nc # override yaml value
if anchors:
logger.info(f'Overriding model.yaml anchors with anchors={anchors}')
self.yaml['anchors'] = round(anchors) # override yaml value
self.model, self.save = parse_model(deepcopy(self.yaml), ch=[ch]) # model, savelist
self.names = [str(i) for i in range(self.yaml['nc'])] # default names
# print([x.shape for x in self.forward(torch.zeros(1, ch, 64, 64))])
# Build strides, anchors
# m = self.model[-1] # Detect()
# if isinstance(m, Detect):
# s = 256 # 2x min stride
# m.stride = torch.tensor([s / x.shape[-2] for x in self.forward(torch.zeros(1, ch, s, s))]) # forward
# m.anchors /= m.stride.view(-1, 1, 1)
# check_anchor_order(m)
# self.stride = m.stride
# self._initialize_biases() # only run once
# print('Strides: %s' % m.stride.tolist())
# Init weights, biases
initialize_weights(self)
self.info()
logger.info('')
def forward(self, x, augment=False, profile=False):
if augment:
img_size = x.shape[-2:] # height, width
s = [1, 0.83, 0.67] # scales
f = [None, 3, None] # flips (2-ud, 3-lr)
y = [] # outputs
for si, fi in zip(s, f):
xi = scale_img(x.flip(fi) if fi else x, si, gs=int(self.stride.max()))
yi = self.forward_once(xi)[0] # forward
# cv2.imwrite(f'img_{si}.jpg', 255 * xi[0].cpu().numpy().transpose((1, 2, 0))[:, :, ::-1]) # save
yi[..., :4] /= si # de-scale
if fi == 2:
yi[..., 1] = img_size[0] - yi[..., 1] # de-flip ud
elif fi == 3:
yi[..., 0] = img_size[1] - yi[..., 0] # de-flip lr
y.append(yi)
return torch.cat(y, 1), None # augmented inference, train
else:
return self.forward_once(x, profile) # single-scale inference, train
def forward_once(self, x, profile=False):
y, dt = [], [] # outputs
for m in self.model:
if m.f != -1: # if not from previous layer
x = y[m.f] if isinstance(m.f, int) else [x if j == -1 else y[j] for j in m.f] # from earlier layers
if profile:
o = thop.profile(m, inputs=(x,), verbose=False)[0] / 1E9 * 2 if thop else 0 # FLOPS
t = time_synchronized()
for _ in range(10):
_ = m(x)
dt.append((time_synchronized() - t) * 100)
print('%10.1f%10.0f%10.1fms %-40s' % (o, m.np, dt[-1], m.type))
x = m(x) # run
y.append(x if m.i in self.save else None) # save output
if profile:
print('%.1fms total' % sum(dt))
return x
def _initialize_biases(self, cf=None): # initialize biases into Detect(), cf is class frequency
# https://arxiv.org/abs/1708.02002 section 3.3
# cf = torch.bincount(torch.tensor(np.concatenate(dataset.labels, 0)[:, 0]).long(), minlength=nc) + 1.
m = self.model[-1] # Detect() module
for mi, s in zip(m.m, m.stride): # from
b = mi.bias.view(m.na, -1) # conv.bias(255) to (3,85)
b.data[:, 4] += math.log(8 / (640 / s) ** 2) # obj (8 objects per 640 image)
b.data[:, 5:] += math.log(0.6 / (m.nc - 0.99)) if cf is None else torch.log(cf / cf.sum()) # cls
mi.bias = torch.nn.Parameter(b.view(-1), requires_grad=True)
def _print_biases(self):
m = self.model[-1] # Detect() module
for mi in m.m: # from
b = mi.bias.detach().view(m.na, -1).T # conv.bias(255) to (3,85)
print(('%6g Conv2d.bias:' + '%10.3g' * 6) % (mi.weight.shape[1], *b[:5].mean(1).tolist(), b[5:].mean()))
# def _print_weights(self):
# for m in self.model.modules():
# if type(m) is Bottleneck:
# print('%10.3g' % (m.w.detach().sigmoid() * 2)) # shortcut weights
def fuse(self): # fuse model Conv2d() + BatchNorm2d() layers
print('Fusing layers... ')
for m in self.model.modules():
if type(m) is Conv and hasattr(m, 'bn'):
m.conv = fuse_conv_and_bn(m.conv, m.bn) # update conv
delattr(m, 'bn') # remove batchnorm
m.forward = m.fuseforward # update forward
self.info()
return self
def nms(self, mode=True): # add or remove NMS module
present = type(self.model[-1]) is NMS # last layer is NMS
if mode and not present:
print('Adding NMS... ')
m = NMS() # module
m.f = -1 # from
m.i = self.model[-1].i + 1 # index
self.model.add_module(name='%s' % m.i, module=m) # add
self.eval()
elif not mode and present:
print('Removing NMS... ')
self.model = self.model[:-1] # remove
return self
def autoshape(self): # add autoShape module
print('Adding autoShape... ')
m = autoShape(self) # wrap model
copy_attr(m, self, include=('yaml', 'nc', 'hyp', 'names', 'stride'), exclude=()) # copy attributes
return m
def info(self, verbose=False, img_size=640): # print model information
model_info(self, verbose, img_size)
def parse_model(d, ch): # model_dict, input_channels(3)
logger.info('\n%3s%18s%3s%10s %-40s%-30s' % ('', 'from', 'n', 'params', 'module', 'arguments'))
anchors, nc, gd, gw = d['anchors'], d['nc'], d['depth_multiple'], d['width_multiple']
na = (len(anchors[0]) // 2) if isinstance(anchors, list) else anchors # number of anchors
# no = na * (nc + 5) # number of outputs = anchors * (classes + 5)
no = 6
layers, save, c2 = [], [], ch[-1] # layers, savelist, ch out
for i, (f, n, m, args) in enumerate(d['backbone'] + d['head']): # from, number, module, args
m = eval(m) if isinstance(m, str) else m # eval strings
for j, a in enumerate(args):
try:
args[j] = eval(a) if isinstance(a, str) else a # eval strings
except:
pass
n = max(round(n * gd), 1) if n > 1 else n # depth gain
if m in [Conv, GhostConv, Bottleneck, GhostBottleneck, SPP, DWConv, MixConv2d, Focus, CrossConv, BottleneckCSP,
C3, C3TR]:
c1, c2 = ch[f], args[0]
if c2 != no: # if not output
c2 = make_divisible(c2 * gw, 8)
args = [c1, c2, *args[1:]]
if m in [BottleneckCSP, C3, C3TR]:
args.insert(2, n) # number of repeats
n = 1
elif m is nn.BatchNorm2d:
args = [ch[f]]
elif m is Concat:
c2 = sum([ch[x] for x in f])
elif m is Detect:
args.append([ch[x] for x in f])
if isinstance(args[1], int): # number of anchors
args[1] = [list(range(args[1] * 2))] * len(f)
elif m is Contract:
c2 = ch[f] * args[0] ** 2
elif m is Expand:
c2 = ch[f] // args[0] ** 2
else:
c2 = ch[f]
m_ = nn.Sequential(*[m(*args) for _ in range(n)]) if n > 1 else m(*args) # module
t = str(m)[8:-2].replace('__main__.', '') # module type
np = sum([x.numel() for x in m_.parameters()]) # number params
m_.i, m_.f, m_.type, m_.np = i, f, t, np # attach index, 'from' index, type, number params
logger.info('%3s%18s%3s%10.0f %-40s%-30s' % (i, f, n, np, t, args)) # print
save.extend(x % i for x in ([f] if isinstance(f, int) else f) if x != -1) # append to savelist
layers.append(m_)
if i == 0:
ch = []
ch.append(c2)
return nn.Sequential(*layers), sorted(save)
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument('--cfg', type=str, default='yolov5s.yaml', help='model.yaml')
parser.add_argument('--device', default='', help='cuda device, i.e. 0 or 0,1,2,3 or cpu')
opt = parser.parse_args()
opt.cfg = check_file(opt.cfg) # check file
set_logging()
device = select_device(opt.device)
# Create model
model = Model(opt.cfg).to(device)
model.train()
# Profile
# img = torch.rand(8 if torch.cuda.is_available() else 1, 3, 640, 640).to(device)
# y = model(img, profile=True)
# Tensorboard
# from torch.utils.tensorboard import SummaryWriter
# tb_writer = SummaryWriter()
# print("Run 'tensorboard --logdir=models/runs' to view tensorboard at http://localhost:6006/")
# tb_writer.add_graph(model.model, img) # add model to tensorboard
# tb_writer.add_image('test', img[0], dataformats='CWH') # add model to tensorboard

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,4 @@
{
"labelnames":["钓鱼","游泳"],
"labelIndexs":["SL01","SL02"]
}

View File

@ -0,0 +1,7 @@
{
"post_process":{ "name":"post_process","conf_thres":0.25,"iou_thres":0.45,"classes":5,"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]] }
}

View File

@ -0,0 +1,61 @@
GPUID: 0
WORKERS: 1
PRINT_FREQ: 10
SAVE_FREQ: 10
PIN_MEMORY: False
OUTPUT_DIR: 'output'
CUDNN:
BENCHMARK: True
DETERMINISTIC: False
ENABLED: True
DATASET:
DATASET: 360CC
ROOT: "../textGenerator/dataset/dataset9/images"
CHAR_FILE: '../textGenerator/dataset/dataset9/chars.txt'
JSON_FILE: {'train': '../textGenerator/dataset/dataset9/train.txt', 'val': '../textGenerator/dataset/dataset9/val.txt'}
# JSON_FILE: {'train': 'H:/DL-DATASET/360M/train.txt', 'val': 'H:/DL-DATASET/360M/test.txt'}
SCALE_FACTOR: 0.25
ROT_FACTOR: 30
STD: 0.193
MEAN: 0.588
ALPHABETS: ''
TRAIN:
BATCH_SIZE_PER_GPU: 32
SHUFFLE: True
BEGIN_EPOCH: 0
END_EPOCH: 100
RESUME:
IS_RESUME: False
FILE: 'output/360CC/crnn/2023-04-27-13-01/checkpoints/checkpoint_99_acc_0.5030.pth'
OPTIMIZER: 'adam'
LR: 0.0001
WD: 0.0
LR_STEP: [60, 80]
LR_FACTOR: 0.1
MOMENTUM: 0.0
NESTEROV: False
RMSPROP_ALPHA:
RMSPROP_CENTERED:
FINETUNE:
IS_FINETUNE: False
FINETUNE_CHECKPOINIT: 'output/checkpoints/mixed_second_finetune_acc_97P7.pth'
FREEZE: true
TEST:
BATCH_SIZE_PER_GPU: 16
SHUFFLE: True # for random test rather than test on the whole validation set
NUM_TEST_BATCH: 1000
NUM_TEST_DISP: 10
MODEL:
NAME: 'crnn'
IMAGE_SIZE:
OW: 160 # origial width: 280
H: 32
W: 160 # resized width: 160
NUM_CLASSES: 0
NUM_HIDDEN: 256

7934
conf/OCR_Ch/Ch.txt Normal file

File diff suppressed because it is too large Load Diff

92
conf/OCR_Ch/chars.txt Normal file
View File

@ -0,0 +1,92 @@
a
b
c
d
e
f
g
h
i
j
k
l
m
n
o
p
q
r
s
t
u
v
w
x
y
z
A
B
C
D
E
F
G
H
I
J
K
L
M
N
O
P
Q
R
S
T
U
V
W
X
Y
Z
0
1
2
3
4
5
6
7
8
9
°
!
"
#
$
%
&
'
(
)
*
+
,
-
.
/
:
;
?
@
[
\
]
^
_
`
{
|
}
~

View File

@ -0,0 +1,5 @@
{
"labelnames_实际":["国旗","浮标","船名","船只","未挂国旗船只" ],
"labelnames":[ "国旗","浮标","船名","船只","未挂国旗船只" ],
"labelIndexs":["SL040", "SL041","SL042","SL043","SL044"]
}

View File

@ -0,0 +1,4 @@
{
"labelnames":["人"],
"labelIndexs":["SL031"]
}

View File

@ -0,0 +1,7 @@
{
"post_process":{ "name":"post_process","conf_thres":0.25,"iou_thres":0.45,"classes":5,"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]] }
}

11
conf/check.sh Normal file
View File

@ -0,0 +1,11 @@
#检测混合模型
for bus in highWay2 river2 drowning noParking river
do
diff /mnt/thsw2/DSP2/weights/${bus}/yolov5.pt ${bus}/yolov5.pt
diff /mnt/thsw2/DSP2/weights/${bus}/stdc_360X640.pth ${bus}/stdc_360X640.pth
done
#检查检测模型
for bus in forest2 vehicle pedestrian smogfire AnglerSwimmer countryRoad cityMangement
do
diff /mnt/thsw2/DSP2/weights/${bus}/yolov5.pt ${bus}/yolov5.pt
done

View File

@ -0,0 +1,4 @@
{
"labelnames":["车辆","垃圾","商贩"],
"labelIndexs":["SL01","SL02","SL03"]
}

7
conf/cityMangement/para.json Executable file
View File

@ -0,0 +1,7 @@
{
"post_process":{ "name":"post_process","conf_thres":0.25,"iou_thres":0.45,"classes":5,"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]] }
}

View File

@ -0,0 +1,4 @@
{
"labelnames":["车辆","垃圾","商贩","违停"],
"labelIndexs":["SL01","SL02","SL03","SL04"]
}

7
conf/cityMangement2/para.json Executable file
View File

@ -0,0 +1,7 @@
{
"post_process":{ "name":"post_process","conf_thres":0.25,"score_byClass":{"0":0.88,"1":0.3,"2":0.3,"3":0.3 } ,"iou_thres":0.45,"classes":5,"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]] }
}

Binary file not shown.

View File

@ -0,0 +1,4 @@
{
"labelnames":["车辆","垃圾","商贩","违停"],
"labelIndexs":["SL01","SL02","SL03","SL04"]
}

View File

@ -0,0 +1,7 @@
{
"post_process":{ "name":"post_process","conf_thres":0.25,"score_byClass":{"0":0.88,"1":0.3,"2":0.3,"3":0.3 } ,"iou_thres":0.45,"classes":5,"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]] }
}

5
conf/cityRoad/labelnames.json Executable file
View File

@ -0,0 +1,5 @@
{
"labelnames":["护栏","交通标志","非交通标志","施工","施工"],
"labelIndexs":["SL01","SL02","SL03","SL04","SL05"],
"labelnamesActual":["护栏","交通标志","非交通标志","锥桶","水马" ]
}

7
conf/cityRoad/para.json Executable file
View File

@ -0,0 +1,7 @@
{
"post_process":{ "name":"post_process","conf_thres":0.25,"iou_thres":0.45,"classes":5,"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]] }
}

View File

@ -0,0 +1,4 @@
{
"labelnames":["违法种植"],
"labelIndexs":["SL01"]
}

View File

@ -0,0 +1,7 @@
{
"post_process":{ "name":"post_process","conf_thres":0.25,"iou_thres":0.45,"classes":5,"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]] }
}

View File

@ -0,0 +1,4 @@
{
"labelnames":[ "纵向裂缝","横向裂缝","网状裂缝" ],
"labelIndexs":["SL01","SL02","SL03"]
}

View File

@ -0,0 +1,5 @@
crack_yolov5_202302.pt对应类别['pedestrian', 'vehicle', 'D00', 'D10', 'Repair', 'D20', 'D40', 'Block crack', 'JiShui']
roaddamage20231028.pt对应类别[ 'D00','D10','D20','D40','D44','D50','Repair','D43','D01','D11','D0w0','Block crack' ]
[ 'D00':纵向裂缝,
'D10':横向裂缝,
'D20':网状裂缝 ]

View File

@ -0,0 +1,4 @@
{
"labelnames":["人头"],
"labelIndexs":["SL01"]
}

5
conf/drowning/labelnames.json Executable file
View File

@ -0,0 +1,5 @@
{
"labelnames":[ "人头","人","船只" ],
"labelIndexs":[ "SL001","SL002","SL003" ]
}

10
conf/drowning/para.json Executable file
View File

@ -0,0 +1,10 @@
{
"post_process":{
"name":"post_process","conf_thres":0.25,"iou_thres":0.25,"classes":9,
"rainbows":[ [0,0,255],[0,255,0],[255,0,0],[255,0,0],[255,255,0],[255,0,0],[255,0,127],[255,0,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]]
}
}

View File

@ -0,0 +1,4 @@
{
"labelnames":["林斑","病死树"],
"labelIndexs":["SL031","SL032"]
}

7
conf/forest/para.json Normal file
View File

@ -0,0 +1,7 @@
{
"post_process":{ "name":"post_process","conf_thres":0.25,"iou_thres":0.45,"classes":5,"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]] }
}

View File

@ -0,0 +1,4 @@
{
"labelnames":["林斑","病死树","行人","火焰","烟雾","云朵"],
"labelIndexs":["SL031","SL032","SL033","SL034","SL035","SL036","SL037"]
}

7
conf/forest2/para.json Normal file
View File

@ -0,0 +1,7 @@
{
"post_process":{ "name":"post_process","conf_thres":0.25,"iou_thres":0.45,"classes":5,"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]] }
}

View File

@ -0,0 +1,4 @@
{
"labelnames":["林斑","病死树","行人","火焰","烟雾","人群"],
"labelIndexs":["SL031","SL032","SL033","SL034","SL035","SL036","SL037"]
}

View File

@ -0,0 +1,7 @@
{
"post_process":{ "name":"post_process","conf_thres":0.25,"iou_thres":0.45,"classes":5,"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]] }
}

View File

@ -0,0 +1,4 @@
name,r,g,b,cls
0,0,0,0,bg
1,128,0,0,road
2,0,128,0,vehicle
1 name r g b cls
2 0 0 0 0 bg
3 1 128 0 0 road
4 2 0 128 0 vehicle

6
conf/highWay2/labelnames.json Executable file
View File

@ -0,0 +1,6 @@
{
"labelnames":["行人","车辆","裂缝","裂缝","修补","裂缝","坑槽","裂缝","积水", "影子","事故"],
"labelnames_实际":["行人","车辆","纵向裂缝","横向裂缝","修补","网状裂纹","坑槽","块状裂纹","积水","影子","事故"],
"labelIndexs":["SL01","SL02","SL03","SL04","SL05","SL06","SL007","SL008","SL009","SL010","SL011" ]
}

10
conf/highWay2/para.json Executable file
View File

@ -0,0 +1,10 @@
{
"post_process":{
"name":"post_process","conf_thres":0.25,"iou_thres":0.25,"classes":9,
"rainbows":[ [0,0,255],[0,255,0],[255,0,0],[255,0,0],[255,255,0],[255,0,0],[255,0,127],[255,0,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]]
}
}

View File

@ -0,0 +1,5 @@
{
"labelnames":[ "车","T角点","L角点","违停" ],
"labelIndexs":[ "SL001","SL002","SL003","SL004" ]
}

10
conf/illParking/para.json Executable file
View File

@ -0,0 +1,10 @@
{
"post_process":{
"name":"post_process","conf_thres":0.25,"iou_thres":0.25,"classes":9,
"rainbows":[ [0,0,255],[0,255,0],[255,0,0],[255,0,0],[255,255,0],[255,0,0],[255,0,127],[255,0,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]]
}
}

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,5 @@
name,cls
背景,0
道路,1
车道线,2
车辆,3
1 name cls
2 背景 0
3 道路 1
4 车道线 2
5 车辆 3

View File

@ -0,0 +1,6 @@
{
"labelnames":[ "车辆","违停" ],
"labelIndexs":[ "SL001","SL002" ]
}

10
conf/noParking/para.json Executable file
View File

@ -0,0 +1,10 @@
{
"post_process":{
"name":"post_process","conf_thres":0.25,"iou_thres":0.25,"classes":9,
"rainbows":[ [0,0,255],[0,255,0],[255,0,0],[255,0,0],[255,255,0],[255,0,0],[255,0,127],[255,0,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]]
}
}

61
conf/ocr2/360CC_config.yaml Executable file
View File

@ -0,0 +1,61 @@
GPUID: 0
WORKERS: 1
PRINT_FREQ: 10
SAVE_FREQ: 10
PIN_MEMORY: False
OUTPUT_DIR: 'output'
CUDNN:
BENCHMARK: True
DETERMINISTIC: False
ENABLED: True
DATASET:
DATASET: 360CC
ROOT: "../textGenerator/dataset/dataset9/images"
CHAR_FILE: '../textGenerator/dataset/dataset9/chars.txt'
JSON_FILE: {'train': '../textGenerator/dataset/dataset9/train.txt', 'val': '../textGenerator/dataset/dataset9/val.txt'}
# JSON_FILE: {'train': 'H:/DL-DATASET/360M/train.txt', 'val': 'H:/DL-DATASET/360M/test.txt'}
SCALE_FACTOR: 0.25
ROT_FACTOR: 30
STD: 0.193
MEAN: 0.588
ALPHABETS: ''
TRAIN:
BATCH_SIZE_PER_GPU: 32
SHUFFLE: True
BEGIN_EPOCH: 0
END_EPOCH: 100
RESUME:
IS_RESUME: False
FILE: 'output/360CC/crnn/2023-04-27-13-01/checkpoints/checkpoint_99_acc_0.5030.pth'
OPTIMIZER: 'adam'
LR: 0.0001
WD: 0.0
LR_STEP: [60, 80]
LR_FACTOR: 0.1
MOMENTUM: 0.0
NESTEROV: False
RMSPROP_ALPHA:
RMSPROP_CENTERED:
FINETUNE:
IS_FINETUNE: False
FINETUNE_CHECKPOINIT: 'output/checkpoints/mixed_second_finetune_acc_97P7.pth'
FREEZE: true
TEST:
BATCH_SIZE_PER_GPU: 16
SHUFFLE: True # for random test rather than test on the whole validation set
NUM_TEST_BATCH: 1000
NUM_TEST_DISP: 10
MODEL:
NAME: 'crnn'
IMAGE_SIZE:
OW: 160 # origial width: 280
H: 32
W: 160 # resized width: 160
NUM_CLASSES: 0
NUM_HIDDEN: 256

1
conf/ocr2/benchmark.txt Normal file

File diff suppressed because one or more lines are too long

92
conf/ocr2/chars.txt Executable file
View File

@ -0,0 +1,92 @@
a
b
c
d
e
f
g
h
i
j
k
l
m
n
o
p
q
r
s
t
u
v
w
x
y
z
A
B
C
D
E
F
G
H
I
J
K
L
M
N
O
P
Q
R
S
T
U
V
W
X
Y
Z
0
1
2
3
4
5
6
7
8
9
°
!
"
#
$
%
&
'
(
)
*
+
,
-
.
/
:
;
?
@
[
\
]
^
_
`
{
|
}
~

1
conf/ocr2/chars2.txt Normal file
View File

@ -0,0 +1 @@
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789°!"#$%&'()*+,-./:;?@[\]^_`{|}~

56767
conf/ocr_en/en.txt Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1 @@
0123456789!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~ €ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
Can't render this file because it contains an unexpected character in line 1 and column 12.

7
conf/para.json Normal file
View File

@ -0,0 +1,7 @@
{
"post_process":{ "name":"post_process","conf_thres":0.25,"iou_thres":0.45,"classes":5,"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]] }
}

View File

@ -0,0 +1,4 @@
{
"labelnames":["行人"],
"labelIndexs":["SL01"]
}

View File

@ -0,0 +1,7 @@
{
"post_process":{ "name":"post_process","conf_thres":0.25,"iou_thres":0.45,"classes":5,"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]] }
}

BIN
conf/platech.ttf Normal file

Binary file not shown.

View File

@ -0,0 +1,6 @@
{
"labelnames":["坑槽"],
"labelnames_实际":["坑槽"],
"labelIndexs":["SL01" ]
}

10
conf/pothole/para.json Normal file
View File

@ -0,0 +1,10 @@
{
"post_process":{
"name":"post_process","conf_thres":0.25,"iou_thres":0.25,"classes":9,
"rainbows":[ [0,0,255],[0,255,0],[255,0,0],[255,0,0],[255,255,0],[255,0,0],[255,0,127],[255,0,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]]
}
}

View File

@ -0,0 +1,5 @@
{
"labelnames":["排口","水生植被","其它","漂浮物","污染排口","菜地","违建","岸坡垃圾"],
"labelIndexs":["SL04","SL011","SL013","SL001","SL001","SL002","SL003","SL004" ],
"labelOrders":[0,1,2,3,4,5,6,7]
}

7
conf/river/para.json Normal file
View File

@ -0,0 +1,7 @@
{
"post_process":{ "name":"post_process","conf_thres":0.25,"iou_thres":0.45,"classes":5,"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]] }
}

5
conf/river2/labelnames.json Executable file
View File

@ -0,0 +1,5 @@
{
"labelnames":[ "漂浮物","垃圾","排口","非法建筑","非法种植","水生植物","游泳人员","钓鱼人员","船只","蓝藻"] ,
"labelIndexs":[ "SL04","SL05","SL06","SL07","SL08","SL09","SL10","SL11","SL12","SL13" ],
"labelOrders":[0,1,2,3,4,5,6,7,8,9]
}

7
conf/river2/para.json Executable file
View File

@ -0,0 +1,7 @@
{
"post_process":{ "name":"post_process","conf_thres":0.25,"iou_thres":0.3,"ovlap_thres_crossCategory":0.65,"classes":5,"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]] }
}

View File

@ -0,0 +1,5 @@
{
"labelnames_实际":["纵向裂缝","横向裂缝","修补","网状裂纹","坑槽","块状裂纹","积水"],
"labelnames":["裂缝","裂缝","修补","裂缝","坑槽","裂缝","积水"],
"labelIndexs":["SL030","SL031","SL032","SL033","SL034","SL035","SL036"]
}

10
conf/road/para.json Normal file
View File

@ -0,0 +1,10 @@
{
"post_process":{ "name":"post_process","conf_thres":0.25,"iou_thres":0.45,"classes":5,
"rainbows":[[0,0,255],[0,0,255],[255,0,0],[0,0,255],[255,255,0],[0,0,255],[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]]
}
}

4
conf/ship/labelnames.json Executable file
View File

@ -0,0 +1,4 @@
{
"labelnames":["船只"],
"labelIndexs":["SL01"]
}

7
conf/ship/para.json Executable file
View File

@ -0,0 +1,7 @@
{
"post_process":{ "name":"post_process","conf_thres":0.25,"iou_thres":0.45,"classes":5,"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]] }
}

View File

@ -0,0 +1,4 @@
name,r,g,b,cls
0,0,0,0,bg
1,128,0,0,road
2,0,128,0,vehicle
1 name r g b cls
2 0 0 0 0 bg
3 1 128 0 0 road
4 2 0 128 0 vehicle

View File

@ -0,0 +1,5 @@
{
"labelnames_实际":[ "0","1","2","3","4","5","6","7","8","9","10","11","12","13","boat" ],
"labelnames":[ "0","1","2","3","4","5","6","7","8","9","10","11","12","13","船只" ],
"labelIndexs":["SL050", "SL051", "SL052", "SL053", "SL054", "SL055", "SL056", "SL057", "SL058", "SL059", "SL060", "SL061", "SL062","SL063", "SL064" ]
}

10
conf/ship2/para.json Normal file
View File

@ -0,0 +1,10 @@
{
"post_process":{ "name":"post_process","conf_thres":0.25,"iou_thres":0.45,"classes":5,
"rainbows":[[0,0,255],[0,0,255],[255,0,0],[0,0,255],[255,255,0],[0,0,255],[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]]
}
}

Some files were not shown because too many files have changed in this diff Show More