Browse Source

add crackMeasurement

master
wangjin0928 11 months ago
parent
commit
13a08e800a
22 changed files with 516 additions and 77 deletions
  1. +63
    -16
      AI.py
  2. BIN
      __pycache__/AI.cpython-38.pyc
  3. BIN
      __pycache__/stdc.cpython-38.pyc
  4. +1
    -1
      crowdUtils/run.sh
  5. +7
    -1
      readme.md
  6. BIN
      segutils/__pycache__/model_stages.cpython-38.pyc
  7. BIN
      segutils/__pycache__/segmodel.cpython-38.pyc
  8. +32
    -0
      segutils/crackUtils.py
  9. +207
    -20
      segutils/model_stages.py
  10. +1
    -1
      segutils/run.sh
  11. +9
    -0
      segutils/run_dy.sh
  12. +2
    -2
      segutils/segmodel.py
  13. +64
    -0
      segutils/toTrt.py
  14. +84
    -36
      stdc.py
  15. BIN
      trackUtils/__pycache__/sort.cpython-38.pyc
  16. +1
    -0
      trackUtils/sort.py
  17. BIN
      utilsK/__pycache__/crackUtils.cpython-38.pyc
  18. +36
    -0
      utilsK/crackUtils.py
  19. +4
    -0
      weights/conf/crackMeasurement/labelnames.json
  20. BIN
      weights/conf/crackMeasurement/stdc_360X640.pth
  21. BIN
      weights/conf/crackMeasurement/yolov5.pt
  22. +5
    -0
      weights/conf/crackMeasurement/权重对应类别.txt

+ 63
- 16
AI.py View File

@@ -165,32 +165,63 @@ def default_mix(predlist,par):
def AI_process_N(im0s,modelList,postProcess):
#输入参数
# 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
## 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 AI_process_C(im0s,modelList,postProcess):
#输入参数
## im0s---原始图像列表
## modelList--所有的模型
# postProcess--字典{},包括后处理函数,及其参数
#输出参数
##ret[0]--检测结果;
##ret[1]--时间信息
#modelList包括模型,每个模型是一个类,里面的eval函数可以输出该模型的推理结果
t0=time.time()
detRets0 = modelList[0].eval(im0s[0])
detRets0 = detRets0[0]
#detRets0=[[12, 46, 1127, 1544, 0.2340087890625, 2.0], [1884, 1248, 2992, 1485, 0.64208984375, 1.0]]
detRets0 = list(filter(lambda x: x[5]<=2, 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]
detRets1 = [x[0]*255 for x in detRets1]
t2=time.time()
mixFunction =postProcess['function']
crackInfos = [mixFunction(patchMask) 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 )
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):
@@ -457,6 +488,18 @@ def AI_det_track_N( im0s_in,modelList,postProcess,sort_tracker):
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):
'''
输入:
@@ -506,17 +549,21 @@ def AI_det_track_batch_N(imgarray_list, iframe_list ,modelList,postProcess,sort_
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)
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]=1,frames[0]可能会在frame_min之前出现,即一个横跨了多个批次。
@@ -535,7 +582,7 @@ def AI_det_track_batch_N(imgarray_list, iframe_list ,modelList,postProcess,sort_
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 ,'-----')
#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

BIN
__pycache__/AI.cpython-38.pyc View File


BIN
__pycache__/stdc.cpython-38.pyc View File


+ 1
- 1
crowdUtils/run.sh View File

@@ -1,4 +1,4 @@
gpu=2080Ti
url=/mnt/thsw2/DSP2/weights/crowdCounting/weights
#python toTrt.py --weights ${url}/crowdCounting.pth
python toTrt.py --weights ${url}/crowdCounting.pth
mv ${url}/crowdCounting_dynamic.engine ${url}/crowdCounting_${gpu}_dynamic.engine

+ 7
- 1
readme.md View File

@@ -92,4 +92,10 @@
2023.11.06
1.增加cityMangement3,和cityMangement2一样的检测目标。但用了三个模型。
2.所有的demo3.0.py采用模型列表的方式输入参数
3.从cityMangement3 没有更新A100的trt文件和权重,因为云端A100服务器不存在了
3.从cityMangement3 没有更新A100的trt文件和权重,因为云端A100服务器不存在了
2023.11.17
1.修改stdc网络,增加了pth模式下,动态输入模型。Trt等其他方式不支持动态。
2.增加crackMeasure模型,返回值ret,timeInfos,其中ret为:[[ x0,y0,x1,y1,score,class,裂缝长度,平均宽度,最大宽度,最小宽度],[...],[...]。
3.Debug 跟踪模型中一条跟踪链上,历史框上有不同的类别, 修正为同一类别


BIN
segutils/__pycache__/model_stages.cpython-38.pyc View File


BIN
segutils/__pycache__/segmodel.cpython-38.pyc View File


+ 32
- 0
segutils/crackUtils.py View File

@@ -0,0 +1,32 @@
import numpy as np
from skimage.morphology import medial_axis
def Crack_measure(_mask_cv_gray,dsx=(123-30)*1000/35*0.004387636):
'''裂缝实际尺寸测量'''
'''输入:单个裂缝分割图像
过程:。
返回:最终绘制的结果图、最终落水人员(坐标、类别、置信度),
'''
# 图像转化
###READ
img = np.array(_mask_cv_gray.astype(np.int32))
image0 = binary = img
###SKELETONIZATION
img_skeletonized, distance = medial_axis(image0, return_distance=True)
#print(img_skeletonized)
img_skeletonized = np.array(img_skeletonized.astype(np.int32))
###COMPUTING WIDTH
dist_on_skel = distance * img_skeletonized
width = dist_on_skel[dist_on_skel != 0] * 2
for i in range(len(width)):
if width[i] <= 2.0:
width[i] = width[i]
else:
width[i] = width[i] - 2
###OUTPUT
real_length = np.count_nonzero(img_skeletonized) *dsx # Each pixel remaining after
real_mean_width = np.mean(width)*dsx
real_max_width = np.max(width)*dsx
real_min_width = np.min(width)*dsx
return real_length,real_mean_width,real_max_width,real_min_width

+ 207
- 20
segutils/model_stages.py View File

@@ -69,9 +69,9 @@ class BiSeNetOutput(nn.Module):
return wd_params, nowd_params


class AttentionRefinementModule(nn.Module):
class AttentionRefinementModule_static(nn.Module):
def __init__(self, in_chan, out_chan,avg_pool2d_kernel_size, *args, **kwargs):
super(AttentionRefinementModule, self).__init__()
super(AttentionRefinementModule_static, self).__init__()
self.conv = ConvBNReLU(in_chan, out_chan, ks=3, stride=1, padding=1)
self.conv_atten = nn.Conv2d(out_chan, out_chan, kernel_size= 1, bias=False)
# self.bn_atten = nn.BatchNorm2d(out_chan)
@@ -85,6 +85,7 @@ class AttentionRefinementModule(nn.Module):
def forward(self, x):
feat = self.conv(x)
#atten = F.avg_pool2d(feat, feat.size()[2:])
atten = F.avg_pool2d(feat, self.avg_pool2d_kernel_size)
#print('------------------newline89:','out:',atten.size(),'in:',feat.size(), self.avg_pool2d_kernel_size)
atten = self.conv_atten(atten)
@@ -98,16 +99,48 @@ class AttentionRefinementModule(nn.Module):
if isinstance(ly, nn.Conv2d):
nn.init.kaiming_normal_(ly.weight, a=1)
if not ly.bias is None: nn.init.constant_(ly.bias, 0)
class AttentionRefinementModule(nn.Module):
def __init__(self, in_chan, out_chan, *args, **kwargs):
super(AttentionRefinementModule, self).__init__()
self.conv = ConvBNReLU(in_chan, out_chan, ks=3, stride=1, padding=1)
self.conv_atten = nn.Conv2d(out_chan, out_chan, kernel_size= 1, bias=False)
# self.bn_atten = nn.BatchNorm2d(out_chan)
# self.bn_atten = BatchNorm2d(out_chan, activation='none')
self.bn_atten = nn.BatchNorm2d(out_chan)########################2

self.sigmoid_atten = nn.Sigmoid()

self.init_weight()

class ContextPath(nn.Module):
def forward(self, x):
feat = self.conv(x)
atten = F.avg_pool2d(feat, feat.size()[2:])
#atten = F.avg_pool2d(feat, self.avg_pool2d_kernel_size)
#print('------------------newline89:','out:',atten.size(),'in:',feat.size(), self.avg_pool2d_kernel_size)
atten = self.conv_atten(atten)
atten = self.bn_atten(atten)
atten = self.sigmoid_atten(atten)
out = torch.mul(feat, atten)
return out

def init_weight(self):
for ly in self.children():
if isinstance(ly, nn.Conv2d):
nn.init.kaiming_normal_(ly.weight, a=1)
if not ly.bias is None: nn.init.constant_(ly.bias, 0)


class ContextPath_static(nn.Module):
def __init__(self, backbone='CatNetSmall', pretrain_model='', use_conv_last=False,modelSize=(360,640), *args, **kwargs):
super(ContextPath, self).__init__()
super(ContextPath_static, self).__init__()
self.backbone_name = backbone
self.modelSize = modelSize

self.avg_pool_kernel_size_32=[ int(modelSize[0]/32+0.999), int( modelSize[1]/32+0.999 ) ]
self.avg_pool_kernel_size_16=[ int(modelSize[0]/16+0.999), int( modelSize[1]/16+0.999 ) ]
if backbone == 'STDCNet1446':
self.backbone = STDCNet1446(pretrain_model=pretrain_model, use_conv_last=use_conv_last)
self.arm16 = AttentionRefinementModule(512, 128)
@@ -121,11 +154,15 @@ class ContextPath(nn.Module):

elif backbone == 'STDCNet813':
self.backbone = STDCNet813(pretrain_model=pretrain_model, use_conv_last=use_conv_last)
self.arm16 = AttentionRefinementModule(512, 128,self.avg_pool_kernel_size_16)
self.arm16 = AttentionRefinementModule_static(512, 128,self.avg_pool_kernel_size_16)
inplanes = 1024
if use_conv_last:
inplanes = 1024
self.arm32 = AttentionRefinementModule(inplanes, 128,self.avg_pool_kernel_size_32)
self.arm32 = AttentionRefinementModule_static(inplanes, 128,self.avg_pool_kernel_size_32)
self.conv_head32 = ConvBNReLU(128, 128, ks=3, stride=1, padding=1)
self.conv_head16 = ConvBNReLU(128, 128, ks=3, stride=1, padding=1)
self.conv_avg = ConvBNReLU(inplanes, 128, ks=1, stride=1, padding=0)
@@ -182,10 +219,92 @@ class ContextPath(nn.Module):
nowd_params += list(module.parameters())
return wd_params, nowd_params

class ContextPath(nn.Module):
def __init__(self, backbone='CatNetSmall', pretrain_model='', use_conv_last=False, *args, **kwargs):
super(ContextPath, self).__init__()
self.backbone_name = backbone
if backbone == 'STDCNet1446':
self.backbone = STDCNet1446(pretrain_model=pretrain_model, use_conv_last=use_conv_last)
self.arm16 = AttentionRefinementModule(512, 128)
inplanes = 1024
if use_conv_last:
inplanes = 1024
self.arm32 = AttentionRefinementModule(inplanes, 128)
self.conv_head32 = ConvBNReLU(128, 128, ks=3, stride=1, padding=1)
self.conv_head16 = ConvBNReLU(128, 128, ks=3, stride=1, padding=1)
self.conv_avg = ConvBNReLU(inplanes, 128, ks=1, stride=1, padding=0)

elif backbone == 'STDCNet813':
self.backbone = STDCNet813(pretrain_model=pretrain_model, use_conv_last=use_conv_last)
self.arm16 = AttentionRefinementModule(512, 128)
inplanes = 1024
if use_conv_last:
inplanes = 1024
self.arm32 = AttentionRefinementModule(inplanes, 128)
self.conv_head32 = ConvBNReLU(128, 128, ks=3, stride=1, padding=1)
self.conv_head16 = ConvBNReLU(128, 128, ks=3, stride=1, padding=1)
self.conv_avg = ConvBNReLU(inplanes, 128, ks=1, stride=1, padding=0)
else:
print("backbone is not in backbone lists")
exit(0)

class FeatureFusionModule(nn.Module):
self.init_weight()

def forward(self, x):
H0, W0 = x.size()[2:]

feat2, feat4, feat8, feat16, feat32 = self.backbone(x)
H8, W8 = feat8.size()[2:]
H16, W16 = feat16.size()[2:]
H32, W32 = feat32.size()[2:]
avg = F.avg_pool2d(feat32, feat32.size()[2:])
#print('line147:self.avg_pool_kernel_size_32:',self.avg_pool_kernel_size_32)
#avg = F.avg_pool2d(feat32, self.avg_pool_kernel_size_32)
#print('------------------newline140:','out:','out;',avg.size(),' in:',feat32.size())
avg = self.conv_avg(avg)
avg_up = F.interpolate(avg, (H32, W32), mode='nearest')
#print('------------line143,arm32:',feat32.size())
feat32_arm = self.arm32(feat32)
feat32_sum = feat32_arm + avg_up
feat32_up = F.interpolate(feat32_sum, (H16, W16), mode='nearest')
feat32_up = self.conv_head32(feat32_up)
#print('------------line148,arm16:',feat16.size())
feat16_arm = self.arm16(feat16)
feat16_sum = feat16_arm + feat32_up
feat16_up = F.interpolate(feat16_sum, (H8, W8), mode='nearest')
feat16_up = self.conv_head16(feat16_up)
return feat2, feat4, feat8, feat16, feat16_up, feat32_up # x8, x16

# return feat8, feat16_up # x8, x16

def init_weight(self):
for ly in self.children():
if isinstance(ly, nn.Conv2d):
nn.init.kaiming_normal_(ly.weight, a=1)
if not ly.bias is None: nn.init.constant_(ly.bias, 0)

def get_params(self):
wd_params, nowd_params = [], []
for name, module in self.named_modules():
if isinstance(module, (nn.Linear, nn.Conv2d)):
wd_params.append(module.weight)
if not module.bias is None:
nowd_params.append(module.bias)
elif isinstance(module, nn.BatchNorm2d):#################3
nowd_params += list(module.parameters())
return wd_params, nowd_params


class FeatureFusionModule_static(nn.Module):
def __init__(self, in_chan, out_chan,modelSize ,*args, **kwargs):
super(FeatureFusionModule, self).__init__()
super(FeatureFusionModule_static, self).__init__()
self.convblk = ConvBNReLU(in_chan, out_chan, ks=1, stride=1, padding=0)
self.avg_pool_kernel_size=[ int(modelSize[0]/8+0.9999), int( modelSize[1]/8+0.9999 ) ]
self.conv1 = nn.Conv2d(out_chan,
@@ -237,19 +356,81 @@ class FeatureFusionModule(nn.Module):
elif isinstance(module, nn.BatchNorm2d):##################4
nowd_params += list(module.parameters())
return wd_params, nowd_params
class FeatureFusionModule(nn.Module):
def __init__(self, in_chan, out_chan ,*args, **kwargs):
super(FeatureFusionModule, self).__init__()
self.convblk = ConvBNReLU(in_chan, out_chan, ks=1, stride=1, padding=0)

self.conv1 = nn.Conv2d(out_chan,
out_chan//4,
kernel_size = 1,
stride = 1,
padding = 0,
bias = False)
self.conv2 = nn.Conv2d(out_chan//4,
out_chan,
kernel_size = 1,
stride = 1,
padding = 0,
bias = False)
self.relu = nn.ReLU(inplace=True)
self.sigmoid = nn.Sigmoid()
self.init_weight()

def forward(self, fsp, fcp):
fcat = torch.cat([fsp, fcp], dim=1)
feat = self.convblk(fcat)
atten = F.avg_pool2d(feat, feat.size()[2:])
#atten = F.avg_pool2d(feat, kernel_size=self.avg_pool_kernel_size)
#print('------------------newline199:',' out:',atten.size(),'in:',feat.size())
atten = self.conv1(atten)
atten = self.relu(atten)
atten = self.conv2(atten)
atten = self.sigmoid(atten)
feat_atten = torch.mul(feat, atten)
feat_out = feat_atten + feat
return feat_out

def init_weight(self):
for ly in self.children():
if isinstance(ly, nn.Conv2d):
nn.init.kaiming_normal_(ly.weight, a=1)
if not ly.bias is None: nn.init.constant_(ly.bias, 0)

def get_params(self):
wd_params, nowd_params = [], []
for name, module in self.named_modules():
if isinstance(module, (nn.Linear, nn.Conv2d)):
wd_params.append(module.weight)
if not module.bias is None:
nowd_params.append(module.bias)
elif isinstance(module, nn.BatchNorm2d):##################4
nowd_params += list(module.parameters())
return wd_params, nowd_params


class BiSeNet_STDC(nn.Module):
def __init__(self, backbone, n_classes, pretrain_model='', use_boundary_2=False, use_boundary_4=False,
use_boundary_8=False, use_boundary_16=False, use_conv_last=False,modelSize=(360,640)):
use_boundary_8=False, use_boundary_16=False, use_conv_last=False,**kwargs):
super(BiSeNet_STDC, self).__init__()
if 'modelSize' in kwargs:
modelSize = kwargs['modelSize']
else:
modelSize=None
self.use_boundary_2 = use_boundary_2
self.use_boundary_4 = use_boundary_4
self.use_boundary_8 = use_boundary_8
self.use_boundary_16 = use_boundary_16
# self.heat_map = heat_map
self.cp = ContextPath(backbone, pretrain_model, use_conv_last=use_conv_last,modelSize=modelSize)
if modelSize:
self.cp = ContextPath_static(backbone, pretrain_model, use_conv_last=use_conv_last,modelSize=modelSize)
else:
self.cp = ContextPath(backbone, pretrain_model, use_conv_last=use_conv_last)
if backbone == 'STDCNet1446':
conv_out_inplanes = 128
@@ -270,8 +451,10 @@ class BiSeNet_STDC(nn.Module):
else:
print("backbone is not in backbone lists")
exit(0)

self.ffm = FeatureFusionModule(inplane, 256,modelSize)
if modelSize:
self.ffm = FeatureFusionModule_static(inplane, 256,modelSize)
else:
self.ffm = FeatureFusionModule(inplane, 256)
self.conv_out = BiSeNetOutput(256, 256, n_classes)
self.conv_out16 = BiSeNetOutput(conv_out_inplanes, 64, n_classes)
self.conv_out32 = BiSeNetOutput(conv_out_inplanes, 64, n_classes)
@@ -343,12 +526,16 @@ class BiSeNet_STDC(nn.Module):

if __name__ == "__main__":
net = BiSeNet('STDCNet813', 19)
net.cuda()
net.eval()
in_ten = torch.randn(1, 3, 768, 1536).cuda()
out, out16, out32 = net(in_ten)
print(out.shape)

model = BiSeNet_STDC(backbone='STDCNet813', n_classes=2,
use_boundary_2=False, use_boundary_4=False,
use_boundary_8=True, use_boundary_16=False,
use_conv_last=False,
# modelSize=[360,640]
)
#modelSize=[360,640]
print()
# torch.save(net.state_dict(), 'STDCNet813.pth')###


+ 1
- 1
segutils/run.sh View File

@@ -1,5 +1,5 @@
gpu=2080Ti
name=cityMangement3
name=crackMeasurement
nclass=2
mWidth=640
mHeight=360

+ 9
- 0
segutils/run_dy.sh View File

@@ -0,0 +1,9 @@
#动态尺寸的stdc转trt没有成功,因为里有用到了全局池化,池化的过程中kener_size不固定
gpu=2080Ti
name=crackMeasurement
nclass=2
mWidth=0
mHeight=0
python toTrt.py --weights /mnt/thsw2/DSP2/weights/${name}/stdc_360X640.pth --nclass ${nclass} --mWidth ${mWidth} --mHeight ${mHeight}

mv /mnt/thsw2/DSP2/weights/${name}/stdc_${mWidth}X${mHeight}.engine /mnt/thsw2/DSP2/weights/${name}/stdc_${mHeight}X${mWidth}_${gpu}_fp16.engine

+ 2
- 2
segutils/segmodel.py View File

@@ -29,7 +29,7 @@ class SegModel(object):
time0 = time.time()
imageH, imageW, _ = image.shape
image = self.RB_convert(image)
#print('###line28: image:',image[10:12,10:12,0])
print('line32: image:',image[100,100,:],image.shape )
img = self.preprocess_image(image)
if self.device != 'cpu':
imgs = img.to(self.device)
@@ -37,7 +37,7 @@ class SegModel(object):
time1 = time.time()
self.model.eval()
with torch.no_grad():
#print('#### segmodel.py line35:',len(imgs),imgs[0].shape , imgs[0][0,10:12,10:12])
print(' segmodel.py line35:',len(imgs),imgs[0].shape , imgs[0,:,100,100])
output = self.model(imgs)
time2 = time.time()

+ 64
- 0
segutils/toTrt.py View File

@@ -0,0 +1,64 @@
from pathlib import Path
import torch
import os,sys
import argparse
sys.path.extend(['segutils'])
from model_stages import BiSeNet_STDC
from trtUtils2 import pth2onnx,onnx2engine,onnx_inference
def main(opt):
if opt.mWidth ==0 or opt.mHeight==0:
modelSize=None
else:
modelSize = ( int(opt.mHeight), int(opt.mWidth) )
model = BiSeNet_STDC(backbone='STDCNet813', n_classes=int(opt.nclass),
use_boundary_2=False, use_boundary_4=False,
use_boundary_8=True, use_boundary_16=False,
use_conv_last=False,
modelSize=modelSize
)
model.load_state_dict(torch.load(opt.weights.strip(), map_location='cuda:0' ))
#model= model.to(device)
#pth_model='../weights/best_mae.pth'
pth_model=opt.weights.strip()
onnx_name = pth_model.replace('.pth','_dynamic.onnx')
trt_name = onnx_name.replace('.onnx','.engine')
dynamic_hw ={'input':{0:'batch',2:'H',3:'W'},
'output0':{1:'C',2:'H',3:'W'},
'output1':{1:'C',2:'H',3:'W'},
}
inputShape =(1, 3, 128*4,128*4)#(bs,channels,height,width)
input_profile_shapes = [(1,3,256,256),(1,3,1024,1024),(1,3,2048,2048)]
pth2onnx(model,onnx_name,input_shape=(1,3,512,512),input_names=['input'],output_names=[ 'output0' ,'output1'],dynamix_axis=dynamic_hw)
onnx2engine(onnx_name,trt_name,input_shape=[1,3,-1,-1],half=True,max_batch_size=1,input_profile_shapes=input_profile_shapes)
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument('--weights', type=str, default='stdc_360X640.pth', help='model path(s)')
parser.add_argument('--nclass', type=int, default=2, help='segmodel nclass')
parser.add_argument('--mWidth', type=int, default=640, help='segmodel mWdith')
parser.add_argument('--mHeight', type=int, default=360, help='segmodel mHeight')
opt = parser.parse_args()
main(opt)

+ 84
- 36
stdc.py View File

@@ -3,18 +3,21 @@ import tensorrt as trt
import torch
import sys
from segutils.trtUtils import segPreProcess_image,segTrtForward,segPreProcess_image_torch
from segutils.segmodel import SegModel
from segutils.model_stages import BiSeNet_STDC
import time,cv2
import numpy as np
class stdcModel(object):
def __init__(self, weights=None,
par={'modelSize':(640,360),'nclass':2,'predResize':True,'mean':(0.485, 0.456, 0.406),'std' :(0.229, 0.224, 0.225),'numpy':False, 'RGB_convert_first':True}
par={'modelSize':(640,360),'dynamic':False,'nclass':2,'predResize':True,'mean':(0.485, 0.456, 0.406),'std' :(0.229, 0.224, 0.225),'numpy':False, 'RGB_convert_first':True}
):
self.par = par
self.device = 'cuda:0'
self.half =True
self.half =True
if 'dynamic' not in par.keys():
self.dynamic=False
else: self.dynamic=par['dynamic']
if weights.endswith('.engine'):
self. infer_type ='trt'
@@ -25,49 +28,94 @@ class stdcModel(object):
sys.exit(0)
if self.infer_type=='trt':
if self.dynamic :
print('####################ERROR##########,STDC动态模型不能采用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 = SegModel(nclass=par['seg_nclass'],weights=weights,device=self.device)
print('############load seg model pth success:',weights,self.model,par['seg_nclass'] )
if self.dynamic: modelSize=None
else: modelSize=( self.par['modelSize'][1], self.par['modelSize'][0] )
self.model = BiSeNet_STDC(backbone='STDCNet813', n_classes=par['seg_nclass'],
use_boundary_2=False, use_boundary_4=False,
use_boundary_8=True, use_boundary_16=False,
use_conv_last=False,
modelSize = modelSize
)
self.model.load_state_dict(torch.load(weights, map_location=torch.device(self.device) ))
self.model= self.model.to(self.device)
print('#########加载模型:',weights,' 类型:',self.infer_type)
def eval(self,image):
if self.infer_type=='trt':
seg_pred,segstr = self.segtrtEval(image)
else:
def preprocess_image(self,image):
image = self.RB_convert(image)
seg_pred,segstr = self.model.eval(image )
return seg_pred,segstr
if self.dynamic:
H,W=image.shape[0:2];
yscale = self.par['modelSize'][1]/H
xscale = self.par['modelSize'][0]/W
dscale = min(yscale,xscale)
re_size = ( int((dscale*W)//4*4), int( (dscale*H)//4*4 ) )
else: re_size = self.par['modelSize']
#print('####line 58:,', re_size,image.shape)
image = cv2.resize(image,re_size, interpolation=cv2.INTER_LINEAR)
image = image.astype(np.float32)
image /= 255.0
image[:, :, 0] -= self.par['mean'][0]
image[:, :, 1] -= self.par['mean'][1]
image[:, :, 2] -= self.par['mean'][2]
image[:, :, 0] /= self.par['std'][0]
image[:, :, 1] /= self.par['std'][1]
image[:, :, 2] /= self.par['std'][2]
image = np.transpose(image, (2, 0, 1))
image = torch.from_numpy(image).float()
image = image.unsqueeze(0)
if self.device != 'cpu':
image = image.to(self.device)
return image
def RB_convert(self,image):
image_c = image.copy()
image_c[:,:,0] = image[:,:,2]
image_c[:,:,2] = image[:,:,0]
return image_c
def get_ms(self,t1,t0):
return (t1-t0)*1000.0
def pthEval(self,image_array0):
seg_pred,segstr = self.model.eval(image_array0 )
return
def segtrtEval(self,image_array0):
time0_0=time.time()
H,W,C=image_array0.shape
#img_input = segPreProcess_image(image_array0,modelSize=self.par['modelSize'],mean=self.par['mean'],std =self.par['std'],numpy=self.par['numpy'], RGB_convert_first=self.par['RGB_convert_first'] )
#img_input = img_input.to(self.device)
#print('###line56:',img_input.size())
img_input = segPreProcess_image_torch(image_array0,modelSize=self.par['modelSize'],mean=self.par['mean'],std =self.par['std'],numpy=self.par['numpy'], RGB_convert_first=self.par['RGB_convert_first'] )
def eval(self,image):
time0 = time.time()
imageH, imageW, _ = image.shape
img = self.preprocess_image(image)
time1 = time.time()
time1_0=time.time()
pred=segTrtForward(self.model,[img_input])
time2_0=time.time()
if self.infer_type=='trt':
pred=segTrtForward(self.model,[img])
elif self.infer_type=='pth':
self.model.eval()
with torch.no_grad():
pred = self.model(img)
time2 = time.time()
pred=torch.argmax(pred,dim=1).cpu().numpy()[0]
time3_0 = time.time()
if 'predResize' in self.par.keys():
if self.par['predResize']:
pred = cv2.resize(pred.astype(np.uint8),(W,H))
else:
pred = cv2.resize(pred.astype(np.uint8),(W,H))
time4_0 = time.time()
segInfoStr= 'stdc:%.1f (pre-precess:%.1f ,infer:%.1f ,post-cpu-argmax:%.1f ,post-resize:%.1f) '%(self.get_ms(time4_0,time0_0), self.get_ms(time1_0,time0_0),self.get_ms(time2_0,time1_0),self.get_ms(time3_0,time2_0),self.get_ms(time4_0,time3_0) )
return pred,segInfoStr
time3 = time.time()
pred = cv2.resize(pred.astype(np.uint8),(imageW,imageH))
time4 = time.time()
outstr= 'pre-precess:%.1f ,infer:%.1f ,post-cpu-argmax:%.1f ,post-resize:%.1f, total:%.1f \n '%( self.get_ms(time1,time0),self.get_ms(time2,time1),self.get_ms(time3,time2),self.get_ms(time4,time3),self.get_ms(time4,time0) )
return pred,outstr

BIN
trackUtils/__pycache__/sort.cpython-38.pyc View File


+ 1
- 0
trackUtils/sort.py View File

@@ -410,6 +410,7 @@ class Sort(object):
for t in reversed(to_del):
self.trackers.pop(t)
# 将目标检测框与卡尔曼滤波器预测的跟踪框关联获取跟踪成功的目标,新增的目标,离开画面的目标
matched, unmatched_dets, unmatched_trks = associate_detections_to_trackers(dets, trks, self.iou_threshold)
# 将跟踪成功的目标框更新到对应的卡尔曼滤波器

BIN
utilsK/__pycache__/crackUtils.cpython-38.pyc View File


+ 36
- 0
utilsK/crackUtils.py View File

@@ -0,0 +1,36 @@
import numpy as np
from skimage.morphology import medial_axis
def Crack_measure(_mask_cv_gray,par={'dsx':(123-30)*1000/35*0.004387636 } ):
'''裂缝实际尺寸测量'''
'''输入:单个裂缝分割图像
过程:。
返回:最终绘制的结果图、最终落水人员(坐标、类别、置信度),
'''
# 图像转化
dsx = par['dsx']
###READ
img = np.array(_mask_cv_gray.astype(np.int32))
image0 = binary = img
###SKELETONIZATION
img_skeletonized, distance = medial_axis(image0, return_distance=True)
#print(img_skeletonized)
img_skeletonized = np.array(img_skeletonized.astype(np.int32))
###COMPUTING WIDTH
dist_on_skel = distance * img_skeletonized
width = dist_on_skel[dist_on_skel != 0] * 2
for i in range(len(width)):
if width[i] <= 2.0:
width[i] = width[i]
else:
width[i] = width[i] - 2
###OUTPUT
real_length = np.count_nonzero(img_skeletonized) *dsx # Each pixel remaining after
if len(width)==0:
return [0,0,0,0]
real_mean_width = np.mean(width)*dsx
real_max_width = np.max(width)*dsx
real_min_width = np.min(width)*dsx
return [real_length,real_mean_width,real_max_width,real_min_width]

+ 4
- 0
weights/conf/crackMeasurement/labelnames.json View File

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

BIN
weights/conf/crackMeasurement/stdc_360X640.pth View File


BIN
weights/conf/crackMeasurement/yolov5.pt View File


+ 5
- 0
weights/conf/crackMeasurement/权重对应类别.txt 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':网状裂缝 ]

Loading…
Cancel
Save