tuoheng_algN/vodsdk/util/QueRiver.py

347 lines
15 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

from kafka import KafkaProducer, KafkaConsumer
from kafka.errors import kafka_errors
import traceback
import json, base64,os
import numpy as np
from multiprocessing import Process,Queue
import time,cv2,string,random
import subprocess as sp
import matplotlib.pyplot as plt
from utils.datasets import LoadStreams, LoadImages
from models.experimental import attempt_load
from utils.general import check_img_size, check_requirements, check_imshow, non_max_suppression, apply_classifier, scale_coords, xyxy2xywh, strip_optimizer, set_logging, increment_path
import torch,sys
#from segutils.segmodel import SegModel,get_largest_contours
#sys.path.extend(['../yolov5/segutils'])
from segutils.segWaterBuilding import SegModel,get_largest_contours,illBuildings
#from segutils.core.models.bisenet import BiSeNet
from segutils.core.models.bisenet import BiSeNet_MultiOutput
from utils.plots import plot_one_box,plot_one_box_PIL,draw_painting_joint,get_label_arrays,get_websource
from collections import Counter
#import matplotlib
import matplotlib.pyplot as plt
# get_labelnames,get_label_arrays,post_process_,save_problem_images,time_str
#FP_DEBUG=open('debut.txt','w')
def bsJpgCode(image_ori):
jpgCode = cv2.imencode('.jpg',image_ori)[-1]###np.array,(4502009,1)
bsCode = str(base64.b64encode(jpgCode))[2:-1] ###str,长6002680
return bsCode
def bsJpgDecode(bsCode):
bsDecode = base64.b64decode(bsCode)###types,长4502009
npString = np.frombuffer(bsDecode,np.uint8)###np.array,(长4502009,)
jpgDecode = cv2.imdecode(npString,cv2.IMREAD_COLOR)###np.array,(3000,4000,3)
return jpgDecode
def get_ms(time0,time1):
str_time ='%.2f ms'%((time1-time0)*1000)
return str_time
rainbows=[
(0,0,255),(0,255,0),(255,0,0),(255,0,255),(255,255,0),(255,127,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)
]
def get_labelnames(labelnames):
with open(labelnames,'r') as fp:
namesjson=json.load(fp)
names_fromfile=namesjson['labelnames']
names = names_fromfile
return names
def check_stream(stream):
cap = cv2.VideoCapture(stream)
if cap.isOpened():
return True
else:
return False
#####
def drawWater(pred,image_array0,river={'color':(0,255,255),'line_width':3,'segRegionCnt':2}):####pred是模型的输出只有水分割的任务
##画出水体区域
contours, hierarchy = cv2.findContours(pred,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
water = pred.copy(); water[:,:] = 0
if len(contours)==0:
return image_array0,water
max_ids = get_largest_contours(contours,river['segRegionCnt']);
for max_id in max_ids:
cv2.fillPoly(water, [contours[max_id][:,0,:]], 1)
cv2.drawContours(image_array0,contours,max_id,river['color'],river['line_width'] )
return image_array0,water
def scale_back(boxes,padInfos):
top, left,r = padInfos[0:3]
boxes[:,0] = (boxes[:,0] - left) * r
boxes[:,2] = (boxes[:,2] - left) * r
boxes[:,1] = (boxes[:,1] - top) * r
boxes[:,3] = (boxes[:,3] - top) * r
return boxes
def img_pad(img, size, pad_value=[114,114,114]):
###填充成固定尺寸
H,W,_ = img.shape
r = max(H/size[0], W/size[1])
img_r = cv2.resize(img, (int(W/r), int(H/r)))
tb = size[0] - img_r.shape[0]
lr = size[1] - img_r.shape[1]
top = int(tb/2)
bottom = tb - top
left = int(lr/2)
right = lr - left
pad_image = cv2.copyMakeBorder(img_r, top, bottom, left, right, cv2.BORDER_CONSTANT,value=pad_value)
return pad_image,(top, left,r)
def post_process_(datas,conf_thres, iou_thres,names,label_arraylist,rainbows,iframe,ObjectPar={ 'object_config':[0,1,2,3,4], 'slopeIndex':[5,6,7] ,'segmodel':True,'segRegionCnt':1 },font={ 'line_thickness':None, 'fontSize':None,'boxLine_thickness':None,'waterLineColor':(0,255,255),'waterLineWidth':3},padInfos=None ):
object_config,slopeIndex,segmodel,segRegionCnt=ObjectPar['object_config'],ObjectPar['slopeIndex'],ObjectPar['segmodel'],ObjectPar['segRegionCnt']
##输入dataset genereate 生成的数据model预测的结果prednms参数
##主要操作NMS ---> 坐标转换 ---> 画图
##输出原图、AI处理后的图、检测结果
time0=time.time()
path, img, im0s, vid_cap ,pred,seg_pred= datas[0:6];
#segmodel=True
pred = non_max_suppression(pred, conf_thres, iou_thres, classes=None, agnostic=False)
time1=time.time()
i=0;det=pred[0]###一次检测一张图片
time1_1 = time.time()
#p, s, im0 = path[i], '%g: ' % i, im0s[i].copy()
p, s, im0 = path[i], '%g: ' % i, im0s[i]
time1_2 = time.time()
gn = torch.tensor(im0.shape)[[1, 0, 1, 0]] # normalization gain whwh
time1_3 = time.time()
det_xywh=[];
#im0_brg=cv2.cvtColor(im0,cv2.COLOR_RGB2BGR);
if segmodel:
if len(seg_pred)==2:
im0,water = illBuildings(seg_pred,im0)
else:
river={ 'color':font['waterLineColor'],'line_width':font['waterLineWidth'],'segRegionCnt':segRegionCnt }
im0,water = drawWater(seg_pred,im0,river)
time2=time.time()
#plt.imshow(im0);plt.show()
if len(det)>0:
# Rescale boxes from img_size to im0 size
if not padInfos:
det[:, :4] = scale_coords(img.shape[2:], det[:, :4],im0.shape).round()
else:
#print('####line131:',det[:, :])
det[:, :4] = scale_back( det[:, :4],padInfos).round()
#print('####line133:',det[:, :])
#用seg模型确定有效检测匡及河道轮廓线
if segmodel:
cls_indexs = det[:, 5].clone().cpu().numpy().astype(np.int32)
##判断哪些目标属于岸坡的
slope_flag = np.array([x in slopeIndex for x in cls_indexs ] )
det_c = det.clone(); det_c=det_c.cpu().numpy()
try:
area_factors = np.array([np.sum(water[int(x[1]):int(x[3]), int(x[0]):int(x[2])] )*1.0/(1.0*(x[2]-x[0])*(x[3]-x[1])+0.00001) for x in det_c] )
except:
print('*****************************line143: error:',det_c)
water_flag = np.array(area_factors>0.1)
det = det[water_flag|slope_flag]##如果是水上目标则需要与水的iou超过0.1;如果是岸坡目标,则直接保留。
#对检测匡绘图
for *xyxy, conf, cls in reversed(det):
xywh = (xyxy2xywh(torch.tensor(xyxy).view(1, 4)) / gn).view(-1).tolist() # normalized xywh
cls_c = cls.cpu().numpy()
if int(cls_c) not in object_config: ###如果不是所需要的目标,则不显示
continue
conf_c = conf.cpu().numpy()
line = [float(cls_c), *xywh, float(conf_c)] # label format
det_xywh.append(line)
label = f'{names[int(cls)]} {conf:.2f}'
im0 = draw_painting_joint(xyxy,im0,label_arraylist[int(cls)],score=conf,color=rainbows[int(cls)%20],font=font)
time3=time.time()
strout='nms:%s drawWater:%s,copy:%s,toTensor:%s,detDraw:%s '%(get_ms(time0,time1),get_ms(time1,time2),get_ms(time1_1,time1_2),get_ms(time1_2,time1_3), get_ms(time2,time3) )
return [im0s[0],im0,det_xywh,iframe],strout
def preprocess(par):
print('#####process:',par['name'])
##负责读取视频生成原图及供检测的使用图numpy格式
#source='rtmp://liveplay.yunhengzhizao.cn/live/demo_HD5M'
#img_size=640; stride=32
while True:
cap = cv2.VideoCapture(par['source'])
iframe = 0
if cap.isOpened():
print( '#### read %s success!'%(par['source']))
try:
dataset = LoadStreams(par['source'], img_size=640, stride=32)
for path, img, im0s, vid_cap in dataset:
datas=[path, img, im0s, vid_cap,iframe]
par['queOut'].put(datas)
iframe +=1
except Exception as e:
print('###read error:%s '%(par['source']))
time.sleep(10)
iframe = 0
else:
print('###read error:%s '%(par['source'] ))
time.sleep(10)
iframe = 0
def gpu_process(par):
print('#####process:',par['name'])
half=True
##gpu运算,检测模型
weights = par['weights']
device = par['device']
print('###line127:',par['device'])
model = attempt_load(par['weights'], map_location=par['device']) # load FP32 model
if half:
model.half()
##gpu运算分割模型
seg_nclass = par['seg_nclass']
seg_weights = par['seg_weights']
#segmodel = SegModel(nclass=seg_nclass,weights=seg_weights,device=device)
nclass = [2,2]
Segmodel = BiSeNet_MultiOutput(nclass)
weights='weights/segmentation/WaterBuilding.pth'
segmodel = SegModel(model=Segmodel,nclass=nclass,weights=weights,device='cuda:0',multiOutput=True)
while True:
if not par['queIn'].empty():
time0=time.time()
datas = par['queIn'].get()
path, img, im0s, vid_cap,iframe = datas[0:5]
time1=time.time()
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
time2 = time.time()
pred = model(img,augment=False)[0]
time3 = time.time()
seg_pred = segmodel.eval(im0s[0],outsize=None,smooth_kernel=20)
time4 = time.time()
fpStr= 'process:%s ,iframe:%d,getdata:%s,copygpu:%s,dettime:%s,segtime:%s , time:%s, queLen:%d '%( par['name'],iframe,get_ms(time0,time1) ,get_ms(time1,time2) ,get_ms(time2,time3) ,get_ms(time3,time4),get_ms(time0,time4) ,par['queIn'].qsize() )
#FP_DEBUG.write( fpStr+'\n' )
datasOut = [path, img, im0s, vid_cap,pred,seg_pred,iframe]
par['queOut'].put(datasOut)
if par['debug']:
print('#####process:',par['name'],' line107')
else:
time.sleep(1/300)
def get_cls(array):
dcs = Counter(array)
keys = list(dcs.keys())
values = list(dcs.values())
max_index = values.index(max(values))
cls = int(keys[max_index])
return cls
def save_problem_images(post_results,iimage_cnt,names,streamName='live-THSAHD5M',outImaDir='problems/images_tmp',imageTxtFile=False):
## [cls, x,y,w,h, conf]
problem_image=[[] for i in range(6)]
dets_list = [x[2] for x in post_results]
mean_scores=[ np.array(x)[:,5].mean() for x in dets_list ] ###mean conf
best_index = mean_scores.index(max(mean_scores)) ##获取该批图片里问题图片的index
best_frame = post_results[ best_index][3] ##获取绝对帧号
img_send = post_results[best_index][1]##AI处理后的图
img_bak = post_results[best_index][0]##原图
cls_max = get_cls( x[0] for x in dets_list[best_index] )
time_str = time.strftime("%Y-%m-%d-%H-%M-%S", time.localtime())
uid=''.join(random.sample(string.ascii_letters + string.digits, 16))
#ori_name = '2022-01-20-15-57-36_frame-368-720_type-漂浮物_qVh4zI08ZlwJN9on_s-live-THSAHD5M_OR.jpg'
#2022-01-13-15-07-57_frame-9999-9999_type-结束_9999999999999999_s-off-XJRW20220110115904_AI.jpg
outnameOR= '%s/%s_frame-%d-%d_type-%s_%s_s-%s_AI.jpg'%(outImaDir,time_str,best_frame,iimage_cnt,names[cls_max],uid,streamName)
outnameAR= '%s/%s_frame-%d-%d_type-%s_%s_s-%s_OR.jpg'%(outImaDir,time_str,best_frame,iimage_cnt,names[cls_max],uid,streamName)
cv2.imwrite(outnameOR,img_send)
cv2.imwrite(outnameAR,img_bak)
if imageTxtFile:
outnameOR_txt = outnameOR.replace('.jpg','.txt')
fp=open(outnameOR_txt,'w');fp.write(outnameOR+'\n');fp.close()
outnameAI_txt = outnameAR.replace('.jpg','.txt')
fp=open(outnameAI_txt,'w');fp.write(outnameAR+'\n');fp.close()
parOut = {}; parOut['imgOR'] = img_send; parOut['imgAR'] = img_send; parOut['uid']=uid
parOut['imgORname']=os.path.basename(outnameOR);parOut['imgARname']=os.path.basename(outnameAR);
parOut['time_str'] = time_str;parOut['type'] = names[cls_max]
return parOut
def post_process(par):
print('#####process:',par['name'])
###post-process参数
conf_thres,iou_thres,classes=par['conf_thres'],par['iou_thres'],par['classes']
labelnames=par['labelnames']
rainbows=par['rainbows']
fpsample = par['fpsample']
names=get_labelnames(labelnames)
label_arraylist = get_label_arrays(names,rainbows,outfontsize=40)
iimage_cnt = 0
post_results=[]
while True:
if not par['queIn'].empty():
time0=time.time()
datas = par['queIn'].get()
iframe = datas[6]
if par['debug']:
print('#####process:',par['name'],' line129')
p_result,timeOut = post_process_(datas,conf_thres, iou_thres,names,label_arraylist,rainbows,iframe)
par['queOut'].put(p_result)
##输出结果
##每隔 fpsample帧处理一次如果有问题就保存图片
if (iframe % fpsample == 0) and (len(post_results)>0) :
#print('####line204:',iframe,post_results)
save_problem_images(post_results,iframe,names)
post_results=[]
if len(p_result[2] )>0: ##
#post_list = p_result.append(iframe)
post_results.append(p_result)
#print('####line201:',type(p_result))
time1=time.time()
outstr='process:%s ,iframe:%d,%s , time:%s, queLen:%d '%( par['name'],iframe,timeOut,get_ms(time0,time1) ,par['queIn'].qsize() )
#FP_DEBUG.write(outstr +'\n')
#print( 'process:%s ,iframe:%d,%s , time:%s, queLen:%d '%( par['name'],iframe,timeOut,get_ms(time0,time1) ,par['queIn'].qsize() ) )
else:
time.sleep(1/300)
def save_logfile(name,txt):
if os.path.exists(name):
fp=open(name,'r+')
else:
fp=open(name,'w')
fp.write('%s %s \n'%(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()),txt))
fp.close()
def time_str():
return time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
if __name__=='__main__':
jsonfile='config/queRiver.json'
#image_encode_decode()
work_stream(jsonfile)
#par={'name':'preprocess'}
#preprocess(par)