DSP
This commit is contained in:
commit
b33d091cbd
|
|
@ -0,0 +1,353 @@
|
|||
from PIL import Image
|
||||
import numpy as np
|
||||
import cv2
|
||||
import base64
|
||||
import io,os
|
||||
import requests
|
||||
import time,json
|
||||
import string,random
|
||||
import glob,string,sys
|
||||
from multiprocessing import Process,Queue
|
||||
import oss2,copy
|
||||
from kafka import KafkaProducer, KafkaConsumer
|
||||
from utilsK.sendUtils import *
|
||||
|
||||
from utilsK.masterUtils import create_logFile,wrtiteLog,writeELK_log,send_kafka
|
||||
from voduploadsdk.UploadVideoRequest import UploadVideoRequest
|
||||
from voduploadsdk.AliyunVodUtils import *
|
||||
from voduploadsdk.AliyunVodUploader import AliyunVodUploader
|
||||
import hashlib
|
||||
from kafka.errors import kafka_errors
|
||||
##for CeKanYuan
|
||||
#10月21日,通过图像名称判断,是那个平台。方式不好。
|
||||
#10月22日,改成访问固定的地址,从地址中读取,平台的名称与地址。每隔2分钟访问一次。
|
||||
#3月18日,采用OSS阿里云存储桶
|
||||
#platform_query_url='http://47.96.182.154:9051/api/suanfa/getPlatformInfo'
|
||||
platform_query_url='SendLog/platformQuery.json'
|
||||
api = 'http://121.40.249.52:9050/api/taskFile/submitUAVKHQuestion'
|
||||
#api = 'http://47.98.157.120:9040/api/taskFile/submitUAVKHQuestion'
|
||||
|
||||
##这套名字,是联通的。
|
||||
name_dic={
|
||||
"排口":"入河、湖排口",
|
||||
"排污口": "入河、湖排口",
|
||||
"水生植被": "水生植物",
|
||||
"漂浮物": "有大面积漂物",
|
||||
"结束": "结束",
|
||||
'其它' :'其它'
|
||||
}
|
||||
## for TH river
|
||||
##这套代码是河长制度的。
|
||||
'''
|
||||
nameID_dic={
|
||||
"排口":'00000',
|
||||
"排污口": '8378',
|
||||
"水生植被": '8380',
|
||||
"漂浮物": '8368',
|
||||
"结束":'9999',
|
||||
"其它":'8888'
|
||||
}
|
||||
'''
|
||||
|
||||
msg_dict_off={
|
||||
"request_id":"fflvgyntTsZCamqjuLArkiSYIbKXEeWx",#消息ID标识
|
||||
"status":"running",#任务状态
|
||||
"type":str(2),#消息类型 1:实时 2:离线
|
||||
#"error":str(9999),#错误信息####
|
||||
"error_code":"",#//错误编号
|
||||
"error_msg":"",#//错误描述
|
||||
"progress":"",
|
||||
"results":[#问题结果
|
||||
{
|
||||
"original_url":"",#原图地址
|
||||
"sign_url":"",#AI标记地址
|
||||
"category_id":"",#分类标识
|
||||
"description":"",#问题描述
|
||||
"analyse_time":"",#时间戳
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
msg_dict_on={
|
||||
"request_id":"nnlvgyntTsZCamqjuLArkiSYIbKXEeWx",#消息ID标识
|
||||
"status":"running",#任务状态
|
||||
"type":str(1),#消息类型 1:实时 2:离线
|
||||
"error_code":"",#//错误编号
|
||||
"error_msg":"",#//错误描述
|
||||
"progressOn":"",
|
||||
"results":[#问题结果
|
||||
{
|
||||
"original_url":"",#原视频地址(离线识别时为空不传,实时识别时需要上传)
|
||||
"sign_url":"",#识别后视频地址
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
|
||||
def mintor_offline_ending(parIn):
|
||||
|
||||
indir,server,topic,fp_log = parIn['indir'],parIn['server'],parIn['topic'] ,parIn['fp_log']
|
||||
par_kafka={};par_kafka['server']=server;par_kafka['topic']=topic;
|
||||
logger = parIn['logger'];thread='Send-tranfer-oss:mintor-offline-ending'
|
||||
time_interval = parIn['timeInterval']
|
||||
###轮询image_tmp的文件夹,每10s一次,一旦产生离线结束标志,则不停地发送没30秒heartbeat信号。
|
||||
producer = KafkaProducer(
|
||||
bootstrap_servers=par_kafka['server'],#tencent yun
|
||||
value_serializer=lambda v: v.encode('utf-8'),
|
||||
metadata_max_age_ms=120000,
|
||||
)
|
||||
outStrList={}
|
||||
writeELK_log(msg='child processs starts',fp=fp_log,thread=thread,level='INFO',line=sys._getframe().f_lineno,logger=logger)
|
||||
time_ss0=time.time()
|
||||
while True:
|
||||
|
||||
filelist_AI = sorted(glob.glob('%s/*_AI.txt'%(indir)),key=os.path.getmtime)
|
||||
filelist = filelist_AI
|
||||
|
||||
off_msgs=[]
|
||||
|
||||
for filename in filelist[0:]:
|
||||
filename_base = os.path.basename(filename)
|
||||
##解析文件名
|
||||
typename,requestId,onLineType = parse_filename_for_oss(filename_base)
|
||||
if (onLineType=='off') and (typename=='结束'):
|
||||
off_msgs.append(requestId)
|
||||
|
||||
for requestId in off_msgs:
|
||||
msg_heart = copy.deepcopy(msg_dict_off)
|
||||
msg_heart['status']='running'
|
||||
msg_heart["request_id"]=requestId
|
||||
msg_heart = json.dumps(msg_heart, ensure_ascii=False)
|
||||
|
||||
outStrList['success']= '----- send heartBeat in Transfer success, msg:%s '%(requestId)
|
||||
outStrList['failure']='----- kafka error when sending heartBeat in Transfer '
|
||||
outStrList['Refailure']='----- kafka error when Re-sending heartBeat in Transfer '
|
||||
|
||||
|
||||
send_kafka(producer,par_kafka,msg_heart,outStrList,fp_log,line=sys._getframe().f_lineno,logger=logger,thread=thread );
|
||||
|
||||
time.sleep(time_interval)
|
||||
time_ss1=time.time()
|
||||
if time_ss1 - time_ss0>120:
|
||||
outstrs = 'child process sleeping:%f s '%(time_ss1-time_ss0)
|
||||
writeELK_log(msg=outstrs,fp=fp_log,thread=thread,level='INFO',line=sys._getframe().f_lineno,logger=logger)
|
||||
time_ss0=time_ss1
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
def test5(par):
|
||||
|
||||
indir,outdir,logdir,jsonDir = par['indir'],par['outdir'],par['logdir'],par['jsonDir']
|
||||
hearBeatTimeMs = par['hearBeatTimeMs']
|
||||
videoBakDir,ossPar,vodPar,kafkaPar = par['videoBakDir'], par['ossPar'],par['vodPar'],par['kafkaPar']
|
||||
|
||||
|
||||
|
||||
time0_0 = time.time();logname='SendPics.log';thread='Send-tranfer-oss:main'
|
||||
fp_log=create_logFile(logdir=logdir,name=logname)
|
||||
|
||||
logger=logdir.replace('/','.')+'.'+logname
|
||||
writeELK_log(msg='Send_tranfer_oss process starts',fp=fp_log,thread=thread,level='INFO',line=sys._getframe().f_lineno,logger=logger)
|
||||
nameID_dic=getNamedic(par['labelnamesFile'].strip())
|
||||
|
||||
parIn={};####给心跳信号发射的子进程参数
|
||||
parIn['indir'],parIn['server'],parIn['topic'] ,parIn['fp_log']=indir,kafkaPar['boostServer'],kafkaPar['topic'],fp_log
|
||||
parIn['timeInterval'] = hearBeatTimeMs;parIn['logger']=logger
|
||||
HeartProcess=Process(target=mintor_offline_ending,name='process-sendHeartOnly',args=(parIn,))
|
||||
HeartProcess.start()
|
||||
|
||||
|
||||
ifind=0
|
||||
time0_0 = time.time()
|
||||
|
||||
producer = KafkaProducer(
|
||||
bootstrap_servers=kafkaPar['boostServer'],#tencent yun
|
||||
value_serializer=lambda v: v.encode('utf-8'),
|
||||
metadata_max_age_ms=120000,
|
||||
)
|
||||
|
||||
|
||||
|
||||
|
||||
###登陆准备存储桶
|
||||
auth = oss2.Auth(ossPar['AId'], ossPar['ASt'])
|
||||
# Endpoint以杭州为例,其它Region请按实际情况填写。
|
||||
bucket = oss2.Bucket(auth, ossPar['Epoint'], ossPar['bucketName'])
|
||||
|
||||
##VOD
|
||||
clt = init_vod_client(vodPar['AId'], vodPar['ASt'])
|
||||
uploader = AliyunVodUploader(vodPar['AId'], vodPar['ASt'])
|
||||
|
||||
|
||||
writeELK_log(msg='Load Parameter over',fp=fp_log,thread=thread,level='INFO',line=sys._getframe().f_lineno,logger=logger)
|
||||
par_heart={};outStrList={}
|
||||
time_b0=time.time()
|
||||
while True:
|
||||
|
||||
filelist_AI = sorted(glob.glob('%s/*_AI.txt'%(indir)),key=os.path.getmtime)
|
||||
filelist=[]
|
||||
for filename in filelist_AI:
|
||||
filename_base = os.path.basename(filename)
|
||||
typename,requestId,onLineType = parse_filename_for_oss(filename_base)
|
||||
if typename in ["其它"]:
|
||||
continue
|
||||
filelist.append(filename)
|
||||
|
||||
if len(filelist)!=0:
|
||||
time0 = time.time()
|
||||
for filename in filelist[0:]:
|
||||
filename_base = os.path.basename(filename)
|
||||
##解析文件名
|
||||
typename,requestId,onLineType = parse_filename_for_oss(filename_base)
|
||||
|
||||
##存储文件
|
||||
filename_OR=filename.replace('_AI.','_OR.')
|
||||
|
||||
filename_AI_image = filename.replace('.txt','.jpg')
|
||||
filename_OR_image = filename_OR.replace('.txt','.jpg')
|
||||
|
||||
taskInfos = lodaMsgInfos(jsonDir,requestId)
|
||||
oss_dir = taskInfos['results_base_dir']
|
||||
|
||||
#if typename in ["排口","其它"]:
|
||||
# continue
|
||||
if typename not in ['结束','超时结束']:
|
||||
|
||||
time_s1 = time.time()
|
||||
ObjectName_AI=os.path.join(oss_dir,os.path.basename(filename_AI_image))
|
||||
ObjectName_OR=os.path.join(oss_dir,os.path.basename(filename_OR_image))
|
||||
bucket.put_object_from_file(ObjectName_AI, filename_AI_image)
|
||||
ret2=bucket.put_object_from_file(ObjectName_OR, filename_OR_image)
|
||||
|
||||
outstr=' oss bucket upload %s %s %s '%('***'*3,'Send:',filename)
|
||||
#outstr=wrtiteLog(fp_log,outstr);print( outstr);
|
||||
writeELK_log(msg=outstr,fp=fp_log,thread=thread,level='INFO',line=sys._getframe().f_lineno,logger=logger)
|
||||
|
||||
msg = copy.deepcopy(msg_dict_off)
|
||||
if onLineType!='off': msg['type']=str(1)
|
||||
else: msg['type']=str(2)
|
||||
msg['results'][0]['original_url']= ObjectName_OR
|
||||
msg['results'][0]['sign_url']= ObjectName_AI
|
||||
msg['results'][0]['category_id']= nameID_dic[typename]
|
||||
msg['results'][0]['description']= typename
|
||||
msg['results'][0]['analyse_time']= time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
|
||||
msg = update_json(taskInfos,msg)
|
||||
time_s2 = time.time()
|
||||
else:
|
||||
time_s1 = time.time()
|
||||
if onLineType!='off':
|
||||
msg = copy.deepcopy(msg_dict_on)
|
||||
msg["request_id"]=requestId ;msg['type']=str(1)
|
||||
msg['results'][0]['original_url']= "yourAddess"
|
||||
msg['results'][0]['sign_url']= "yourAddess"###最新的视频文件
|
||||
upCnt=1;upLoaded=False
|
||||
while upCnt<4:
|
||||
try:
|
||||
videoUrl=os.path.join(videoBakDir,requestId+'_AI.MP4')
|
||||
uploadVideoRequest = UploadVideoRequest(videoUrl, 'offLineVideo')
|
||||
videoId = uploader.uploadLocalVideo(uploadVideoRequest)
|
||||
|
||||
VideoId_AI=str(videoId['VideoId'])
|
||||
|
||||
videoUrl=os.path.join(videoBakDir,requestId+'_OR.MP4')
|
||||
uploadVideoRequest = UploadVideoRequest(videoUrl, 'offLineVideo')
|
||||
videoId = uploader.uploadLocalVideo(uploadVideoRequest)
|
||||
VideoId_OR=str(videoId['VideoId'])
|
||||
|
||||
outstr=VideoId_OR+','+VideoId_AI
|
||||
writeELK_log(msg=outstr,fp=fp_log,thread=thread,level='INFO',line=sys._getframe().f_lineno,logger=logger)
|
||||
msg['results'][0]['sign_url']=VideoId_AI
|
||||
msg['results'][0]['original_url']=VideoId_OR
|
||||
upCnt=4;upLoaded=True
|
||||
except Exception as e:
|
||||
writeELK_log(msg='video uploading error:%s, times:%d'%(e,upCnt),fp=fp_log,thread=thread,level='WARNING',line=sys._getframe().f_lineno,logger=logger);
|
||||
upCnt+=1;upLoaded=False
|
||||
if not upLoaded:
|
||||
msg['error_msg']='video uploading failure' ; msg['error_code']='101' ;
|
||||
|
||||
|
||||
else:
|
||||
msg = copy.deepcopy(msg_dict_off)
|
||||
msg['type']=str(2)
|
||||
msg["request_id"]=requestId
|
||||
msg['results'][0]['original_url']= taskInfos['original_url']
|
||||
videoUrl=os.path.join(videoBakDir,requestId+'.MP4')
|
||||
upCnt=1;upLoaded=False
|
||||
while upCnt<4:
|
||||
try:
|
||||
uploadVideoRequest = UploadVideoRequest(videoUrl, 'offLineVideo')
|
||||
videoId = uploader.uploadLocalVideo(uploadVideoRequest)
|
||||
outstr=' oss upload video over %s '%(str(videoId['VideoId']))
|
||||
writeELK_log(msg=outstr,fp=fp_log,thread=thread,level='INFO',line=sys._getframe().f_lineno,logger=logger)
|
||||
msg['results'][0]['sign_url']= str(videoId['VideoId'])###最新的视频文件
|
||||
upCnt=4;upLoaded=True
|
||||
except Exception as e:
|
||||
writeELK_log(msg='video uploading error:%s, times:%d'%(e,upCnt),fp=fp_log,thread=thread,level='WARNING',line=sys._getframe().f_lineno,logger=logger);
|
||||
upCnt+=1;upLoaded=False
|
||||
if not upLoaded:
|
||||
msg['error_msg']='video uploading failure' ; msg['error_code']='101' ;
|
||||
if upLoaded:
|
||||
if typename=='结束': msg["status"]="success"
|
||||
else: msg["status"]="timeout"
|
||||
else:
|
||||
msg["status"]='failed'
|
||||
time_s2 = time.time()
|
||||
|
||||
msg = json.dumps(msg, ensure_ascii=False)
|
||||
future = producer.send(
|
||||
kafkaPar['topic'],
|
||||
msg
|
||||
)
|
||||
|
||||
|
||||
try:
|
||||
record_metadata = future.get()
|
||||
outstr='kafka send:%s msg:%s producer status:%s'%(onLineType,msg,producer.bootstrap_connected())
|
||||
#outstr=wrtiteLog(fp_log,outstr);print( outstr);
|
||||
writeELK_log(msg=outstr,fp=fp_log,thread=thread,level='INFO',line=sys._getframe().f_lineno,logger=logger)
|
||||
except Exception as e:
|
||||
outstr='kafka ERROR:%s'%(str(e))
|
||||
#outstr=wrtiteLog(fp_log,outstr);print( outstr);
|
||||
writeELK_log(msg=outstr,fp=fp_log,thread=thread,level='WARNING',line=sys._getframe().f_lineno,logger=logger)
|
||||
producer.close()
|
||||
|
||||
producer = KafkaProducer(
|
||||
bootstrap_servers=kafkaPar['boostServer'],#tencent yun
|
||||
value_serializer=lambda v: v.encode('utf-8')
|
||||
)
|
||||
try:
|
||||
future = producer.send(kafkaPar['topic'], msg).get()
|
||||
except Exception as e:
|
||||
outstr='kafka resend ERROR:%s'%(str(e))
|
||||
#poutstr=wrtiteLog(fp_log,outstr);print( outstr);
|
||||
writeELK_log(msg=outstr,fp=fp_log,thread=thread,level='ERROR',line=sys._getframe().f_lineno,logger=logger)
|
||||
|
||||
|
||||
time_s3 = time.time()
|
||||
|
||||
##上传后的图片,移走到另外一个文件夹###
|
||||
cmd = 'mv \'%s\' \'%s\' '%(filename,outdir); os.system(cmd)
|
||||
cmd = 'mv \'%s\' \'%s\' '%(filename_OR,outdir); os.system(cmd)
|
||||
time_s4 = time.time()
|
||||
print('-'*50)
|
||||
|
||||
else:
|
||||
time.sleep(1)
|
||||
time_b1=time.time()
|
||||
if time_b1-time_b0>120:
|
||||
writeELK_log(msg='send main process sleeping',fp=fp_log,thread=thread,level='INFO',line=sys._getframe().f_lineno,logger=logger)
|
||||
time_b0=time_b1
|
||||
fp_log.close()
|
||||
|
||||
if __name__=='__main__':
|
||||
|
||||
masterFile="conf/send_oss.json"
|
||||
assert os.path.exists(masterFile)
|
||||
with open(masterFile,'r') as fp:
|
||||
par=json.load(fp)
|
||||
|
||||
test5(par)
|
||||
|
|
@ -0,0 +1,595 @@
|
|||
import numpy as np
|
||||
import time,ast,copy
|
||||
#from flask import request, Flask,jsonify
|
||||
import base64,cv2,os,sys,json
|
||||
#sys.path.extend(['../yolov5'])
|
||||
#from Send_tranfer import b64encode_function,JsonSend,name_dic,nameID_dic,getLogFileFp
|
||||
from segutils.segmodel import SegModel,get_largest_contours
|
||||
from models.experimental import attempt_load
|
||||
from utils.datasets import LoadStreams, LoadImages
|
||||
from utils.torch_utils import select_device, load_classifier, time_synchronized
|
||||
from queRiver import get_labelnames,get_label_arrays,post_process_,save_problem_images,time_str
|
||||
import subprocess as sp
|
||||
import matplotlib.pyplot as plt
|
||||
import torch,random,string
|
||||
import multiprocessing
|
||||
from multiprocessing import Process,Queue
|
||||
import traceback
|
||||
from kafka import KafkaProducer, KafkaConsumer,TopicPartition
|
||||
from kafka.errors import kafka_errors
|
||||
|
||||
#torch.multiprocessing.set_start_method('spawn')
|
||||
import utilsK
|
||||
from utilsK.GPUtils import *
|
||||
from utilsK.masterUtils import *
|
||||
from utilsK.sendUtils import create_status_msg,update_json
|
||||
|
||||
#from utilsK.modelEval import onlineModelProcsss
|
||||
import random,string
|
||||
from DSP_Send_tranfer_oss import msg_dict_on,msg_dict_off
|
||||
|
||||
process_id=0
|
||||
|
||||
def onlineModelProcess(parIn ):
|
||||
DEBUG=False
|
||||
streamName = parIn['streamName']
|
||||
childCallback=parIn['callback']
|
||||
outStrList={}
|
||||
object_config=parIn['object_config']
|
||||
allowedList,allowedList_string=get_needed_objectsIndex(object_config)
|
||||
|
||||
|
||||
#try:
|
||||
for wan in ['test']:
|
||||
jsonfile=parIn['modelJson']
|
||||
with open(jsonfile,'r') as fp:
|
||||
parAll = json.load(fp)
|
||||
|
||||
Detweights=parAll['gpu_process']['det_weights']
|
||||
seg_nclass = parAll['gpu_process']['seg_nclass']
|
||||
Segweights = parAll['gpu_process']['seg_weights']
|
||||
StreamRecoveringTime=int(parAll['StreamRecoveringTime'])
|
||||
TaskStatusQueryUrl=parAll["TaskStatusQueryUrl"]
|
||||
videoSave = parAll['AI_video_save']
|
||||
imageTxtFile = parAll['imageTxtFile']
|
||||
taskId,msgId = streamName.split('-')[1:3]
|
||||
|
||||
inSource,outSource=parIn['inSource'],parIn['outSource']
|
||||
|
||||
##构建日志文件
|
||||
if outSource != 'NO':
|
||||
logdir = parAll['logChildProcessOnline']
|
||||
waitingTime=parAll['StreamWaitingTime']
|
||||
else:
|
||||
logdir = parAll['logChildProcessOffline']
|
||||
waitingTime=5
|
||||
logname='gpuprocess.log'
|
||||
fp_log=create_logFile(logdir=logdir,name=logname)
|
||||
logger=logdir.replace('/','.')+'.'+logname
|
||||
kafka_par=parIn['kafka_par']
|
||||
producer = KafkaProducer(bootstrap_servers=kafka_par['server'],value_serializer=lambda v: v.encode('utf-8'),metadata_max_age_ms=120000)
|
||||
|
||||
####要先检查视频的有效性
|
||||
###开始的时候,如果在线任务没有流,要发送的心跳消息,msg_h,
|
||||
msg_h= copy.deepcopy(msg_dict_off);
|
||||
msg_h['status']='waiting';msg_h['request_id']=msgId
|
||||
|
||||
|
||||
thread='master:gpuprocess-%s'%(msgId)
|
||||
if outSource == 'NO':
|
||||
msg_h['type']=2
|
||||
Stream_ok,_= get_fps_rtmp(inSource,video=True)
|
||||
else:
|
||||
msg_h['type']=1
|
||||
msg_h_d = json.dumps(msg_h, ensure_ascii=False)
|
||||
outStrList=get_infos(taskId, msgId,msg_h_d,key_str='waiting stream or video, send heartbeat')
|
||||
Stream_ok=check_stream(inSource,producer,kafka_par,msg_h_d,outStrList,fp_log,logger,line=sys._getframe().f_lineno,thread=thread ,timeMs=waitingTime)
|
||||
|
||||
if Stream_ok:###发送开始信号
|
||||
msg_h['status']='running'
|
||||
msg_h_d = json.dumps(msg_h, ensure_ascii=False)
|
||||
outStrList= get_infos(taskId, msgId,msg_h_d,key_str='informing stream/video is ok')
|
||||
send_kafka(producer,kafka_par,msg_h_d,outStrList,fp_log,line=sys._getframe().f_lineno,logger=logger,thread=thread );
|
||||
|
||||
else:
|
||||
####检测离线视频是否有效,无效要报错
|
||||
outstr='offline vedio or live stream Error:%s '%(inSource)
|
||||
#outstr=wrtiteLog(fp_log,outstr);print( outstr);
|
||||
writeELK_log(msg=outstr,fp=fp_log,level='ERROR',line=sys._getframe().f_lineno,logger=logger)
|
||||
|
||||
msg_h['error_msg']='Stream or video ERROR';msg_h['error_code']='102' ;msg_h['status']='failed';
|
||||
msg_h_d = json.dumps(msg_h, ensure_ascii=False);
|
||||
outStrList= get_infos(taskId, msgId,msg_h_d,key_str='informing invaid video or stream success')
|
||||
send_kafka(producer,kafka_par,msg_h_d,outStrList,fp_log ,line=sys._getframe().f_lineno,logger=logger,thread=thread );
|
||||
childCallback.send(' offline vedio or live stream Error')
|
||||
continue
|
||||
allowedList_string='allow index are:'+ allowedList_string
|
||||
writeELK_log(msg=allowedList_string,fp=fp_log,line=sys._getframe().f_lineno,logger=logger)
|
||||
|
||||
|
||||
if (inSource.endswith('.MP4')) or (inSource.endswith('.mp4')):
|
||||
fps,outW,outH,totalcnt=get_fps_rtmp(inSource,video=True)[1][0:4];
|
||||
else:
|
||||
fps,outW,outH,totalcnt=get_fps_rtmp(inSource,video=False)[1][0:4]
|
||||
fps = int(fps+0.5)
|
||||
if fps>30: fps=25 ###线下测试时候,有时候读帧率是9000,明显不符合实际,所以加这个判断。
|
||||
if outSource != 'NO':
|
||||
command=['/usr/bin/ffmpeg','-y','-f', 'rawvideo','-vcodec','rawvideo','-pix_fmt', 'bgr24',
|
||||
'-s', "{}x{}".format(outW,outH),# 图片分辨率
|
||||
'-r', str(fps),# 视频帧率
|
||||
'-i', '-','-c:v',
|
||||
'libx264',
|
||||
'-pix_fmt', 'yuv420p',
|
||||
'-f', 'flv',outSource
|
||||
]
|
||||
|
||||
|
||||
video_flag = videoSave['onLine']
|
||||
logdir = parAll['logChildProcessOnline']
|
||||
waitingTime=parAll['StreamWaitingTime']
|
||||
else:
|
||||
video_flag = videoSave['offLine'] ;logdir = parAll['logChildProcessOffline']
|
||||
waitingTime=5
|
||||
|
||||
device = select_device(parIn['device'])
|
||||
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)
|
||||
|
||||
|
||||
|
||||
|
||||
##后处理参数
|
||||
par=parAll['post_process']
|
||||
conf_thres,iou_thres,classes=par['conf_thres'],par['iou_thres'],par['classes']
|
||||
outImaDir = par['outImaDir']
|
||||
outVideoDir = par['outVideoDir']
|
||||
labelnames=par['labelnames']
|
||||
rainbows=par['rainbows']
|
||||
fpsample = par['fpsample']
|
||||
names=get_labelnames(labelnames)
|
||||
label_arraylist = get_label_arrays(names,rainbows,outfontsize=40)
|
||||
|
||||
#dataset = LoadStreams(inSource, img_size=640, stride=32)
|
||||
|
||||
|
||||
childCallback.send('####model load success####')
|
||||
print('#####line153:',outVideoDir,video_flag)
|
||||
if (outVideoDir!='NO') : ####2022.06.27新增在线任务也要传AI视频和原始视频
|
||||
if video_flag:
|
||||
request_id = streamName.split('-')[2]
|
||||
save_path = os.path.join(outVideoDir,request_id+'.MP4')
|
||||
vid_writer = cv2.VideoWriter(save_path, cv2.VideoWriter_fourcc(*'mp4v'), fps, (outW,outH))
|
||||
if vid_writer.isOpened(): outstr='touch video success:%s'%(save_path);level='INFO'
|
||||
else:outstr='touch video failed:%s'%(save_path);level='ERROR'
|
||||
writeELK_log(msg=outstr,fp=fp_log,level=level,line=sys._getframe().f_lineno,logger=logger)
|
||||
else:
|
||||
request_id = streamName.split('-')[2]
|
||||
save_path_OR = os.path.join(outVideoDir,request_id+'_OR.MP4')
|
||||
vid_writer_OR = cv2.VideoWriter(save_path_OR, cv2.VideoWriter_fourcc(*'mp4v'), fps, (outW,outH))
|
||||
save_path_AI = os.path.join(outVideoDir,request_id+'_AI.MP4')
|
||||
vid_writer_AI = cv2.VideoWriter(save_path_AI, cv2.VideoWriter_fourcc(*'mp4v'), fps, (outW,outH))
|
||||
if vid_writer_AI.isOpened() and vid_writer_OR.isOpened() :outstr='touch video success:%s,%s'%(save_path_OR,save_path_AI);level='INFO'
|
||||
else:outstr='touch video failed:%s,%s, fps:%d ,%d , %d'%(save_path_OR,save_path_AI,fps,outW,outH);level='ERROR'
|
||||
writeELK_log(msg=outstr,fp=fp_log,level=level,line=sys._getframe().f_lineno,logger=logger)
|
||||
|
||||
iframe = 0;post_results=[];time_beg=time.time()
|
||||
|
||||
t00=time.time()
|
||||
time_kafka0=time.time()
|
||||
|
||||
Pushed_Flag=False
|
||||
while True:
|
||||
try:
|
||||
dataset = LoadStreams(inSource, img_size=640, stride=32)
|
||||
# 管道配置,其中用到管道
|
||||
if outSource !='NO' and (not Pushed_Flag):
|
||||
ppipe = sp.Popen(command, stdin=sp.PIPE);Pushed_Flag = True
|
||||
for path, img, im0s, vid_cap in dataset:
|
||||
t0= time_synchronized()
|
||||
if outSource == 'NO':###如果不推流,则显示进度条。离线不推流
|
||||
view_bar(iframe,totalcnt,time_beg ,parIn['process_uid'] )
|
||||
streamCheckCnt=0
|
||||
###直播和离线都是1分钟发一次消息
|
||||
time_kafka1 = time.time()
|
||||
if time_kafka1 - time_kafka0 >60:
|
||||
time_kafka0 = time_kafka1
|
||||
###发送状态信息waiting
|
||||
msg = copy.deepcopy(msg_dict_off);
|
||||
msg['request_id']= msgId;
|
||||
if outSource == 'NO':
|
||||
msg['progress']= '%.4f'%(iframe*1.0/totalcnt)
|
||||
msg['type']=2
|
||||
else:
|
||||
msg['progressOn']= str(iframe)
|
||||
msg['type']=1
|
||||
|
||||
msg = json.dumps(msg, ensure_ascii=False)
|
||||
outStrList= get_infos(taskId, msgId,msg,key_str='processing send progressbar or online heartbeat')
|
||||
send_kafka(producer,kafka_par,msg,outStrList,fp_log,line=sys._getframe().f_lineno,logger=logger,thread=thread );
|
||||
|
||||
time0=time.time()
|
||||
iframe +=1
|
||||
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
|
||||
|
||||
timeseg0 = time.time()
|
||||
seg_pred,segstr = segmodel.eval(im0s[0] )
|
||||
timeseg1 = time.time()
|
||||
|
||||
t1= time_synchronized()
|
||||
|
||||
pred = model(img,augment=False)[0]
|
||||
|
||||
time4 = time.time()
|
||||
datas = [path, img, im0s, vid_cap,pred,seg_pred,iframe]
|
||||
# "labelnames":["排口","排口","水生植被","漂浮物","其它"]
|
||||
|
||||
p_result,timeOut = post_process_(datas,conf_thres, iou_thres,names,label_arraylist,rainbows,iframe,object_config=allowedList)
|
||||
t2= time_synchronized()
|
||||
|
||||
#print('###line138:',timeOut,outSource,outVideoDir)
|
||||
##每隔 fpsample帧处理一次,如果有问题就保存图片
|
||||
if (iframe % fpsample == 0) and (len(post_results)>0) :
|
||||
parImage=save_problem_images(post_results,iframe,names,streamName=streamName,outImaDir='problems/images_tmp',imageTxtFile=imageTxtFile)
|
||||
post_results=[]
|
||||
|
||||
if len(p_result[2] )>0: ##
|
||||
post_results.append(p_result)
|
||||
t3= time_synchronized()
|
||||
image_array = p_result[1]
|
||||
if outSource!='NO':
|
||||
ppipe.stdin.write(image_array.tobytes())
|
||||
|
||||
if (outVideoDir!='NO'):
|
||||
if video_flag: ret = vid_writer.write(image_array)
|
||||
else:
|
||||
time_w0=time.time()
|
||||
ret = vid_writer_AI.write(image_array)
|
||||
ret = vid_writer_OR.write(im0s[0])
|
||||
time_w1=time.time()
|
||||
#if not ret:
|
||||
# print('\n write two videos time:%f ms'%(time_w1-time_w0)*1000,ret)
|
||||
t4= time_synchronized()
|
||||
|
||||
timestr2 = time.strftime("%Y-%m-%d-%H-%M-%S", time.localtime())
|
||||
if iframe%100==0:
|
||||
outstr='%s,,read:%.1f ms,copy:%.1f, infer:%.1f ms, detinfer:%.1f ms,draw:%.1f ms, save:%.1f ms total:%.1f ms \n'%(timestr2,(t0 - t00)*1000,(timeseg0-t0)*1000, (t1 - timeseg0)*1000,(t2-t1)*1000, (t3 - t2)*1000,(t4-t3)*1000, (t4-t00)*1000)
|
||||
#wrtiteLog(fp_log,outstr);
|
||||
writeELK_log(msg=outstr,fp=fp_log,line=sys._getframe().f_lineno,logger=logger,printFlag=False)
|
||||
#print(outstr)
|
||||
t00 = t4;
|
||||
|
||||
except Exception as e:
|
||||
#if outSource:###推流才有如下
|
||||
streamCheckCnt+=1;taskEnd=False
|
||||
if streamCheckCnt==1:timeBreak0=time.time();time_kafka0 = time.time()
|
||||
timeBreak1=time.time();
|
||||
if timeBreak1-timeBreak0 >5 and Pushed_Flag:###流断开5秒后,要关闭推流
|
||||
ppipe.kill();Pushed_Flag=False
|
||||
writeELK_log(msg='stream pip is killed ',fp=fp_log,line=sys._getframe().f_lineno,logger=logger)
|
||||
|
||||
###读接口,看看任务有没有结束
|
||||
query_url='%s/%s/status'%(TaskStatusQueryUrl,msgId)
|
||||
requestInfos,taskEnd=query_request_status(query_url)
|
||||
|
||||
#requestInfos,taskEnd='this line 274 test',False #############
|
||||
####taskEnd######################DEBUG
|
||||
#taskEnd=False
|
||||
|
||||
if timeBreak1-timeBreak0 >StreamRecoveringTime : ##默认30分钟内,流没有恢复的话,就断开。
|
||||
taskEnd=True
|
||||
|
||||
outstr_channel='%s ,taskEnd:%s'%(requestInfos,taskEnd)
|
||||
writeELK_log(msg=outstr_channel,fp=fp_log,line=sys._getframe().f_lineno,logger=logger)
|
||||
if outSource == 'NO':#离线没有推流
|
||||
taskEnd=True
|
||||
if taskEnd:
|
||||
if timeBreak1-timeBreak0 > 60:###超时结束
|
||||
writeTxtEndFlag(outImaDir,streamName,imageTxtFile,endFlag='超时结束')
|
||||
else:
|
||||
writeTxtEndFlag(outImaDir,streamName,imageTxtFile,endFlag='结束')
|
||||
if (outVideoDir!='NO'):
|
||||
if video_flag:vid_writer.release()
|
||||
else:
|
||||
vid_writer_OR.release();
|
||||
vid_writer_AI.release();
|
||||
outstr='Task ends:%.1f , msgid:%s,taskID:%s '%(timeBreak1-timeBreak0,taskId,msgId)
|
||||
writeELK_log(msg=outstr,fp=fp_log,line=sys._getframe().f_lineno,logger=logger)
|
||||
break
|
||||
|
||||
##执行到这里的一定是在线任务,在等待流的过程中要发送waiting
|
||||
time_kafka1 = time.time()
|
||||
if time_kafka1-time_kafka0>60:
|
||||
msg_res = copy.deepcopy(msg_dict_off);
|
||||
msg_res['request_id']= msgId; msg_res['type']=1
|
||||
msg_res = json.dumps(msg_res, ensure_ascii=False)
|
||||
outStrList= get_infos(taskId, msgId,msg_res,key_str='Waiting stream restoring heartbeat')
|
||||
send_kafka(producer,kafka_par,msg_res,outStrList,fp_log,line=sys._getframe().f_lineno,logger=logger,thread=thread );
|
||||
|
||||
outstr='Waiting stream recovering:%.1f s'%(timeBreak1-timeBreak0)
|
||||
writeELK_log(msg=outstr,fp=fp_log,line=sys._getframe().f_lineno,logger=logger)
|
||||
writeELK_log(msg=outstr_channel,fp=fp_log,line=sys._getframe().f_lineno,logger=logger)
|
||||
time_kafka0 = time_kafka1
|
||||
|
||||
#break###断流或者到终点
|
||||
|
||||
time.sleep(5)
|
||||
print('Waiting stream for ',e)
|
||||
def lauch_process(gpuid,inSource,outSource,taskId,msgId,modelJson,kafka_par,object_config=[ { 'id':"0",'config':{}}, { 'id':"1",'config':{}} ]):
|
||||
|
||||
if outSource=='NO':
|
||||
streamName='off-%s-%s'%(taskId,msgId)
|
||||
else:
|
||||
streamName='live-%s-%s'%(taskId,msgId)
|
||||
dataPar ={
|
||||
'imgData':'',
|
||||
'imgName':'testW',
|
||||
'streamName':streamName,
|
||||
'taskId':taskId,
|
||||
'msgId':msgId,
|
||||
'object_config':object_config,
|
||||
'device':str(gpuid),
|
||||
'modelJson':modelJson,
|
||||
'kafka_par':kafka_par,
|
||||
|
||||
}
|
||||
#dataPar['inSource'] = 'http://images.5gai.taauav.com/video/8bc32984dd893930dabb2856eb92b4d1.mp4';dataPar['outSource'] = None
|
||||
dataPar['inSource'] = inSource;dataPar['outSource'] = outSource
|
||||
process_uid=''.join(random.sample(string.ascii_letters + string.digits, 16));dataPar['process_uid']=process_uid
|
||||
parent_conn, child_conn = multiprocessing.Pipe();dataPar['callback']=child_conn
|
||||
gpuProcess=Process(target=onlineModelProcess,name='process:%s'%( process_uid ),args=(dataPar,))
|
||||
gpuProcess.start()
|
||||
gpuProcess.join()
|
||||
#print(dir(gpuProcess))
|
||||
#child_return = parent_conn.recv()
|
||||
#timestr2=time.strftime("%Y-%m-%d %H:%M:%S ", time.localtime())
|
||||
#print(timestr2,'-'*20,'progress:%s ,msgId:%s , taskId:%s return:'%(process_uid,msgId,taskId),child_return)
|
||||
|
||||
return gpuProcess
|
||||
|
||||
|
||||
msg_dict_offline = {
|
||||
|
||||
"biz_id":"hehuzhang",
|
||||
"mod_id":"ai",
|
||||
"request_id":'bb'+''.join(random.sample(string.ascii_letters ,30) ) ,
|
||||
"offering_id":"http://vod.play.t-aaron.com/customerTrans/c49a2c620795d124f2ae4b10197b8d0e/303b7a58-17f3ef4494e-0004-f90c-f2c-7ec68.mp4",
|
||||
"offering_type":"mp4",
|
||||
"results_base_dir": "XJRW202203171535"+str(random.randint(10,99)),
|
||||
|
||||
'outSource':'NO'
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
taskStatus={}
|
||||
taskStatus['onLine'] = Queue(100)
|
||||
taskStatus['offLine']= Queue(100)
|
||||
taskStatus['pidInfos']= {}
|
||||
|
||||
def get_msg_from_kafka(par):
|
||||
thread='master:readingKafka'
|
||||
outStrList={}
|
||||
fp_log = par['fp_log']
|
||||
logger=par['logger']
|
||||
consumer = KafkaConsumer(bootstrap_servers=par['server'],client_id='AI_server',group_id=par['group_id'],auto_offset_reset='latest')
|
||||
consumer.subscribe( par['topic'][0:2])
|
||||
outstr='reading kafka process starts'
|
||||
writeELK_log(msg=outstr,fp=fp_log,thread=thread,line=sys._getframe().f_lineno,logger=logger)
|
||||
kafka_par ={ 'server':par['server'],'topic':par['topic'][2] }
|
||||
producer = KafkaProducer(
|
||||
bootstrap_servers=par['server'],#tencent yun
|
||||
value_serializer=lambda v: v.encode('utf-8'),
|
||||
metadata_max_age_ms=120000)
|
||||
|
||||
|
||||
for ii,msg in enumerate(consumer):
|
||||
##读取消息
|
||||
try:
|
||||
taskInfos = eval(msg.value.decode('utf-8') )
|
||||
except:
|
||||
outstr='%s msg format error,value:%s,offset:%d partition:%s topic:%s'%('#'*20,msg.value,msg.offset,msg.topic,msg.topic)
|
||||
continue
|
||||
|
||||
if msg.topic == par['topic'][0]: ##
|
||||
taskInfos['inSource']= taskInfos['pull_url'];
|
||||
taskInfos['outSource']= taskInfos['push_url'] ;
|
||||
taskInfos['object_config']= taskInfos['models']
|
||||
taskStatus['onLine'].put( taskInfos )
|
||||
save_message(par['kafka'],taskInfos)
|
||||
|
||||
###发送状态信息waiting
|
||||
msg = create_status_msg(msg_dict_on,taskInfos,sts='waiting')
|
||||
outStrList=get_infos(taskInfos['results_base_dir'], taskInfos['request_id'],msg,key_str='read msgs from kafka online task and response to kafka')
|
||||
send_kafka(producer,kafka_par,msg,outStrList,fp_log,line=sys._getframe().f_lineno,logger=logger,thread=thread);
|
||||
|
||||
else:
|
||||
try:
|
||||
taskInfos['inSource']= taskInfos['original_url'];
|
||||
taskInfos['outSource']= 'NO'
|
||||
taskInfos['object_config']= taskInfos['models']
|
||||
taskStatus['offLine'].put( taskInfos )
|
||||
save_message(par['kafka'],taskInfos)
|
||||
|
||||
###发送状态信息waiting
|
||||
msg = create_status_msg(msg_dict_off,taskInfos,sts='waiting')
|
||||
outStrList=get_infos(taskInfos['results_base_dir'], taskInfos['request_id'],msg,key_str='read msgs from kafka offline task and response to kafka')
|
||||
send_kafka(producer,kafka_par,msg,outStrList,fp_log ,line=sys._getframe().f_lineno,logger=logger,thread=thread );
|
||||
except Exception as e:
|
||||
print('######msg Error######',msg,e)
|
||||
|
||||
|
||||
def detector(par):
|
||||
|
||||
####初始化信息列表
|
||||
kafka_par ={ 'server':par['server'],'topic':par['topic'][2] }
|
||||
producer = KafkaProducer(
|
||||
bootstrap_servers=par['server'],#tencent yun
|
||||
value_serializer=lambda v: v.encode('utf-8'),
|
||||
metadata_max_age_ms=120000)
|
||||
time_interval=par['logPrintInterval']
|
||||
logname='detector.log';thread='master:detector'
|
||||
fp_log=create_logFile(logdir=par['logDir'],name=logname)
|
||||
##准备日志函数所需参数
|
||||
logger=par['logDir'].replace('/','.')+'.'+logname
|
||||
#wrtiteLog(fp_log,'########### detector process starts ######\n');
|
||||
outstr='detector process starts';sys._getframe().f_lineno
|
||||
writeELK_log(msg=outstr,fp=fp_log,thread=thread,line=sys._getframe().f_lineno,logger=logger)
|
||||
|
||||
###开启kafka consumer 进程##
|
||||
parIn=copy.deepcopy(par);parIn['fp_log']=fp_log ;parIn['logger']=logger
|
||||
HeartProcess=Process(target=get_msg_from_kafka,name='process-consumer-kafka',args=(parIn,))
|
||||
HeartProcess.start()
|
||||
|
||||
|
||||
timeSleep=1
|
||||
|
||||
time0=time.time()
|
||||
time0_kafQuery=time.time()
|
||||
time0_taskQuery=time.time()
|
||||
time0_sleep=time.time()
|
||||
outStrList={}
|
||||
while True:###每隔timeSleep秒,轮询一次
|
||||
|
||||
time0_taskQuery,printFlag = check_time_interval(time0_taskQuery,time_interval)
|
||||
outstr_task= ' task queue onLine cnt:%d offLine:%d'%(taskStatus['onLine'].qsize(), taskStatus['offLine'].qsize())
|
||||
if (taskStatus['onLine'].qsize()>0) or (taskStatus['offLine'].qsize()>0):
|
||||
#outstr_task=wrtiteLog(fp_log,outstr_task);print( outstr_task);
|
||||
writeELK_log(msg=outstr_task,fp=fp_log,thread=thread,line=sys._getframe().f_lineno,logger=logger)
|
||||
##2-更新显卡信息
|
||||
gpuStatus = getGPUInfos()
|
||||
|
||||
##3-优先考虑在线任务
|
||||
if not taskStatus['onLine'].empty():
|
||||
###3.1-先判断有没有空闲显卡:
|
||||
cuda = get_available_gpu(gpuStatus)
|
||||
###获取在线任务信息,并执行,lauch process
|
||||
taskInfos = taskStatus['onLine'].get()
|
||||
outstr='start to process onLine taskId:%s msgId:%s'%( taskInfos['results_base_dir'],taskInfos['request_id'] )
|
||||
#outstr=wrtiteLog(fp_log,outstr);print( outstr);
|
||||
writeELK_log(msg=outstr,fp=fp_log,thread=thread,line=sys._getframe().f_lineno,logger=logger)
|
||||
if cuda: ###3.1.1 -有空余显卡
|
||||
#lauch process
|
||||
msg= copy.deepcopy(msg_dict_on);
|
||||
gpuProcess=lauch_process(cuda,taskInfos['inSource'],taskInfos['outSource'],taskInfos['results_base_dir'],taskInfos['request_id'],par['modelJson'],kafka_par,taskInfos['object_config'])
|
||||
taskStatus['pidInfos'][gpuProcess.pid] = {'gpuProcess':gpuProcess,'type':'onLine','taskInfos':taskInfos}
|
||||
|
||||
else:###3.1.2-没有显卡
|
||||
##判断有没有显卡上面都是离线进程的
|
||||
cuda_pid = get_potential_gpu(gpuStatus,taskStatus['pidInfos'])
|
||||
|
||||
if cuda_pid:#3.1.2.1 - ##如果有可以杀死的进程
|
||||
cuda = cuda_pid['cuda']
|
||||
pids = cuda_pid['pids']
|
||||
##kill 离线进程,并更新离线任务表
|
||||
cnt_off_0 = taskStatus['offLine'].qsize()
|
||||
for pid in pids:
|
||||
##kill 离线进程
|
||||
taskStatus['pidInfos'][pid]['gpuProcess'].kill()
|
||||
##更新离线任务表
|
||||
taskStatus['offLine'].put( taskStatus['pidInfos'][pid]['taskInfos'] )
|
||||
taskInfos_off=taskStatus['pidInfos'][pid]['taskInfos']
|
||||
|
||||
##发送离线数据,说明状态变成waiting
|
||||
msg= msg_dict_off;
|
||||
msg=update_json(taskInfos_off,msg,offkeys=["request_id","biz_id" ,"mod_id"] )
|
||||
msg['results'][0]['original_url']=taskInfos_off['inSource']
|
||||
msg['results'][0]['sign_url']=get_boradcast_address(taskInfos_off['outSource'])
|
||||
msg['status']='waiting'
|
||||
msg = json.dumps(msg, ensure_ascii=False)
|
||||
|
||||
|
||||
outStrList=get_infos(taskInfos_off['results_base_dir'], taskInfos_off['request_id'],msg,key_str='start online task after kill offline tasks')
|
||||
|
||||
send_kafka(producer,kafka_par,msg,outStrList,fp_log ,line=sys._getframe().f_lineno,logger=logger,thread=thread );
|
||||
|
||||
|
||||
cnt_off_1 = taskStatus['offLine'].qsize()
|
||||
outstr='before killing process, offtask cnt:%d ,after killing, offtask cnt:%d '%(cnt_off_0,cnt_off_1)
|
||||
#outstr=wrtiteLog(fp_log,outstr);print( outstr);
|
||||
writeELK_log(msg=outstr,fp=fp_log,thread=thread,line=sys._getframe().f_lineno,logger=logger)
|
||||
gpuProcess=lauch_process(cuda,taskInfos['inSource'],taskInfos['outSource'],taskInfos['results_base_dir'],taskInfos['request_id'],par['modelJson'],kafka_par,taskInfos['object_config'])
|
||||
|
||||
###更新pidinfos,update pidInfos
|
||||
taskStatus['pidInfos'][gpuProcess.pid] = {'gpuProcess':gpuProcess,'type':'onLine','taskInfos':taskInfos}
|
||||
else:
|
||||
outstr='No available GPUs for onLine task'
|
||||
#outstr=wrtiteLog(fp_log,outstr);print(outstr);
|
||||
writeELK_log(msg=outstr,fp=fp_log,level='ERROR',thread=thread,line=sys._getframe().f_lineno,logger=logger)
|
||||
|
||||
##4-更新显卡信息
|
||||
gpuStatus = getGPUInfos()
|
||||
##5-考虑离线任务
|
||||
if not taskStatus['offLine'].empty():
|
||||
cudaArrange= arrange_offlineProcess(gpuStatus,taskStatus['pidInfos'],modelMemory=1500)
|
||||
outstr='IN OFF LINE TASKS available cudas:%s'%(cudaArrange)
|
||||
#outstr=wrtiteLog(fp_log,outstr);print( outstr);
|
||||
writeELK_log(msg=outstr,fp=fp_log,thread=thread,line=sys._getframe().f_lineno,logger=logger)
|
||||
|
||||
for cuda in cudaArrange:
|
||||
if not taskStatus['offLine'].empty():
|
||||
taskInfos = taskStatus['offLine'].get()
|
||||
outstr='start to process offLine taskId:%s msgId:%s'%( taskInfos['results_base_dir'],taskInfos['request_id'] )
|
||||
|
||||
#outstr=wrtiteLog(fp_log,outstr);print( outstr);
|
||||
writeELK_log(msg=outstr,fp=fp_log,thread=thread,line=sys._getframe().f_lineno,logger=logger)
|
||||
gpuProcess=lauch_process(cuda,taskInfos['inSource'],taskInfos['outSource'],taskInfos['results_base_dir'],taskInfos['request_id'],par['modelJson'],kafka_par,taskInfos['object_config'])
|
||||
taskStatus['pidInfos'][gpuProcess.pid] = {'gpuProcess':gpuProcess,'type':'offLine','taskInfos':taskInfos}
|
||||
|
||||
|
||||
|
||||
|
||||
if get_whether_gpuProcess():
|
||||
time0_sleep,printFlag = check_time_interval(time0_sleep,time_interval)
|
||||
if printFlag:
|
||||
outstr= '*'*20 +'sleep '+'*'*20;
|
||||
#outstr=wrtiteLog(fp_log,outstr);print( outstr);
|
||||
writeELK_log(msg=outstr,fp=fp_log,thread=thread,line=sys._getframe().f_lineno,logger=logger)
|
||||
|
||||
time.sleep(timeSleep)
|
||||
|
||||
####检查gpu子进程是否结束,如果结束要join(),否则会产生僵尸进程###
|
||||
#taskStatus['pidInfos'][gpuProcess.pid] = {'gpuProcess':gpuProcess,'type':'onLine','taskInfos':taskInfos}
|
||||
for key in list(taskStatus['pidInfos'].keys()):
|
||||
if not taskStatus['pidInfos'][key]['gpuProcess'].is_alive():
|
||||
taskStatus['pidInfos'][key]['gpuProcess'].join()
|
||||
taskStatus['pidInfos'].pop(key)
|
||||
|
||||
print('########Program End#####')
|
||||
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
par={};
|
||||
###topic0--在线,topic1--离线
|
||||
|
||||
#par['server']='212.129.223.66:9092';par['topic']=('thsw','thsw2','testReturn');par['group_id']='test';
|
||||
#101.132.127.1:19092
|
||||
|
||||
'''
|
||||
par['server']='101.132.127.1:19092 ';par['topic']=('alg-online-tasks','alg-offline-tasks','alg-task-results');par['group_id']='test';
|
||||
|
||||
par['kafka']='mintors/kafka'
|
||||
par['modelJson']='conf/model.json'
|
||||
'''
|
||||
masterFile="conf/master.json"
|
||||
assert os.path.exists(masterFile)
|
||||
with open(masterFile,'r') as fp:
|
||||
data=json.load(fp)
|
||||
par=data['par']
|
||||
print(par)
|
||||
detector(par)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,77 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# This file is auto-generated, don't edit it. Thanks.
|
||||
import sys
|
||||
|
||||
from typing import List
|
||||
|
||||
from alibabacloud_vod20170321.client import Client as vod20170321Client
|
||||
from alibabacloud_tea_openapi import models as open_api_models
|
||||
from alibabacloud_vod20170321 import models as vod_20170321_models
|
||||
from alibabacloud_tea_util import models as util_models
|
||||
from alibabacloud_tea_util.client import Client as UtilClient
|
||||
|
||||
|
||||
class Sample:
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
@staticmethod
|
||||
def create_client(
|
||||
access_key_id: str,
|
||||
access_key_secret: str,
|
||||
) -> vod20170321Client:
|
||||
"""
|
||||
使用AK&SK初始化账号Client
|
||||
@param access_key_id:
|
||||
@param access_key_secret:
|
||||
@return: Client
|
||||
@throws Exception
|
||||
"""
|
||||
config = open_api_models.Config(
|
||||
# 您的 AccessKey ID,
|
||||
access_key_id=access_key_id,
|
||||
# 您的 AccessKey Secret,
|
||||
access_key_secret=access_key_secret
|
||||
)
|
||||
# 访问的域名
|
||||
config.endpoint = f'vod.cn-shanghai.aliyuncs.com'
|
||||
return vod20170321Client(config)
|
||||
|
||||
@staticmethod
|
||||
def main(
|
||||
args: List[str],
|
||||
) -> None:
|
||||
client = Sample.create_client('LTAI5tSJ62TLMUb4SZuf285A', 'MWYynm30filZ7x0HqSHlU3pdLVNeI7')
|
||||
get_upload_details_request = vod_20170321_models.GetUploadDetailsRequest(
|
||||
media_ids='6d040a5749f74b80afac476563250d6d',
|
||||
media_type='video'
|
||||
)
|
||||
runtime = util_models.RuntimeOptions()
|
||||
try:
|
||||
# 复制代码运行请自行打印 API 的返回值
|
||||
ret=client.get_upload_details_with_options(get_upload_details_request, runtime)
|
||||
print(ret)
|
||||
except Exception as error:
|
||||
# 如有需要,请打印 error
|
||||
UtilClient.assert_as_string(error.message)
|
||||
|
||||
@staticmethod
|
||||
async def main_async(
|
||||
args: List[str],
|
||||
) -> None:
|
||||
client = Sample.create_client('accessKeyId', 'accessKeySecret')
|
||||
get_upload_details_request = vod_20170321_models.GetUploadDetailsRequest(
|
||||
media_ids='6d040a5749f74b80afac476563250d6d',
|
||||
media_type='video'
|
||||
)
|
||||
runtime = util_models.RuntimeOptions()
|
||||
try:
|
||||
# 复制代码运行请自行打印 API 的返回值
|
||||
await client.get_upload_details_with_options_async(get_upload_details_request, runtime)
|
||||
except Exception as error:
|
||||
# 如有需要,请打印 error
|
||||
UtilClient.assert_as_string(error.message)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
Sample.main(sys.argv[1:])
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -0,0 +1,119 @@
|
|||
|
||||
import numpy as np
|
||||
|
||||
import base64
|
||||
import io,os
|
||||
import requests
|
||||
import time,json
|
||||
import string,random
|
||||
import glob,string,sys
|
||||
|
||||
import oss2,copy
|
||||
from kafka import KafkaProducer, KafkaConsumer
|
||||
|
||||
|
||||
|
||||
from kafka.errors import kafka_errors
|
||||
|
||||
msg_dict_off={
|
||||
"msg_id":"bblvgyntTsZCamqjuLArkiSYIbKXEeWx",#消息ID标识
|
||||
"biz_id":"hehuzhang",#业务标识
|
||||
"mod_id":"ai",#模型标识
|
||||
"status":"running",#任务状态
|
||||
"type":str(1),#数据类型:1图片 2视频
|
||||
"error":str(9999),#错误信息
|
||||
"results":[#问题结果
|
||||
{
|
||||
"original_url":"",#原图地址
|
||||
"sign_url":"",#AI标记地址
|
||||
"category_id":"",#分类标识
|
||||
"description":"",#问题描述
|
||||
"time":"",#时间戳
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
def test5(par):
|
||||
|
||||
indir,outdir,logdir,jsonDir = par['indir'],par['outdir'],par['logdir'],par['jsonDir']
|
||||
videoBakDir,ossPar,vodPar,kafkaPar = par['videoBakDir'], par['ossPar'],par['vodPar'],par['kafkaPar']
|
||||
|
||||
'''producer = KafkaProducer(
|
||||
bootstrap_servers=kafkaPar['boostServer'],#tencent yun
|
||||
value_serializer=lambda v: v.encode('utf-8'),
|
||||
#request_timeout_ms=3,
|
||||
#connections_max_idle_ms=60000
|
||||
|
||||
)'''
|
||||
|
||||
producer = KafkaProducer(
|
||||
bootstrap_servers=['101.132.127.1:19092'],
|
||||
key_serializer=lambda k: json.dumps(k).encode(),
|
||||
value_serializer=lambda v: json.dumps(v).encode())
|
||||
|
||||
|
||||
|
||||
#while True:
|
||||
for i in range(5):
|
||||
for j in range(10):
|
||||
|
||||
|
||||
|
||||
msg = copy.deepcopy(msg_dict_off)
|
||||
biz_id = 'i-%d-j-%d'%(i,j)
|
||||
print(biz_id,msg['biz_id'])
|
||||
msg['biz_id'] = biz_id
|
||||
msg = json.dumps(msg, ensure_ascii=False)
|
||||
|
||||
'''future = producer.send(
|
||||
kafkaPar['topic'],
|
||||
msg
|
||||
)'''
|
||||
|
||||
|
||||
future = producer.send(
|
||||
'alg-task-results',
|
||||
key='count_num', # 同一个key值,会被送至同一个分区
|
||||
value=biz_id) # 向分区1发送消息
|
||||
|
||||
|
||||
try:
|
||||
record_metadata = future.get(timeout=30)
|
||||
print('-'*10,biz_id,' send')
|
||||
except Exception as e:
|
||||
print('#'*10,biz_id,' error:',str(e))
|
||||
|
||||
|
||||
for ii in range(30):
|
||||
time.sleep(10)
|
||||
print('sleep %d s'%(ii*10))
|
||||
|
||||
|
||||
for j in range(10,20):
|
||||
msg = copy.deepcopy(msg_dict_off)
|
||||
biz_id = 'i-%d-j%d'%(i,j)
|
||||
msg['biz_id'] = biz_id
|
||||
msg = json.dumps(msg, ensure_ascii=False)
|
||||
|
||||
|
||||
future = producer.send(
|
||||
'alg-task-results',
|
||||
key='count_num', # 同一个key值,会被送至同一个分区
|
||||
value=biz_id) # 向分区1发送消息
|
||||
try:
|
||||
record_metadata = future.get(timeout=30)
|
||||
print('-'*10,biz_id,' send')
|
||||
except Exception as e:
|
||||
print('#'*10,biz_id,' error:',str(e))
|
||||
|
||||
|
||||
|
||||
|
||||
if __name__=='__main__':
|
||||
|
||||
masterFile="conf/send_oss_debug.json"
|
||||
assert os.path.exists(masterFile)
|
||||
with open(masterFile,'r') as fp:
|
||||
par=json.load(fp)
|
||||
|
||||
test5(par)
|
||||
|
|
@ -0,0 +1,117 @@
|
|||
from kafka import KafkaProducer, KafkaConsumer
|
||||
from kafka.errors import kafka_errors
|
||||
import traceback
|
||||
import json
|
||||
import time
|
||||
|
||||
def producer_demo():
|
||||
# 假设生产的消息为键值对(不是一定要键值对),且序列化方式为json
|
||||
producer = KafkaProducer(
|
||||
bootstrap_servers=['101.132.127.1:19092'],
|
||||
key_serializer=lambda k: json.dumps(k).encode(),
|
||||
value_serializer=lambda v: json.dumps(v).encode(),
|
||||
)
|
||||
|
||||
# 发送三条消息
|
||||
for i in range(0, 3):
|
||||
future = producer.send(
|
||||
'alg-task-results',
|
||||
key='count_num', # 同一个key值,会被送至同一个分区
|
||||
value=str(i)) # 向分区1发送消息
|
||||
print("send {}".format(str(i)))
|
||||
try:
|
||||
future.get(timeout=10) # 监控是否发送成功
|
||||
except Exception as e: # 发送失败抛出kafka_errors
|
||||
print(e)
|
||||
|
||||
producer = KafkaProducer(
|
||||
bootstrap_servers=['101.132.127.1:19092'],
|
||||
key_serializer=lambda k: json.dumps(k).encode(),
|
||||
value_serializer=lambda v: json.dumps(v).encode(),
|
||||
)
|
||||
future = producer.send(
|
||||
'alg-task-results',
|
||||
key='count_num', # 同一个key值,会被送至同一个分区
|
||||
value=str(i)) # 向分区1发送消息
|
||||
|
||||
try:
|
||||
future.get() # 监控是否发送成功
|
||||
print("re send {}".format(str(i)))
|
||||
except Exception as e:
|
||||
print('resend error:',e)
|
||||
|
||||
|
||||
for ii in range(30):
|
||||
time.sleep(10)
|
||||
print('sleep %d s'%(ii*10))
|
||||
|
||||
for i in range(0, 3):
|
||||
future = producer.send(
|
||||
'alg-task-results',
|
||||
key='count_num', # 同一个key值,会被送至同一个分区
|
||||
value=str(i)) # 向分区1发送消息
|
||||
print("send {}".format(str(i)))
|
||||
try:
|
||||
future.get() # 监控是否发送成功
|
||||
except Exception as e: # 发送失败抛出kafka_errors
|
||||
|
||||
print(e)
|
||||
producer = KafkaProducer(
|
||||
bootstrap_servers=['101.132.127.1:19092'],
|
||||
key_serializer=lambda k: json.dumps(k).encode(),
|
||||
value_serializer=lambda v: json.dumps(v).encode(),
|
||||
)
|
||||
future = producer.send(
|
||||
'alg-task-results',
|
||||
key='count_num', # 同一个key值,会被送至同一个分区
|
||||
value=str(i)) # 向分区1发送消息
|
||||
|
||||
try:
|
||||
future.get() # 监控是否发送成功
|
||||
print("re send {}".format(str(i)))
|
||||
except Exception as e:
|
||||
print('resend error:',e)
|
||||
|
||||
|
||||
|
||||
def prod():
|
||||
producer = KafkaProducer(
|
||||
bootstrap_servers=['101.132.127.1:19092'],
|
||||
key_serializer=lambda k: json.dumps(k).encode(),
|
||||
metadata_max_age_ms=120000,
|
||||
value_serializer=lambda v: json.dumps(v).encode()
|
||||
)
|
||||
|
||||
# 发送三条消息
|
||||
for i in range(0, 3):
|
||||
future = producer.send(
|
||||
'alg-task-results',
|
||||
key='count_num', # 同一个key值,会被送至同一个分区
|
||||
value=str(i)) # 向分区1发送消息
|
||||
print("send {}".format(str(i)))
|
||||
try:
|
||||
future.get() # 监控是否发送成功
|
||||
except kafka_errors: # 发送失败抛出kafka_errors
|
||||
traceback.format_exc()
|
||||
|
||||
for ii in range(30):
|
||||
time.sleep(10)
|
||||
print('sleep %d s'%(ii*10))
|
||||
|
||||
for i in range(0, 3):
|
||||
future = producer.send(
|
||||
'alg-task-results',
|
||||
key='count_num', # 同一个key值,会被送至同一个分区
|
||||
value=str(i)) # 向分区1发送消息
|
||||
print("send {}".format(str(i)))
|
||||
try:
|
||||
future.get() # 监控是否发送成功
|
||||
except Exception as e:
|
||||
print('resend error:',e)
|
||||
if __name__=='__main__':
|
||||
print('########demo1 2nd############')
|
||||
prod()
|
||||
print('########demo2 1st############')
|
||||
producer_demo()
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,77 @@
|
|||
from kafka import KafkaProducer, KafkaConsumer
|
||||
from kafka.errors import kafka_errors
|
||||
import traceback
|
||||
import json
|
||||
import time
|
||||
|
||||
def producer_demo():
|
||||
# 假设生产的消息为键值对(不是一定要键值对),且序列化方式为json
|
||||
producer = KafkaProducer(
|
||||
bootstrap_servers=['101.132.127.1:19092'],
|
||||
key_serializer=lambda k: json.dumps(k).encode(),
|
||||
value_serializer=lambda v: json.dumps(v).encode())
|
||||
|
||||
# 发送三条消息
|
||||
for i in range(0, 3):
|
||||
future = producer.send(
|
||||
'alg-task-results',
|
||||
key='count_num', # 同一个key值,会被送至同一个分区
|
||||
value=str(i)) # 向分区1发送消息
|
||||
print("send {}".format(str(i)))
|
||||
try:
|
||||
future.get(timeout=10) # 监控是否发送成功
|
||||
except kafka_errors: # 发送失败抛出kafka_errors
|
||||
traceback.format_exc()
|
||||
|
||||
for ii in range(30):
|
||||
time.sleep(10)
|
||||
print('sleep %d s'%(ii*10))
|
||||
|
||||
for i in range(10, 20):
|
||||
future = producer.send(
|
||||
'alg-task-results',
|
||||
key='count_num', # 同一个key值,会被送至同一个分区
|
||||
value=str(i)) # 向分区1发送消息
|
||||
print("send {}".format(str(i)))
|
||||
try:
|
||||
future.get(timeout=10) # 监控是否发送成功
|
||||
except : # 发送失败抛出kafka_errors
|
||||
traceback.format_exc()
|
||||
def prod():
|
||||
producer = KafkaProducer(
|
||||
bootstrap_servers=['101.132.127.1:19092'],
|
||||
key_serializer=lambda k: json.dumps(k).encode(),
|
||||
value_serializer=lambda v: json.dumps(v).encode())
|
||||
|
||||
# 发送三条消息
|
||||
for i in range(0, 3):
|
||||
future = producer.send(
|
||||
'alg-task-results',
|
||||
key='count_num', # 同一个key值,会被送至同一个分区
|
||||
value=str(i)) # 向分区1发送消息
|
||||
print("send {}".format(str(i)))
|
||||
try:
|
||||
future.get(timeout=10) # 监控是否发送成功
|
||||
except kafka_errors: # 发送失败抛出kafka_errors
|
||||
traceback.format_exc()
|
||||
|
||||
for ii in range(30):
|
||||
time.sleep(10)
|
||||
print('sleep %d s'%(ii*10))
|
||||
|
||||
for i in range(0, 3):
|
||||
future = producer.send(
|
||||
'alg-task-results',
|
||||
key='count_num', # 同一个key值,会被送至同一个分区
|
||||
value=str(i)) # 向分区1发送消息
|
||||
print("send {}".format(str(i)))
|
||||
try:
|
||||
future.get(timeout=10) # 监控是否发送成功
|
||||
except kafka_errors: # 发送失败抛出kafka_errors
|
||||
traceback.format_exc()
|
||||
if __name__=='__main__':
|
||||
print('########demo2 1st############')
|
||||
prod()
|
||||
print('########demo1 2nd############')
|
||||
prod()
|
||||
|
||||
|
|
@ -0,0 +1,192 @@
|
|||
from PIL import Image
|
||||
import numpy as np
|
||||
import cv2
|
||||
import base64
|
||||
import io,os
|
||||
import requests
|
||||
import time
|
||||
|
||||
def test():
|
||||
image_path='test/P0017.png'
|
||||
image_array=cv2.imread(image_path)
|
||||
print(image_array.shape)
|
||||
|
||||
image_encode=base64.b64encode(image_array).decode('utf-8')
|
||||
image_bytes=bytes(image_encode,encoding='utf-8')
|
||||
image_decode=np.frombuffer(base64.decodebytes(image_bytes),dtype=np.uint8)
|
||||
print(image_decode.shape)
|
||||
|
||||
request_url='http://192.168.109.49:5000/'
|
||||
|
||||
headers={'content-type':'application/json'}
|
||||
data={'image':image_encode}
|
||||
|
||||
#response=requests.post(request_url,data=data,headers=headers)
|
||||
response=requests.post(request_url,"POST",files=data)
|
||||
print(response)
|
||||
#image=open(image_path,'rb').read()
|
||||
#image=Image.open(io.BytesIO(image))
|
||||
#image=image.resize((224,224))
|
||||
#image=np.asarray(image
|
||||
def test2():
|
||||
image_path='test/P0017.png'
|
||||
image_ori=cv2.imread(image_path)
|
||||
api = 'http://192.168.16.45:8000/detector'
|
||||
img = cv2.imencode('.jpg', image_ori)[-1]
|
||||
|
||||
|
||||
#image_encode=base64.b64encode(image_ori).decode('utf-8')
|
||||
#img=bytes(image_encode,encoding='utf-8')
|
||||
#h,w,c=image_ori.shape
|
||||
|
||||
files = {'file': img}
|
||||
files = {'file': img,'name':'P0017'
|
||||
}
|
||||
res = requests.request("POST", api, files=files).json()
|
||||
|
||||
if res['msg'] == 'success':
|
||||
bboxes = res['data']['bboxes']
|
||||
print(bboxes)
|
||||
#bboxes = np.asarray(bboxes, dtype=np.int32)
|
||||
def get_file_content(filePath):
|
||||
with open(filePath, 'rb') as fp:
|
||||
return fp.read()
|
||||
|
||||
def test3():
|
||||
image_path='test/P0017.png'
|
||||
image_ori=cv2.imread(image_path)
|
||||
api = 'http://192.168.16.45:8000/detector'
|
||||
#img = cv2.imencode('.jpg', img_ori)[-1]
|
||||
|
||||
input_ ={
|
||||
'img_data':'',
|
||||
'img_width':512,
|
||||
'img_height':512,
|
||||
'img_chs':3
|
||||
}
|
||||
|
||||
with open(image_path,'rb') as f:
|
||||
input_['img_data']=base64.b64encode(f.read()).decode('utf-8')
|
||||
|
||||
image_encode=base64.b64encode(image_ori).decode('utf-8')
|
||||
image_bytes=bytes(image_encode,encoding='utf-8')
|
||||
#input_['img_data']=image_bytes
|
||||
|
||||
response=requests.post(api,json=input_).json()
|
||||
print(response['msg'],response['data']['bboxes'])
|
||||
|
||||
###---客户端:读取图片:image_ori=cv2.imread(image_path)--->编码base64.b64encode(f.read()).decode('utf-8') ,(C,H,W)
|
||||
###---服务器端:字节化image_bytes=bytes(img_data,encoding='utf-8')-->解码img_data=np.frombuffer(base64.decodebytes(image_bytes),dtype=np.uint8)-->reshape:mg_data=img_data.reshape(h,w,3)
|
||||
def test4():
|
||||
image_path='test/P0017.png'
|
||||
image_ori=cv2.imread(image_path)
|
||||
api = 'http://192.168.16.45:8000/detector'
|
||||
#img = cv2.imencode('.jpg', img_ori)[-1]
|
||||
|
||||
h,w,c = image_ori.shape
|
||||
input_ ={
|
||||
'img_data':'',
|
||||
'img_width':h,
|
||||
'img_height':w,
|
||||
'img_chs':c
|
||||
}
|
||||
print('input:',input_)
|
||||
|
||||
##decode('utf-8'),有没有好像都行。
|
||||
input_['img_data']=base64.b64encode(image_ori).decode('utf-8')
|
||||
response=requests.post(api,json=input_).json()
|
||||
print(response['msg'],response['data']['bboxes'])
|
||||
|
||||
def decode_encode():
|
||||
##对文件b64编码,b64解码存储
|
||||
image_path='test/P0017.png'
|
||||
with open(image_path,'rb') as fp:
|
||||
encode_img = base64.b64encode(fp.read())
|
||||
with open('t2.png','wb') as f2:
|
||||
f2.write(base64.b64decode(encode_img))
|
||||
|
||||
##输入时数组-->opencv编码jpg字节流-->存储图片文件
|
||||
image_path='test/P0017.png'
|
||||
image_ori=cv2.imread(image_path)
|
||||
image_bytes = cv2.imencode(".png",image_ori)[1].tobytes()
|
||||
with open('bytes2image.png') as fp:
|
||||
fp.write(image_bytes)
|
||||
|
||||
###字节流到数组用cv2.imdecode(np.frombuffer(image_bytes,np.uint8),1)
|
||||
with open(image_path,'rb') as fp:
|
||||
image_bytes2 = fp.read()
|
||||
image_array = cv2.imdecode(np.frombuffer(image_bytes2,np.uint8),1)
|
||||
|
||||
|
||||
##输入时数组-->opencv编码jpg字节流-->存储图片文件
|
||||
image_path='test/P0017.png'
|
||||
image_ori=cv2.imread(image_path)
|
||||
image_bytes = cv2.imencode(".png",image_ori)[1].tobytes()
|
||||
with open('bytes2image.png') as fp:
|
||||
fp.write(image_bytes)
|
||||
|
||||
##image_array--
|
||||
image_path='test/P0017.png'
|
||||
image_ori=cv2.imread(image_path)
|
||||
image_encode=base64.b64encode(image_ori).decode('utf-8')
|
||||
image_bytes=bytes(image_encode,encoding='utf-8')
|
||||
img_data=np.frombuffer(base64.decodebytes(image_bytes),dtype=np.uint8)
|
||||
|
||||
|
||||
def test5():
|
||||
|
||||
import json
|
||||
##输入时数组-->opencv编码jpg字节流-->存储图片文件
|
||||
image_path='imgs/DJI_0445.JPG'
|
||||
|
||||
image_dir = '/home/thsw2/WJ/data/THexit/val/images/'
|
||||
filelist = os.listdir(image_dir)
|
||||
time0 = time.time()
|
||||
for filename in filelist:
|
||||
image_path = os.path.join(image_dir,filename)
|
||||
image_ori=cv2.imread(image_path)
|
||||
|
||||
image_ori = cv2.resize(image_ori, (0, 0), fx=0.25, fy=0.25, interpolation=cv2.INTER_NEAREST)
|
||||
image_pngcode = cv2.imencode(".jpg",image_ori)[-1]
|
||||
|
||||
|
||||
|
||||
api = 'http://192.168.10.10:8000/detector'
|
||||
#api = 'http://47.98.157.120:9040/api/taskFile/submitUAVKHQuestion'
|
||||
#api = 'http://192.168.0.100:9040'
|
||||
|
||||
|
||||
|
||||
h,w,c = image_ori.shape
|
||||
input_ ={
|
||||
'imgData':'',
|
||||
#'img_width':h,
|
||||
#'img_height':w,
|
||||
#'img_chs':c,
|
||||
'imgName':filename
|
||||
}
|
||||
#print('input:',input_ )
|
||||
t1 = time.time()
|
||||
image_code = str(base64.b64encode(image_pngcode))[2:-1]
|
||||
#print( image_code)
|
||||
input_['imgData']=image_code
|
||||
t2 = time.time()
|
||||
response=requests.post(api,json=input_).json()
|
||||
t3 = time.time()
|
||||
print('bs encodetime:%.5f request time:%.5f \n'%(t2-t1,t3-t2))
|
||||
t1_bytes = bytes(image_code,encoding='utf-8')
|
||||
t2_bs64decode = base64.b64decode(t1_bytes)
|
||||
|
||||
img_data = cv2.imdecode(np.frombuffer(base64.b64decode( bytes(image_code,encoding='utf-8')),dtype=np.uint8),1)
|
||||
|
||||
|
||||
#print(response['code'],response['data']['bboxes'])
|
||||
print('Return:',response['data']['bboxes'],' img data shape:',img_data.shape)
|
||||
|
||||
time2 = time.time()
|
||||
print('average time:',(time2-time0)/len(filelist))
|
||||
|
||||
|
||||
|
||||
if __name__=='__main__':
|
||||
test5()
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
from kafka import KafkaProducer, KafkaConsumer
|
||||
from kafka.errors import kafka_errors
|
||||
import traceback
|
||||
import json,time,random,string
|
||||
import utilsK
|
||||
from utilsK.modelEval import onlineModelProcess
|
||||
import multiprocessing
|
||||
from multiprocessing import Process,Queue
|
||||
|
||||
def consumer_demo(par):
|
||||
|
||||
consumer = KafkaConsumer(
|
||||
par['topic'],
|
||||
bootstrap_servers=par['server'],
|
||||
group_id=par['group_id'],
|
||||
auto_offset_reset='latest',
|
||||
enable_auto_commit=False
|
||||
)
|
||||
itest = 0
|
||||
'''
|
||||
for message in consumer:
|
||||
itest+=1
|
||||
if itest>1:break;
|
||||
print("receive value: {}, partition:{} offset:{}".format(
|
||||
json.loads(message.value.decode()), message.partition,message.offset
|
||||
)
|
||||
)
|
||||
consumer.commit()
|
||||
'''
|
||||
|
||||
dataPar ={
|
||||
'imgData':'',
|
||||
'imgName':'testW',
|
||||
'streamName':'THSA_HD5M'
|
||||
}
|
||||
dataPar['inSource'] = 'http://images.5gai.taauav.com/video/8bc32984dd893930dabb2856eb92b4d1.mp4';dataPar['outSource'] = None
|
||||
|
||||
|
||||
process_uid=''.join(random.sample(string.ascii_letters + string.digits, 16))
|
||||
parent_conn, child_conn = multiprocessing.Pipe();
|
||||
dataPar['callback']=child_conn
|
||||
|
||||
gpuProcess=Process(target=onlineModelProcess,name='process:%s'%( process_uid ),args=(dataPar,))
|
||||
gpuProcess.start()
|
||||
child_return = parent_conn.recv()
|
||||
returnData={'bboxes': 9999};
|
||||
returnData['gpu']=str(child_return)
|
||||
returnData['pid']=gpuProcess.pid
|
||||
returnData['pidName']=gpuProcess.name
|
||||
print( '#####consumer main:',returnData )
|
||||
|
||||
|
||||
|
||||
if __name__=='__main__':
|
||||
par={};
|
||||
par['server']='212.129.223.66:9092';par['topic']='thsw';par['group_id']='test';
|
||||
|
||||
consumer_demo(par)
|
||||
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
import traceback
|
||||
from kafka import KafkaProducer, KafkaConsumer,TopicPartition
|
||||
from kafka.errors import kafka_errors
|
||||
import json
|
||||
def get_left_cnt(consumer,topic):
|
||||
partitions = [TopicPartition(topic, p) for p in consumer.partitions_for_topic(topic)]
|
||||
|
||||
# total
|
||||
toff = consumer.end_offsets(partitions)
|
||||
toff = [(key.partition, toff[key]) for key in toff.keys()]
|
||||
toff.sort()
|
||||
|
||||
# current
|
||||
coff = [(x.partition, consumer.committed(x)) for x in partitions]
|
||||
coff.sort()
|
||||
|
||||
# cal sum and left
|
||||
toff_sum = sum([x[1] for x in toff])
|
||||
cur_sum = sum([x[1] for x in coff if x[1] is not None])
|
||||
left_sum = toff_sum - cur_sum
|
||||
|
||||
return left_sum
|
||||
def getAllRecords(consumer,topics):
|
||||
leftCnt = 0
|
||||
for topic in topics[0:2]:
|
||||
leftCnt+=get_left_cnt(consumer,topic)
|
||||
out = []
|
||||
if leftCnt == 0:
|
||||
return []
|
||||
for ii,msg in enumerate(consumer):
|
||||
consumer.commit()
|
||||
out.append(msg)
|
||||
if ii== (leftCnt-1):
|
||||
break###断流或者到终点
|
||||
return out
|
||||
def detector(par):
|
||||
consumer = KafkaConsumer(
|
||||
bootstrap_servers=par['server'],
|
||||
group_id=par['group_id'],
|
||||
#auto_offset_reset='earliest',
|
||||
auto_offset_reset='latest',
|
||||
#isolation_level = 'read_committed',
|
||||
#enable_auto_commit=True
|
||||
)
|
||||
consumer.subscribe( par['topic'][0:2])
|
||||
print( ' Start kafka ')
|
||||
msgs = getAllRecords(consumer,par['topic'])
|
||||
print( 'getover cnt',len(msgs))
|
||||
for ii,msg in enumerate(msgs):
|
||||
print(msg)
|
||||
try:
|
||||
print('##'*10,ii)
|
||||
taskInfos = eval(msg.value.decode('utf-8'))
|
||||
print(taskInfos )
|
||||
except:
|
||||
print('**'*10,'wrong',ii)
|
||||
print(msg.value.decode('utf-8'))
|
||||
if __name__ == '__main__':
|
||||
par={};
|
||||
###topic0--在线,topic1--离线
|
||||
|
||||
#par['server']='212.129.223.66:9092';par['topic']=('thsw','thsw2','testReturn');par['group_id']='test';
|
||||
|
||||
par['server']='101.132.127.1:19092';par['topic']=('alg-online-tasks', 'alg-task-results','alg-offline-tasks');par['group_id']='testww';
|
||||
#par['server']='101.132.127.1:19092';par['topic']=('alg-online-tasks','alg-task-results','alg-offline-tasks');par['group_id']='testW11';
|
||||
par['kafka']='mintors/kafka'
|
||||
detector(par)
|
||||
|
|
@ -0,0 +1,420 @@
|
|||
import numpy as np
|
||||
import time,ast,copy
|
||||
from flask import request, Flask,jsonify
|
||||
import base64,cv2,os,sys,json
|
||||
sys.path.extend(['../yolov5'])
|
||||
#from Send_tranfer import b64encode_function,JsonSend,name_dic,nameID_dic,getLogFileFp
|
||||
from segutils.segmodel import SegModel,get_largest_contours
|
||||
from models.experimental import attempt_load
|
||||
from utils.datasets import LoadStreams, LoadImages
|
||||
from utils.torch_utils import select_device, load_classifier, time_synchronized
|
||||
from queRiver import get_labelnames,get_label_arrays,post_process_,save_problem_images,time_str
|
||||
import subprocess as sp
|
||||
import matplotlib.pyplot as plt
|
||||
import torch,random,string
|
||||
import multiprocessing
|
||||
from multiprocessing import Process,Queue
|
||||
import traceback
|
||||
from kafka import KafkaProducer, KafkaConsumer,TopicPartition
|
||||
from kafka.errors import kafka_errors
|
||||
|
||||
#torch.multiprocessing.set_start_method('spawn')
|
||||
import utilsK
|
||||
from utilsK.GPUtils import *
|
||||
from utilsK.masterUtils import *
|
||||
from utilsK.sendUtils import create_status_msg,update_json
|
||||
|
||||
#from utilsK.modelEval import onlineModelProcess
|
||||
import random,string
|
||||
from Send_tranfer_oss import msg_dict_on,msg_dict_off
|
||||
|
||||
process_id=0
|
||||
|
||||
def onlineModelProcess(parIn ):
|
||||
DEBUG=False
|
||||
streamName = parIn['streamName']
|
||||
childCallback=parIn['callback']
|
||||
#try:
|
||||
for wan in ['test']:
|
||||
jsonfile=parIn['modelJson']
|
||||
with open(jsonfile,'r') as fp:
|
||||
parAll = json.load(fp)
|
||||
|
||||
Detweights=parAll['gpu_process']['det_weights']
|
||||
seg_nclass = parAll['gpu_process']['seg_nclass']
|
||||
Segweights = parAll['gpu_process']['seg_weights']
|
||||
videoSave = parAll['AI_video_save']
|
||||
imageTxtFile = parAll['imageTxtFile']
|
||||
|
||||
|
||||
inSource,outSource=parIn['inSource'],parIn['outSource']
|
||||
|
||||
kafka_par=parIn['kafka_par']
|
||||
producer = KafkaProducer(bootstrap_servers=kafka_par['server'],value_serializer=lambda v: v.encode('utf-8'),metadata_max_age_ms=120000)
|
||||
|
||||
|
||||
|
||||
device = select_device(parIn['device'])
|
||||
half = device.type != 'cpu' # half precision only supported on CUDA
|
||||
model = attempt_load(Detweights, map_location=device) # load FP32 model
|
||||
if half: model.half()
|
||||
|
||||
#print('###line116:,',len(dataset),dataset)
|
||||
if (inSource.endswith('.MP4')) or (inSource.endswith('.mp4')):
|
||||
fps,outW,outH,totalcnt=get_fps_rtmp(inSource,video=True)[0:4]
|
||||
else:
|
||||
fps,outW,outH,totalcnt=get_fps_rtmp(inSource,video=False)[0:4]
|
||||
fps = int(fps+0.5)
|
||||
|
||||
|
||||
segmodel = SegModel(nclass=seg_nclass,weights=Segweights,device=device)
|
||||
|
||||
if outSource != 'NO':
|
||||
command=['ffmpeg','-y','-f', 'rawvideo','-vcodec','rawvideo','-pix_fmt', 'bgr24',
|
||||
'-s', "{}x{}".format(outW,outH),# 图片分辨率
|
||||
'-r', str(fps),# 视频帧率
|
||||
'-i', '-','-c:v', 'libx264','-pix_fmt', 'yuv420p',
|
||||
'-f', 'flv',outSource
|
||||
]
|
||||
video_flag = videoSave['onLine']
|
||||
logdir = parAll['logChildProcessOnline']
|
||||
#print('*'*20,'###line82',command)
|
||||
else:
|
||||
video_flag = videoSave['offLine'] ;logdir = parAll['logChildProcessOffline']
|
||||
|
||||
fp_log=create_logFile(logdir=logdir)
|
||||
# 管道配置,其中用到管道
|
||||
if outSource !='NO' :
|
||||
ppipe = sp.Popen(command, stdin=sp.PIPE)
|
||||
|
||||
|
||||
##后处理参数
|
||||
par=parAll['post_process']
|
||||
conf_thres,iou_thres,classes=par['conf_thres'],par['iou_thres'],par['classes']
|
||||
outImaDir = par['outImaDir']
|
||||
outVideoDir = par['outVideoDir']
|
||||
labelnames=par['labelnames']
|
||||
rainbows=par['rainbows']
|
||||
fpsample = par['fpsample']
|
||||
names=get_labelnames(labelnames)
|
||||
label_arraylist = get_label_arrays(names,rainbows,outfontsize=40)
|
||||
|
||||
dataset = LoadStreams(inSource, img_size=640, stride=32)
|
||||
|
||||
|
||||
childCallback.send('####model load success####')
|
||||
if (outVideoDir!='NO') and video_flag:
|
||||
msg_id = streamName.split('-')[2]
|
||||
save_path = os.path.join(outVideoDir,msg_id+'.MP4')
|
||||
vid_writer = cv2.VideoWriter(save_path, cv2.VideoWriter_fourcc(*'mp4v'), fps, (outW,outH))
|
||||
|
||||
iframe = 0;post_results=[];time_beg=time.time()
|
||||
|
||||
t00=time.time()
|
||||
time_kafka0=time.time()
|
||||
for path, img, im0s, vid_cap in dataset:
|
||||
|
||||
t0= time_synchronized()
|
||||
if not path:
|
||||
EndUrl='%s/%s_frame-9999-9999_type-结束_9999999999999999_s-%s_AI.jpg'%(outImaDir,time_str(),streamName)
|
||||
EndUrl = EndUrl.replace(' ','-').replace(':','-')
|
||||
img_end=np.zeros((100,100),dtype=np.uint8);cv2.imwrite(EndUrl,img_end)
|
||||
if imageTxtFile:
|
||||
EndUrl_txt = EndUrl.replace('.jpg','.txt')
|
||||
fp_t=open(EndUrl_txt,'w');fp_t.write(EndUrl+'\n');fp_t.close()
|
||||
|
||||
EndUrl='%s/%s_frame-9999-9999_type-结束_9999999999999999_s-%s_OR.jpg'%(outImaDir,time_str(),streamName)
|
||||
EndUrl = EndUrl.replace(' ','-').replace(':','-')
|
||||
ret = cv2.imwrite(EndUrl,img_end)
|
||||
if imageTxtFile:
|
||||
EndUrl_txt = EndUrl.replace('.jpg','.txt')
|
||||
fp_t=open(EndUrl_txt,'w');fp_t.write(EndUrl+'\n');fp_t.close()
|
||||
|
||||
#print(EndUrl,ret)
|
||||
childCallback.send('####strem ends####')
|
||||
if (outVideoDir!='NO') and video_flag:
|
||||
vid_writer.release()
|
||||
break###断流或者到终点
|
||||
|
||||
if outSource == 'NO':###如果不推流,则显示进度条
|
||||
view_bar(iframe,totalcnt,time_beg ,parIn['process_uid'] )
|
||||
|
||||
###直播和离线都是1分钟发一次消息。直播发
|
||||
time_kafka1 = time.time()
|
||||
if time_kafka1 - time_kafka0 >60:
|
||||
time_kafka0 = time_kafka1
|
||||
###发送状态信息waiting
|
||||
msg = copy.deepcopy(msg_dict_off);taskId,msgId = streamName.split('-')[1:3]
|
||||
msg['msg_id']= msgId; msg
|
||||
if outSource == 'NO':
|
||||
msg['progressbar']= '%.4f'%(iframe*1.0/totalcnt)
|
||||
msg['type']=1
|
||||
else:
|
||||
msg['progressbarOn']= str(iframe)
|
||||
msg['type']=2
|
||||
|
||||
msg = json.dumps(msg, ensure_ascii=False)
|
||||
|
||||
try:
|
||||
record_metadata = producer.send(kafka_par['topic'], msg).get()
|
||||
outstr='%s processing send progressbar or heartBeat to kafka: taskId:%s msgId:%s send:%s'%('-'*20,taskId, msgId,msg);
|
||||
wrtiteLog(fp_log,outstr);print( outstr);
|
||||
except Exception as e:
|
||||
outstr='#######kafka ERROR when processing sending progressbar or heartBeat:, error: %s'%(str(e))
|
||||
wrtiteLog(fp_log,outstr);print( outstr);
|
||||
try:
|
||||
producer = KafkaProducer(bootstrap_servers=par['server'], value_serializer=lambda v: v.encode('utf-8')).get()
|
||||
future = producer.send(par['topic'][2], msg).get()
|
||||
except Exception as e:
|
||||
outstr='%s re-send progressbar or heartBeat kafka,processing video or stream: taskId:%s msgId:%s send:%s'%('-'*20,taskId, msgId,msg);
|
||||
wrtiteLog(fp_log,outstr);print( outstr);
|
||||
|
||||
|
||||
time0=time.time()
|
||||
iframe +=1
|
||||
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
|
||||
|
||||
timeseg0 = time.time()
|
||||
seg_pred,segstr = segmodel.eval(im0s[0] )
|
||||
timeseg1 = time.time()
|
||||
|
||||
t1= time_synchronized()
|
||||
pred = model(img,augment=False)[0]
|
||||
time4 = time.time()
|
||||
datas = [path, img, im0s, vid_cap,pred,seg_pred,iframe]
|
||||
|
||||
p_result,timeOut = post_process_(datas,conf_thres, iou_thres,names,label_arraylist,rainbows,iframe)
|
||||
t2= time_synchronized()
|
||||
|
||||
#print('###line138:',timeOut,outSource,outVideoDir)
|
||||
##每隔 fpsample帧处理一次,如果有问题就保存图片
|
||||
if (iframe % fpsample == 0) and (len(post_results)>0) :
|
||||
parImage=save_problem_images(post_results,iframe,names,streamName=streamName,outImaDir='problems/images_tmp',imageTxtFile=imageTxtFile)
|
||||
post_results=[]
|
||||
|
||||
if len(p_result[2] )>0: ##
|
||||
post_results.append(p_result)
|
||||
t3= time_synchronized()
|
||||
image_array = p_result[1]
|
||||
if outSource!='NO':
|
||||
ppipe.stdin.write(image_array.tobytes())
|
||||
|
||||
if (outVideoDir!='NO') and video_flag:
|
||||
ret = vid_writer.write(image_array)
|
||||
t4= time_synchronized()
|
||||
|
||||
timestr2 = time.strftime("%Y-%m-%d-%H-%M-%S", time.localtime())
|
||||
if iframe%100==0:
|
||||
outstr='%s,,read:%.1f ms,copy:%.1f, infer:%.1f ms, detinfer:%.1f ms,draw:%.1f ms, save:%.1f ms total:%.1f ms \n'%(timestr2,(t0 - t00)*1000,(timeseg0-t0)*1000, (t1 - timeseg0)*1000,(t2-t1)*1000, (t3 - t2)*1000,(t4-t3)*1000, (t4-t00)*1000)
|
||||
wrtiteLog(fp_log,outstr);
|
||||
#print(outstr)
|
||||
t00 = t4;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
##模型加载之类的错误
|
||||
#except Exception as e:
|
||||
|
||||
# print(time.strftime("%Y-%m-%d %H:%M:%S ", time.localtime()) ,'*'*20,'###line177 ERROR:',e)
|
||||
# childCallback.send(e) #将异常通过管道送出
|
||||
|
||||
|
||||
def lauch_process(gpuid,inSource,outSource,taskId,msgId,modelJson,kafka_par):
|
||||
|
||||
if outSource=='NO':
|
||||
streamName='off-%s-%s'%(taskId,msgId)
|
||||
else:
|
||||
streamName='live-%s-%s'%(taskId,msgId)
|
||||
dataPar ={
|
||||
'imgData':'',
|
||||
'imgName':'testW',
|
||||
'streamName':streamName,
|
||||
'taskId':taskId,
|
||||
'msgId':msgId,
|
||||
'device':str(gpuid),
|
||||
'modelJson':modelJson,
|
||||
'kafka_par':kafka_par,
|
||||
}
|
||||
#dataPar['inSource'] = 'http://images.5gai.taauav.com/video/8bc32984dd893930dabb2856eb92b4d1.mp4';dataPar['outSource'] = None
|
||||
dataPar['inSource'] = inSource;dataPar['outSource'] = outSource
|
||||
process_uid=''.join(random.sample(string.ascii_letters + string.digits, 16));dataPar['process_uid']=process_uid
|
||||
parent_conn, child_conn = multiprocessing.Pipe();dataPar['callback']=child_conn
|
||||
gpuProcess=Process(target=onlineModelProcess,name='process:%s'%( process_uid ),args=(dataPar,))
|
||||
gpuProcess.start()
|
||||
#print(dir(gpuProcess))
|
||||
child_return = parent_conn.recv()
|
||||
timestr2=time.strftime("%Y-%m-%d %H:%M:%S ", time.localtime())
|
||||
print(timestr2,'-'*20,'progress:%s ,msgId:%s , taskId:%s return:'%(process_uid,msgId,taskId),child_return)
|
||||
|
||||
return gpuProcess
|
||||
|
||||
|
||||
msg_dict_offline = {
|
||||
|
||||
"biz_id":"hehuzhang",
|
||||
"mod_id":"ai",
|
||||
"msg_id":'bb'+''.join(random.sample(string.ascii_letters ,30) ) ,
|
||||
"offering_id":"http://vod.play.t-aaron.com/customerTrans/c49a2c620795d124f2ae4b10197b8d0e/303b7a58-17f3ef4494e-0004-f90c-f2c-7ec68.mp4",
|
||||
"offering_type":"mp4",
|
||||
"results_base_dir": "XJRW202203171535"+str(random.randint(10,99)),
|
||||
|
||||
'outSource':'NO'
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
def detector_0(par):
|
||||
####初始化信息列表
|
||||
consumer = KafkaConsumer(
|
||||
bootstrap_servers=par['server'],
|
||||
group_id=par['group_id'],
|
||||
auto_offset_reset='earliest',
|
||||
#max_poll_interval_ms = 1000*60*6,
|
||||
|
||||
#session_timeout_ms=1000*60*5,
|
||||
request_timeout_ms=15000,
|
||||
#enable_auto_commit=True
|
||||
)
|
||||
consumer.subscribe( par['topic'][0:2])
|
||||
kafka_par ={ 'server':par['server'],'topic':par['topic'][2] }
|
||||
producer = KafkaProducer(
|
||||
bootstrap_servers=par['server'],#tencent yun
|
||||
value_serializer=lambda v: v.encode('utf-8'),
|
||||
metadata_max_age_ms=120000)
|
||||
|
||||
taskStatus={}
|
||||
taskStatus['onLine'] = Queue(100)
|
||||
taskStatus['offLine']= Queue(100)
|
||||
taskStatus['pidInfos']= {}
|
||||
|
||||
fp_log=create_logFile(logdir=par['logDir'])
|
||||
wrtiteLog(fp_log,'###########masster starts in line222######\n')
|
||||
|
||||
timeSleep=1
|
||||
|
||||
#taskStatus['pidInfos'][31897]={'gpuProcess':'onlineProcess','type':'onLine'}
|
||||
|
||||
|
||||
time0=time.time()
|
||||
time0_kafQuery=time.time()
|
||||
time0_taskQuery=time.time()
|
||||
time0_sleep=time.time()
|
||||
time_interval=10; outStrList={}
|
||||
|
||||
isleep=0
|
||||
while True:###每隔timeSleep秒,轮询一次
|
||||
#for isleep in range(1):
|
||||
|
||||
##1-读取kafka,更新任务类别
|
||||
try:
|
||||
#msgs = getAllRecords(consumer,par['topic'])
|
||||
msgs=[]
|
||||
for ii,msg in enumerate(consumer):
|
||||
consumer.commit()
|
||||
msgs.append(msg)
|
||||
|
||||
except Exception as e:
|
||||
outstr='%s kafka connecting error:%s '%('#'*20,e)
|
||||
outstr=wrtiteLog(fp_log,outstr);print( outstr);
|
||||
time.sleep(timeSleep)
|
||||
continue
|
||||
#if get_whether_gpuProcess():
|
||||
|
||||
|
||||
for it in range(30):
|
||||
timestr=time.strftime("%Y-%m-%d %H:%M:%S ", time.localtime())
|
||||
print('%s i=%d sleep:%s '%(timestr,isleep,it*10))
|
||||
time.sleep(10)
|
||||
isleep+=1
|
||||
print('########Program End#####')
|
||||
|
||||
def detector(par):
|
||||
####初始化信息列表
|
||||
consumer = KafkaConsumer(
|
||||
bootstrap_servers=par['server'],
|
||||
group_id=par['group_id'],
|
||||
auto_offset_reset='earliest',
|
||||
#max_poll_interval_ms = 1000*60*6,
|
||||
|
||||
#session_timeout_ms=1000*60*5,
|
||||
#request_timeout_ms=11000,
|
||||
#enable_auto_commit=True
|
||||
)
|
||||
consumer.subscribe( par['topic'][0:2])
|
||||
kafka_par ={ 'server':par['server'],'topic':par['topic'][2] }
|
||||
producer = KafkaProducer(
|
||||
bootstrap_servers=par['server'],#tencent yun
|
||||
value_serializer=lambda v: v.encode('utf-8'),
|
||||
metadata_max_age_ms=120000)
|
||||
|
||||
taskStatus={}
|
||||
taskStatus['onLine'] = Queue(100)
|
||||
taskStatus['offLine']= Queue(100)
|
||||
taskStatus['pidInfos']= {}
|
||||
|
||||
|
||||
timeSleep=1
|
||||
|
||||
#taskStatus['pidInfos'][31897]={'gpuProcess':'onlineProcess','type':'onLine'}
|
||||
|
||||
|
||||
time0=time.time()
|
||||
time0_kafQuery=time.time()
|
||||
time0_taskQuery=time.time()
|
||||
time0_sleep=time.time()
|
||||
time_interval=10; outStrList={}
|
||||
|
||||
isleep=0
|
||||
|
||||
for ii,msg in enumerate(consumer):
|
||||
try:
|
||||
taskInfos = eval(msg.value.decode('utf-8') )
|
||||
except:
|
||||
outstr='%s msg format error,value:%s,offset:%d partition:%s topic:%s'%('#'*20,msg.value,msg.offset,msg.topic,msg.topic)
|
||||
continue
|
||||
outstr='%s value:%s,offset:%d partition:%s topic:%s'%('#'*20,msg.value,msg.offset,msg.partition,msg.topic)
|
||||
print(outstr)
|
||||
def get_file():
|
||||
print("文件名 :",__file__,sys._getframe().f_lineno)
|
||||
print("函数名: ", sys._getframe().f_code.co_name)
|
||||
print("模块名: ", sys._getframe().f_back.f_code.co_name)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
par={};
|
||||
###topic0--在线,topic1--离线
|
||||
|
||||
#par['server']='212.129.223.66:9092';par['topic']=('thsw','thsw2','testReturn');par['group_id']='test';
|
||||
#101.132.127.1:19092
|
||||
|
||||
'''
|
||||
par['server']='101.132.127.1:19092 ';par['topic']=('alg-online-tasks','alg-offline-tasks','alg-task-results');par['group_id']='test';
|
||||
|
||||
par['kafka']='mintors/kafka'
|
||||
par['modelJson']='conf/model.json'
|
||||
'''
|
||||
masterFile="conf/master_ten.json"
|
||||
assert os.path.exists(masterFile)
|
||||
with open(masterFile,'r') as fp:
|
||||
data=json.load(fp)
|
||||
get_file()
|
||||
|
||||
|
||||
par=data['par']
|
||||
print(par)
|
||||
detector(par)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,79 @@
|
|||
from PIL import Image
|
||||
import numpy as np
|
||||
import cv2
|
||||
import base64
|
||||
import io
|
||||
import requests
|
||||
|
||||
|
||||
def test():
|
||||
image_path='test/P0017.png'
|
||||
image_array=cv2.imread(image_path)
|
||||
print(image_array.shape)
|
||||
|
||||
image_encode=base64.b64encode(image_array).decode('utf-8')
|
||||
image_bytes=bytes(image_encode,encoding='utf-8')
|
||||
image_decode=np.frombuffer(base64.decodebytes(image_bytes),dtype=np.uint8)
|
||||
print(image_decode.shape)
|
||||
|
||||
request_url='http://192.168.109.49:5000/'
|
||||
|
||||
headers={'content-type':'application/json'}
|
||||
data={'image':image_encode}
|
||||
|
||||
#response=requests.post(request_url,data=data,headers=headers)
|
||||
response=requests.post(request_url,"POST",files=data)
|
||||
print(response)
|
||||
#image=open(image_path,'rb').read()
|
||||
#image=Image.open(io.BytesIO(image))
|
||||
#image=image.resize((224,224))
|
||||
#image=np.asarray(image
|
||||
def test2():
|
||||
image_path='test/P0017.png'
|
||||
image_ori=cv2.imread(image_path)
|
||||
api = 'http://192.168.109.49:8000/detector'
|
||||
#img = cv2.imencode('.jpg', img_ori)[-1]
|
||||
|
||||
image_encode=base64.b64encode(image_ori).decode('utf-8')
|
||||
img=bytes(image_encode,encoding='utf-8')
|
||||
h,w,c=image_ori.shape
|
||||
|
||||
files = {'file': img}
|
||||
files = {'file': img,'name':'P0017',
|
||||
'img_width':w,
|
||||
'img_height':h,
|
||||
'img_chs':c
|
||||
}
|
||||
res = requests.request("POST", api, files=files).json()
|
||||
|
||||
if res['msg'] == 'success':
|
||||
bboxes = res['data']['bboxes']
|
||||
print(bboxes)
|
||||
#bboxes = np.asarray(bboxes, dtype=np.int32)
|
||||
def test3():
|
||||
image_path='test/P0017.png'
|
||||
image_ori=cv2.imread(image_path)
|
||||
api = 'http://192.168.109.49:8000/detector'
|
||||
#img = cv2.imencode('.jpg', img_ori)[-1]
|
||||
|
||||
input_ ={
|
||||
'img_data':'',
|
||||
'img_width':512,
|
||||
'img_height':512,
|
||||
'img_chs':3
|
||||
}
|
||||
|
||||
with open(image_path,'rb') as f:
|
||||
input_['img_data']=base64.b64encode(f.read()).decode()
|
||||
|
||||
image_encode=base64.b64encode(image_ori).decode('utf-8')
|
||||
image_bytes=bytes(image_encode,encoding='utf-8')
|
||||
input_['img_data']=image_bytes:
|
||||
|
||||
response=requests.post(api,json=input_)
|
||||
print(response.text)
|
||||
|
||||
|
||||
|
||||
if __name__=='__main__':
|
||||
test2()
|
||||
|
|
@ -0,0 +1,645 @@
|
|||
import numpy as np
|
||||
import time,ast,copy
|
||||
from flask import request, Flask,jsonify
|
||||
import base64,cv2,os,sys,json
|
||||
sys.path.extend(['../yolov5'])
|
||||
#from Send_tranfer import b64encode_function,JsonSend,name_dic,nameID_dic,getLogFileFp
|
||||
from segutils.segmodel import SegModel,get_largest_contours
|
||||
from models.experimental import attempt_load
|
||||
from utils.datasets import LoadStreams, LoadImages
|
||||
from utils.torch_utils import select_device, load_classifier, time_synchronized
|
||||
from queRiver import get_labelnames,get_label_arrays,post_process_,save_problem_images,time_str
|
||||
import subprocess as sp
|
||||
import matplotlib.pyplot as plt
|
||||
import torch,random,string
|
||||
import multiprocessing
|
||||
from multiprocessing import Process,Queue
|
||||
import traceback
|
||||
from kafka import KafkaProducer, KafkaConsumer,TopicPartition
|
||||
from kafka.errors import kafka_errors
|
||||
|
||||
#torch.multiprocessing.set_start_method('spawn')
|
||||
import utilsK
|
||||
from utilsK.GPUtils import *
|
||||
from utilsK.masterUtils import *
|
||||
from utilsK.sendUtils import create_status_msg,update_json
|
||||
|
||||
#from utilsK.modelEval import onlineModelProcess
|
||||
import random,string
|
||||
from Send_tranfer_oss import msg_dict_on,msg_dict_off
|
||||
import pykafka
|
||||
from pykafka import KafkaClient
|
||||
process_id=0
|
||||
|
||||
def onlineModelProcess(parIn ):
|
||||
DEBUG=False
|
||||
streamName = parIn['streamName']
|
||||
childCallback=parIn['callback']
|
||||
outStrList={}
|
||||
#try:
|
||||
for wan in ['test']:
|
||||
jsonfile=parIn['modelJson']
|
||||
with open(jsonfile,'r') as fp:
|
||||
parAll = json.load(fp)
|
||||
|
||||
Detweights=parAll['gpu_process']['det_weights']
|
||||
seg_nclass = parAll['gpu_process']['seg_nclass']
|
||||
Segweights = parAll['gpu_process']['seg_weights']
|
||||
videoSave = parAll['AI_video_save']
|
||||
imageTxtFile = parAll['imageTxtFile']
|
||||
taskId,msgId = streamName.split('-')[1:3]
|
||||
|
||||
inSource,outSource=parIn['inSource'],parIn['outSource']
|
||||
|
||||
##构建日志文件
|
||||
if outSource != 'NO':
|
||||
logdir = parAll['logChildProcessOnline']
|
||||
waitingTime=parAll['StreamWaitingTime']
|
||||
else:
|
||||
logdir = parAll['logChildProcessOffline']
|
||||
waitingTime=5
|
||||
|
||||
fp_log=create_logFile(logdir=logdir)
|
||||
kafka_par=parIn['kafka_par']
|
||||
producer = KafkaProducer(bootstrap_servers=kafka_par['server'],value_serializer=lambda v: v.encode('utf-8'),metadata_max_age_ms=120000)
|
||||
|
||||
####要先检查视频的有效性
|
||||
###开始的时候,如果在线任务没有流,要发送的心跳消息,msg_h,
|
||||
msg_h= copy.deepcopy(msg_dict_off);
|
||||
msg_h['status']='waiting';msg_h['msg_id']=msgId
|
||||
|
||||
|
||||
if outSource == 'NO':
|
||||
msg_h['type']=1
|
||||
Stream_ok= get_fps_rtmp(inSource,video=True)
|
||||
else:
|
||||
msg_h['type']=2
|
||||
|
||||
msg_h_d = json.dumps(msg_h, ensure_ascii=False)
|
||||
outStrList['success']= '%s waiting stream or video, send heartbeat: taskId:%s msgId:%s send:%s'%('-'*20,taskId, msgId,msg_h);
|
||||
outStrList['failure']='#######kafka ERROR waiting stream or video, send heartbeat'
|
||||
outStrList['Refailure']='##############kafka ERROR waiting stream or video, Re-send heartbeat'
|
||||
Stream_ok=check_stream(inSource,producer,kafka_par,msg_h_d,outStrList,fp_log ,timeMs=waitingTime)
|
||||
|
||||
if Stream_ok:###发送开始信号
|
||||
msg_h['status']='running'
|
||||
msg_h_d = json.dumps(msg_h, ensure_ascii=False)
|
||||
|
||||
outStrList['success']= '%s informing stream/video is ok, taskId:%s msgId:%s send:%s'%('-'*20,taskId, msgId,msg_h);
|
||||
outStrList['failure']='#######kafka ERROR ,when informing stream/video is ok'
|
||||
outStrList['Refailure']='##############kafka ERROR, when re-informing stream/video is ok'
|
||||
|
||||
send_kafka(producer,kafka_par,msg_h_d,outStrList,fp_log );
|
||||
|
||||
else:
|
||||
####检测离线视频是否有效,无效要报错
|
||||
outstr='############# offline vedio or live stream Error:%s #################'%(inSource)
|
||||
outstr=wrtiteLog(fp_log,outstr);print( outstr);
|
||||
|
||||
msg_h['error']=str(1001);msg_h['status']='failed';
|
||||
msg_h_d = json.dumps(msg_h, ensure_ascii=False);
|
||||
outStrList['success']= '%s informing invaid video or stream success : taskId:%s msgId:%s send:%s'%('-'*20,taskId, msgId,msg_h);
|
||||
outStrList['failure']='#######kafka ERROR, when informing invaid video or stream'
|
||||
outStrList['Refailure']='##############kafka ERROR,when re-informing invaid video or stream'
|
||||
send_kafka(producer,kafka_par,msg_h_d,outStrList,fp_log );
|
||||
childCallback.send(' offline vedio or live stream Error')
|
||||
continue
|
||||
|
||||
|
||||
|
||||
if (inSource.endswith('.MP4')) or (inSource.endswith('.mp4')):
|
||||
fps,outW,outH,totalcnt=get_fps_rtmp(inSource,video=True)[0:4]
|
||||
else:
|
||||
fps,outW,outH,totalcnt=get_fps_rtmp(inSource,video=False)[0:4]
|
||||
fps = int(fps+0.5)
|
||||
if outSource != 'NO':
|
||||
command=['ffmpeg','-y','-f', 'rawvideo','-vcodec','rawvideo','-pix_fmt', 'bgr24',
|
||||
'-s', "{}x{}".format(outW,outH),# 图片分辨率
|
||||
'-r', str(fps),# 视频帧率
|
||||
'-i', '-','-c:v', 'libx264','-pix_fmt', 'yuv420p',
|
||||
'-f', 'flv',outSource
|
||||
]
|
||||
video_flag = videoSave['onLine']
|
||||
logdir = parAll['logChildProcessOnline']
|
||||
waitingTime=parAll['StreamWaitingTime']
|
||||
else:
|
||||
video_flag = videoSave['offLine'] ;logdir = parAll['logChildProcessOffline']
|
||||
waitingTime=5
|
||||
|
||||
fp_log=create_logFile(logdir=logdir)
|
||||
|
||||
|
||||
device = select_device(parIn['device'])
|
||||
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)
|
||||
|
||||
|
||||
|
||||
# 管道配置,其中用到管道
|
||||
if outSource !='NO' :
|
||||
ppipe = sp.Popen(command, stdin=sp.PIPE)
|
||||
|
||||
|
||||
##后处理参数
|
||||
par=parAll['post_process']
|
||||
conf_thres,iou_thres,classes=par['conf_thres'],par['iou_thres'],par['classes']
|
||||
outImaDir = par['outImaDir']
|
||||
outVideoDir = par['outVideoDir']
|
||||
labelnames=par['labelnames']
|
||||
rainbows=par['rainbows']
|
||||
fpsample = par['fpsample']
|
||||
names=get_labelnames(labelnames)
|
||||
label_arraylist = get_label_arrays(names,rainbows,outfontsize=40)
|
||||
|
||||
dataset = LoadStreams(inSource, img_size=640, stride=32)
|
||||
|
||||
|
||||
childCallback.send('####model load success####')
|
||||
if (outVideoDir!='NO') and video_flag:
|
||||
msg_id = streamName.split('-')[2]
|
||||
save_path = os.path.join(outVideoDir,msg_id+'.MP4')
|
||||
vid_writer = cv2.VideoWriter(save_path, cv2.VideoWriter_fourcc(*'mp4v'), fps, (outW,outH))
|
||||
|
||||
iframe = 0;post_results=[];time_beg=time.time()
|
||||
|
||||
t00=time.time()
|
||||
time_kafka0=time.time()
|
||||
for path, img, im0s, vid_cap in dataset:
|
||||
|
||||
t0= time_synchronized()
|
||||
if not path:
|
||||
EndUrl='%s/%s_frame-9999-9999_type-结束_9999999999999999_s-%s_AI.jpg'%(outImaDir,time_str(),streamName)
|
||||
EndUrl = EndUrl.replace(' ','-').replace(':','-')
|
||||
img_end=np.zeros((100,100),dtype=np.uint8);cv2.imwrite(EndUrl,img_end)
|
||||
if imageTxtFile:
|
||||
EndUrl_txt = EndUrl.replace('.jpg','.txt')
|
||||
fp_t=open(EndUrl_txt,'w');fp_t.write(EndUrl+'\n');fp_t.close()
|
||||
|
||||
EndUrl='%s/%s_frame-9999-9999_type-结束_9999999999999999_s-%s_OR.jpg'%(outImaDir,time_str(),streamName)
|
||||
EndUrl = EndUrl.replace(' ','-').replace(':','-')
|
||||
ret = cv2.imwrite(EndUrl,img_end)
|
||||
if imageTxtFile:
|
||||
EndUrl_txt = EndUrl.replace('.jpg','.txt')
|
||||
fp_t=open(EndUrl_txt,'w');fp_t.write(EndUrl+'\n');fp_t.close()
|
||||
|
||||
#print(EndUrl,ret)
|
||||
childCallback.send('####strem ends####')
|
||||
if (outVideoDir!='NO') and video_flag:
|
||||
vid_writer.release()
|
||||
break###断流或者到终点
|
||||
|
||||
if outSource == 'NO':###如果不推流,则显示进度条
|
||||
view_bar(iframe,totalcnt,time_beg ,parIn['process_uid'] )
|
||||
|
||||
###直播和离线都是1分钟发一次消息。直播发
|
||||
time_kafka1 = time.time()
|
||||
if time_kafka1 - time_kafka0 >60:
|
||||
time_kafka0 = time_kafka1
|
||||
###发送状态信息waiting
|
||||
msg = copy.deepcopy(msg_dict_off);
|
||||
msg['msg_id']= msgId; msg
|
||||
if outSource == 'NO':
|
||||
msg['progressbar']= '%.4f'%(iframe*1.0/totalcnt)
|
||||
msg['type']=1
|
||||
else:
|
||||
msg['progressbarOn']= str(iframe)
|
||||
msg['type']=2
|
||||
|
||||
msg = json.dumps(msg, ensure_ascii=False)
|
||||
'''
|
||||
try:
|
||||
record_metadata = producer.send(kafka_par['topic'], msg).get()
|
||||
outstr='%s processing send progressbar or heartBeat to kafka: taskId:%s msgId:%s send:%s'%('-'*20,taskId, msgId,msg);
|
||||
wrtiteLog(fp_log,outstr);print( outstr);
|
||||
except Exception as e:
|
||||
outstr='#######kafka ERROR when processing sending progressbar or heartBeat:, error: %s'%(str(e))
|
||||
wrtiteLog(fp_log,outstr);print( outstr);
|
||||
try:
|
||||
producer = KafkaProducer(bootstrap_servers=par['server'], value_serializer=lambda v: v.encode('utf-8')).get()
|
||||
future = producer.send(par['topic'][2], msg).get()
|
||||
except Exception as e:
|
||||
outstr='%s re-send progressbar or heartBeat kafka,processing video or stream: taskId:%s msgId:%s send:%s'%('-'*20,taskId, msgId,msg);
|
||||
wrtiteLog(fp_log,outstr);print( outstr);
|
||||
'''
|
||||
|
||||
|
||||
###发送状态信息waiting
|
||||
outStrList['success']= '%s processing send progressbar or heartBeat to kafka: taskId:%s msgId:%s send:%s'%('-'*20,taskId, msgId,msg);
|
||||
outStrList['failure']='#######kafka ERROR when processing sending progressbar or heartBeat'
|
||||
outStrList['Refailure']='%s re-send progressbar or heartBeat kafka,processing video or stream: taskId:%s msgId:%s send:%s'%('-'*20,taskId, msgId,msg);
|
||||
send_kafka(producer,kafka_par,msg,outStrList,fp_log );
|
||||
|
||||
|
||||
|
||||
time0=time.time()
|
||||
iframe +=1
|
||||
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
|
||||
|
||||
timeseg0 = time.time()
|
||||
seg_pred,segstr = segmodel.eval(im0s[0] )
|
||||
timeseg1 = time.time()
|
||||
|
||||
t1= time_synchronized()
|
||||
pred = model(img,augment=False)[0]
|
||||
time4 = time.time()
|
||||
datas = [path, img, im0s, vid_cap,pred,seg_pred,iframe]
|
||||
|
||||
p_result,timeOut = post_process_(datas,conf_thres, iou_thres,names,label_arraylist,rainbows,iframe)
|
||||
t2= time_synchronized()
|
||||
|
||||
#print('###line138:',timeOut,outSource,outVideoDir)
|
||||
##每隔 fpsample帧处理一次,如果有问题就保存图片
|
||||
if (iframe % fpsample == 0) and (len(post_results)>0) :
|
||||
parImage=save_problem_images(post_results,iframe,names,streamName=streamName,outImaDir='problems/images_tmp',imageTxtFile=imageTxtFile)
|
||||
post_results=[]
|
||||
|
||||
if len(p_result[2] )>0: ##
|
||||
post_results.append(p_result)
|
||||
t3= time_synchronized()
|
||||
image_array = p_result[1]
|
||||
if outSource!='NO':
|
||||
ppipe.stdin.write(image_array.tobytes())
|
||||
|
||||
if (outVideoDir!='NO') and video_flag:
|
||||
ret = vid_writer.write(image_array)
|
||||
t4= time_synchronized()
|
||||
|
||||
timestr2 = time.strftime("%Y-%m-%d-%H-%M-%S", time.localtime())
|
||||
if iframe%100==0:
|
||||
outstr='%s,,read:%.1f ms,copy:%.1f, infer:%.1f ms, detinfer:%.1f ms,draw:%.1f ms, save:%.1f ms total:%.1f ms \n'%(timestr2,(t0 - t00)*1000,(timeseg0-t0)*1000, (t1 - timeseg0)*1000,(t2-t1)*1000, (t3 - t2)*1000,(t4-t3)*1000, (t4-t00)*1000)
|
||||
wrtiteLog(fp_log,outstr);
|
||||
#print(outstr)
|
||||
t00 = t4;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
##模型加载之类的错误
|
||||
#except Exception as e:
|
||||
|
||||
# print(time.strftime("%Y-%m-%d %H:%M:%S ", time.localtime()) ,'*'*20,'###line177 ERROR:',e)
|
||||
# childCallback.send(e) #将异常通过管道送出
|
||||
|
||||
|
||||
def lauch_process(gpuid,inSource,outSource,taskId,msgId,modelJson,kafka_par):
|
||||
|
||||
if outSource=='NO':
|
||||
streamName='off-%s-%s'%(taskId,msgId)
|
||||
else:
|
||||
streamName='live-%s-%s'%(taskId,msgId)
|
||||
dataPar ={
|
||||
'imgData':'',
|
||||
'imgName':'testW',
|
||||
'streamName':streamName,
|
||||
'taskId':taskId,
|
||||
'msgId':msgId,
|
||||
'device':str(gpuid),
|
||||
'modelJson':modelJson,
|
||||
'kafka_par':kafka_par,
|
||||
}
|
||||
#dataPar['inSource'] = 'http://images.5gai.taauav.com/video/8bc32984dd893930dabb2856eb92b4d1.mp4';dataPar['outSource'] = None
|
||||
dataPar['inSource'] = inSource;dataPar['outSource'] = outSource
|
||||
process_uid=''.join(random.sample(string.ascii_letters + string.digits, 16));dataPar['process_uid']=process_uid
|
||||
parent_conn, child_conn = multiprocessing.Pipe();dataPar['callback']=child_conn
|
||||
gpuProcess=Process(target=onlineModelProcess,name='process:%s'%( process_uid ),args=(dataPar,))
|
||||
gpuProcess.start()
|
||||
#print(dir(gpuProcess))
|
||||
#child_return = parent_conn.recv()
|
||||
#timestr2=time.strftime("%Y-%m-%d %H:%M:%S ", time.localtime())
|
||||
#print(timestr2,'-'*20,'progress:%s ,msgId:%s , taskId:%s return:'%(process_uid,msgId,taskId),child_return)
|
||||
|
||||
return gpuProcess
|
||||
|
||||
|
||||
msg_dict_offline = {
|
||||
|
||||
"biz_id":"hehuzhang",
|
||||
"mod_id":"ai",
|
||||
"msg_id":'bb'+''.join(random.sample(string.ascii_letters ,30) ) ,
|
||||
"offering_id":"http://vod.play.t-aaron.com/customerTrans/c49a2c620795d124f2ae4b10197b8d0e/303b7a58-17f3ef4494e-0004-f90c-f2c-7ec68.mp4",
|
||||
"offering_type":"mp4",
|
||||
"results_base_dir": "XJRW202203171535"+str(random.randint(10,99)),
|
||||
|
||||
'outSource':'NO'
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
def detector(par):
|
||||
####初始化信息列表
|
||||
consumer = KafkaConsumer(bootstrap_servers=par['server'],client_id='AI_server',group_id=par['group_id'],auto_offset_reset='earliest')
|
||||
|
||||
|
||||
consumer.subscribe( par['topic'][0:2])
|
||||
'''
|
||||
client = KafkaClient(hosts=par['server'])
|
||||
consumer_pys=[]
|
||||
for topic_name in par['topic'][0:2]:
|
||||
consumer_pys.append(client.topics[ topic_name ].get_simple_consumer(consumer_group=par['group_id'],timeout=30))
|
||||
|
||||
'''
|
||||
|
||||
kafka_par ={ 'server':par['server'],'topic':par['topic'][2] }
|
||||
producer = KafkaProducer(
|
||||
bootstrap_servers=par['server'],#tencent yun
|
||||
value_serializer=lambda v: v.encode('utf-8'),
|
||||
metadata_max_age_ms=120000)
|
||||
|
||||
taskStatus={}
|
||||
taskStatus['onLine'] = Queue(100)
|
||||
taskStatus['offLine']= Queue(100)
|
||||
taskStatus['pidInfos']= {}
|
||||
|
||||
fp_log=create_logFile(logdir=par['logDir'])
|
||||
wrtiteLog(fp_log,'###########masster starts in line222######\n')
|
||||
|
||||
timeSleep=1
|
||||
|
||||
#taskStatus['pidInfos'][31897]={'gpuProcess':'onlineProcess','type':'onLine'}
|
||||
|
||||
|
||||
time0=time.time()
|
||||
time0_kafQuery=time.time()
|
||||
time0_taskQuery=time.time()
|
||||
time0_sleep=time.time()
|
||||
time_interval=10; outStrList={}
|
||||
while True:###每隔timeSleep秒,轮询一次
|
||||
#for isleep in range(1):
|
||||
|
||||
##1-读取kafka,更新任务类别
|
||||
try:
|
||||
'''
|
||||
msgs=[]
|
||||
for consumer in consumer_pys:
|
||||
for msg in consumer:
|
||||
if msg is None:break
|
||||
else:msgs.append(msg)
|
||||
'''
|
||||
msgs = getAllRecords(consumer,par['topic'])
|
||||
except Exception as e:
|
||||
outstr='%s kafka connecting error:%s '%('#'*20,e)
|
||||
outstr=wrtiteLog(fp_log,outstr);print( outstr);
|
||||
time.sleep(timeSleep)
|
||||
continue
|
||||
#if get_whether_gpuProcess():
|
||||
|
||||
time0_kafQuery,printFlag = check_time_interval(time0_kafQuery,time_interval)
|
||||
if printFlag:
|
||||
outstr_kafka=' ##### kafka Left %d records####'%(len(msgs));
|
||||
outstr_kafka=wrtiteLog(fp_log,outstr_kafka)
|
||||
|
||||
for ii,msg in enumerate(msgs):
|
||||
|
||||
try:
|
||||
#taskInfos = eval(json.loads(msg.value ))
|
||||
|
||||
taskInfos = eval(msg.value.decode('utf-8') )
|
||||
|
||||
except:
|
||||
|
||||
outstr='%s msg format error,value:%s,offset:%d partition:%s topic:%s'%('#'*20,msg.value,msg.offset,msg.topic,msg.topic)
|
||||
continue
|
||||
|
||||
if msg.topic == par['topic'][0]: ##
|
||||
|
||||
taskInfos['inSource']= taskInfos['pull_channel'];
|
||||
taskInfos['outSource']= get_push_address(taskInfos['push_channel']) ;
|
||||
|
||||
taskStatus['onLine'].put( taskInfos )
|
||||
save_message(par['kafka'],taskInfos)
|
||||
|
||||
###发送状态信息waiting
|
||||
msg = create_status_msg(msg_dict_on,taskInfos,sts='waiting')
|
||||
outStrList['success']= '%s read from kafka online task and back to kafka: taskId:%s msgId:%s send:%s'%('-'*20,taskInfos['results_base_dir'], taskInfos['msg_id'],msg)
|
||||
outStrList['failure']='#######kafka ERROR when read from kafka online task and back to kafka'
|
||||
outStrList['Refailure']='##############kafka ERROR when read from kafka online task and resend back to kafka:'
|
||||
send_kafka(producer,kafka_par,msg,outStrList,fp_log );
|
||||
|
||||
else:
|
||||
|
||||
taskInfos['inSource']= taskInfos['offering_id'];
|
||||
taskInfos['outSource']= 'NO'
|
||||
|
||||
taskStatus['offLine'].put( taskInfos )
|
||||
save_message(par['kafka'],taskInfos)
|
||||
|
||||
###发送状态信息waiting
|
||||
msg = create_status_msg(msg_dict_off,taskInfos,sts='waiting')
|
||||
|
||||
|
||||
outStrList['success']= '%s read from kafka offline task and back to kafka: taskId:%s msgId:%s send:%s'%('-'*20,taskInfos['results_base_dir'], taskInfos['msg_id'],msg)
|
||||
outStrList['failure']='#######kkafka ERROR when read from kafka offline task and back to kafka:,'
|
||||
outStrList['Refailure']='##############kafka ERROR when read from kafka offline task and resend back to kafka:'
|
||||
send_kafka(producer,kafka_par,msg,outStrList,fp_log );
|
||||
|
||||
|
||||
|
||||
|
||||
#if get_whether_gpuProcess():
|
||||
|
||||
time0_taskQuery,printFlag = check_time_interval(time0_taskQuery,time_interval)
|
||||
outstr_task= ' task queue onLine cnt:%d offLine:%d'%(taskStatus['onLine'].qsize(), taskStatus['offLine'].qsize())
|
||||
|
||||
##2-更新显卡信息
|
||||
gpuStatus = getGPUInfos()
|
||||
|
||||
##3-优先考虑在线任务
|
||||
if not taskStatus['onLine'].empty():
|
||||
###3.1-先判断有没有空闲显卡:
|
||||
cuda = get_available_gpu(gpuStatus)
|
||||
###获取在线任务信息,并执行,lauch process
|
||||
taskInfos = taskStatus['onLine'].get()
|
||||
'''
|
||||
#如果是在线任务,则先检测流,如若流,每10秒更新1次,两分钟内没流就断掉
|
||||
msg_h= copy.deepcopy(msg_dict_on);
|
||||
msg_h['status']='waiting';msg_h['msg_id']=taskInfos['msg_id'];msg_h = json.dumps(msg_h, ensure_ascii=False)
|
||||
outStrList['success']= '%s waiting stream, send heartbeat, msgId:%s, taskID:%s ,%s'%('-'*20, taskInfos['msg_id'],taskInfos['results_base_dir'],msg_h)
|
||||
outStrList['failure']='#######kafka ERROR waiting stream, send heartbeat'
|
||||
outStrList['Refailure']='##############kafka ERROR waiting stream, Re-send heartbeat'
|
||||
|
||||
print('################line389')
|
||||
Stream_ok=check_stream(taskInfos['inSource'],producer,par,msg_h,outStrList,fp_log ,timeMs=par['StreamWaitingTime'])
|
||||
if not Stream_ok:
|
||||
outstr='##############live Stream ERROR #################'
|
||||
outstr=wrtiteLog(fp_log,outstr);print( outstr);
|
||||
|
||||
continue
|
||||
'''
|
||||
print('################396',cuda)
|
||||
if cuda: ###3.1.1 -有空余显卡
|
||||
#lauch process
|
||||
|
||||
msg= copy.deepcopy(msg_dict_on);
|
||||
|
||||
gpuProcess=lauch_process(cuda,taskInfos['inSource'],taskInfos['outSource'],taskInfos['results_base_dir'],taskInfos['msg_id'],par['modelJson'],kafka_par)
|
||||
|
||||
taskStatus['pidInfos'][gpuProcess.pid] = {'gpuProcess':gpuProcess,'type':'onLine','taskInfos':taskInfos}
|
||||
|
||||
'''
|
||||
##返回kafka消息
|
||||
msg=update_json(taskInfos,msg,offkeys=["msg_id","biz_id" ,"mod_id" ])
|
||||
msg['results'][0]['original_url']=taskInfos['inSource']
|
||||
msg['results'][0]['sign_url']=get_boradcast_address(taskInfos['outSource'])
|
||||
msg['status']='running'
|
||||
msg = json.dumps(msg, ensure_ascii=False)
|
||||
|
||||
|
||||
outStrList['success']= '%s start online task from free gpu and back to kafka: pid:%d taskId:%s msgId:%s send:%s'%('-'*20,gpuProcess.pid,taskInfos['results_base_dir'], taskInfos['msg_id'],msg)
|
||||
outStrList['failure']='#######kafka ERROR when start online task from free gpu and back to kafka'
|
||||
outStrList['Refailure']='##############kafka ERROR when start online task from free gpu and resend back to kafka'
|
||||
send_kafka(producer,kafka_par,msg,outStrList,fp_log );
|
||||
'''
|
||||
|
||||
else:###3.1.2-没有显卡
|
||||
##判断有没有显卡上面都是离线进程的
|
||||
cuda_pid = get_potential_gpu(gpuStatus,taskStatus['pidInfos'])
|
||||
|
||||
if cuda_pid:#3.1.2.1 - ##如果有可以杀死的进程
|
||||
cuda = cuda_pid['cuda']
|
||||
pids = cuda_pid['pids']
|
||||
##kill 离线进程,并更新离线任务表
|
||||
cnt_off_0 = taskStatus['offLine'].qsize()
|
||||
for pid in pids:
|
||||
##kill 离线进程
|
||||
taskStatus['pidInfos'][pid]['gpuProcess'].kill()
|
||||
##更新离线任务表
|
||||
taskStatus['offLine'].put( taskStatus['pidInfos'][pid]['taskInfos'] )
|
||||
taskInfos_off=taskStatus['pidInfos'][pid]['taskInfos']
|
||||
|
||||
##发送离线数据,说明状态变成waiting
|
||||
msg= msg_dict_off;
|
||||
msg=update_json(taskInfos_off,msg,offkeys=["msg_id","biz_id" ,"mod_id"] )
|
||||
msg['results'][0]['original_url']=taskInfos_off['inSource']
|
||||
msg['results'][0]['sign_url']=get_boradcast_address(taskInfos_off['outSource'])
|
||||
msg['status']='waiting'
|
||||
msg = json.dumps(msg, ensure_ascii=False)
|
||||
|
||||
outStrList['success']= '%s start online task after kill offline tasks and back to kafka: pid:%d taskId:%s msgId:%s send:%s'%('-'*20,gpuProcess.pid,taskInfos_off['results_base_dir'], taskInfos_off['msg_id'],msg)
|
||||
outStrList['failure']='#######kafka ERROR when start online task after kill offline tasks and back to kafka'
|
||||
outStrList['Refailure']='##############kkafka ERROR when start online task after kill offline tasks and back to kafka'
|
||||
send_kafka(producer,kafka_par,msg,outStrList,fp_log );
|
||||
|
||||
|
||||
cnt_off_1 = taskStatus['offLine'].qsize()
|
||||
outstr='%s before killing process, offtask cnt:%d ,after killing, offtask cnt:%d %s'%('-'*20 ,cnt_off_0,cnt_off_1,'*'*20)
|
||||
outstr=wrtiteLog(fp_log,outstr);print( outstr);
|
||||
gpuProcess=lauch_process(cuda,taskInfos['inSource'],taskInfos['outSource'],taskInfos['results_base_dir'],taskInfos['msg_id'],par['modelJson'],kafka_par)
|
||||
|
||||
|
||||
###更新pidinfos,update pidInfos
|
||||
taskStatus['pidInfos'][gpuProcess.pid] = {'gpuProcess':gpuProcess,'type':'onLine','taskInfos':taskInfos}
|
||||
|
||||
'''
|
||||
##返回kafka消息
|
||||
msg= copy.deepcopy(msg_dict_on);
|
||||
msg=update_json(taskInfos,msg,offkeys=["msg_id","biz_id" ,"mod_id"] )
|
||||
msg['results'][0]['original_url']=taskInfos['inSource']
|
||||
msg['results'][0]['sign_url']=get_boradcast_address(taskInfos['outSource'])
|
||||
msg['status']='running'
|
||||
msg = json.dumps(msg, ensure_ascii=False)
|
||||
|
||||
|
||||
outStrList['success']= '%s start online task after kill offline tasks and back to kafka: pid:%d taskId:%s msgId:%s send:%s'%('-'*20,gpuProcess.pid,taskInfos['results_base_dir'], taskInfos['msg_id'],msg)
|
||||
outStrList['failure']='#######kafka ERROR when start online task after kill offline tasks and back to kafka'
|
||||
outStrList['Refailure']='##############kkafka ERROR when start online task after kill offline tasks and back to kafka'
|
||||
send_kafka(producer,kafka_par,msg,outStrList,fp_log );
|
||||
'''
|
||||
|
||||
|
||||
|
||||
else:
|
||||
outstr='######No available GPUs for onLine####'
|
||||
outstr=wrtiteLog(fp_log,outstr);print( outstr);
|
||||
##4-更新显卡信息
|
||||
gpuStatus = getGPUInfos()
|
||||
##5-考虑离线任务
|
||||
if not taskStatus['offLine'].empty():
|
||||
cudaArrange= arrange_offlineProcess(gpuStatus,taskStatus['pidInfos'],modelMemory=1500)
|
||||
outstr='###line342 IN OFF LINE TASKS available cudas:%s'%(cudaArrange)
|
||||
outstr=wrtiteLog(fp_log,outstr);print( outstr);
|
||||
for cuda in cudaArrange:
|
||||
if not taskStatus['offLine'].empty():
|
||||
taskInfos = taskStatus['offLine'].get()
|
||||
|
||||
'''
|
||||
####检测离线视频是否有效,无效要报错
|
||||
Stream_ok= get_fps_rtmp(taskInfos['inSource'],video=True)
|
||||
if not Stream_ok:
|
||||
outstr='############# offline vedio Error:%s #################'%(taskInfos['inSource'])
|
||||
outstr=wrtiteLog(fp_log,outstr);print( outstr);
|
||||
|
||||
msg_h= copy.deepcopy(msg_dict_off);msg_h['error']=str(1001)###
|
||||
msg_h['status']='failed';msg_h['msg_id']=taskInfos['msg_id'];msg_h = json.dumps(msg_h, ensure_ascii=False);
|
||||
outStrList['success']= '%s video invalid msg sending success , msgId:%s, taskID:%s ,%s'%('-'*20, taskInfos['msg_id'],taskInfos['results_base_dir'],msg_h)
|
||||
outStrList['failure']='#######kafka ERROR when sending invalid msg'
|
||||
outStrList['Refailure']='##############kafka ERROR when Re-sending invalid msg'
|
||||
send_kafka(producer,kafka_par,msg_h,outStrList,fp_log );
|
||||
continue
|
||||
'''
|
||||
|
||||
gpuProcess=lauch_process(cuda,taskInfos['inSource'],taskInfos['outSource'],taskInfos['results_base_dir'],taskInfos['msg_id'],par['modelJson'],kafka_par)
|
||||
taskStatus['pidInfos'][gpuProcess.pid] = {'gpuProcess':gpuProcess,'type':'offLine','taskInfos':taskInfos}
|
||||
|
||||
|
||||
'''
|
||||
msg = create_status_msg(msg_dict_off,taskInfos,sts='running')
|
||||
outStrList['success']= '---------start offline task and back to kafka: pid:%d taskId:%s msgId:%s send:%s'%(gpuProcess.pid,taskInfos['results_base_dir'], taskInfos['msg_id'],msg)
|
||||
outStrList['failure']='#######kafka ERROR when start offline task and back to kafka'
|
||||
outStrList['Refailure']='##############kafka ERROR when start offline task and resend back to kafka'
|
||||
send_kafka(producer,kafka_par,msg,outStrList,fp_log );
|
||||
'''
|
||||
|
||||
|
||||
|
||||
if get_whether_gpuProcess():
|
||||
time0_sleep,printFlag = check_time_interval(time0_sleep,time_interval)
|
||||
if printFlag:
|
||||
timestr2=time.strftime("%Y-%m-%d %H:%M:%S ", time.localtime())
|
||||
outstr= timestr2 + '*'*20 +'sleep '+'*'*20;
|
||||
outstr=wrtiteLog(fp_log,outstr);print( outstr);
|
||||
outstr_task=wrtiteLog(fp_log,outstr_task);print( outstr_task);
|
||||
|
||||
time.sleep(timeSleep)
|
||||
|
||||
print('########Program End#####')
|
||||
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
par={};
|
||||
###topic0--在线,topic1--离线
|
||||
|
||||
#par['server']='212.129.223.66:9092';par['topic']=('thsw','thsw2','testReturn');par['group_id']='test';
|
||||
#101.132.127.1:19092
|
||||
|
||||
'''
|
||||
par['server']='101.132.127.1:19092 ';par['topic']=('alg-online-tasks','alg-offline-tasks','alg-task-results');par['group_id']='test';
|
||||
|
||||
par['kafka']='mintors/kafka'
|
||||
par['modelJson']='conf/model.json'
|
||||
'''
|
||||
masterFile="conf/master.json"
|
||||
assert os.path.exists(masterFile)
|
||||
with open(masterFile,'r') as fp:
|
||||
data=json.load(fp)
|
||||
par=data['par']
|
||||
print(par)
|
||||
detector(par)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,571 @@
|
|||
import numpy as np
|
||||
import time,ast,copy
|
||||
from flask import request, Flask,jsonify
|
||||
import base64,cv2,os,sys,json
|
||||
sys.path.extend(['../yolov5'])
|
||||
#from Send_tranfer import b64encode_function,JsonSend,name_dic,nameID_dic,getLogFileFp
|
||||
from segutils.segmodel import SegModel,get_largest_contours
|
||||
from models.experimental import attempt_load
|
||||
from utils.datasets import LoadStreams, LoadImages
|
||||
from utils.torch_utils import select_device, load_classifier, time_synchronized
|
||||
from queRiver import get_labelnames,get_label_arrays,post_process_,save_problem_images,time_str
|
||||
import subprocess as sp
|
||||
import matplotlib.pyplot as plt
|
||||
import torch,random,string
|
||||
import multiprocessing
|
||||
from multiprocessing import Process,Queue
|
||||
import traceback
|
||||
from kafka import KafkaProducer, KafkaConsumer,TopicPartition
|
||||
from kafka.errors import kafka_errors
|
||||
|
||||
#torch.multiprocessing.set_start_method('spawn')
|
||||
import utilsK
|
||||
from utilsK.GPUtils import *
|
||||
from utilsK.masterUtils import *
|
||||
from utilsK.sendUtils import create_status_msg,update_json
|
||||
|
||||
#from utilsK.modelEval import onlineModelProcess
|
||||
import random,string
|
||||
from Send_tranfer_oss import msg_dict_on,msg_dict_off
|
||||
import pykafka
|
||||
from pykafka import KafkaClient
|
||||
process_id=0
|
||||
|
||||
def onlineModelProcess(parIn ):
|
||||
DEBUG=False
|
||||
streamName = parIn['streamName']
|
||||
childCallback=parIn['callback']
|
||||
outStrList={}
|
||||
#try:
|
||||
for wan in ['test']:
|
||||
jsonfile=parIn['modelJson']
|
||||
with open(jsonfile,'r') as fp:
|
||||
parAll = json.load(fp)
|
||||
|
||||
Detweights=parAll['gpu_process']['det_weights']
|
||||
seg_nclass = parAll['gpu_process']['seg_nclass']
|
||||
Segweights = parAll['gpu_process']['seg_weights']
|
||||
videoSave = parAll['AI_video_save']
|
||||
imageTxtFile = parAll['imageTxtFile']
|
||||
taskId,msgId = streamName.split('-')[1:3]
|
||||
|
||||
inSource,outSource=parIn['inSource'],parIn['outSource']
|
||||
|
||||
##构建日志文件
|
||||
if outSource != 'NO':
|
||||
logdir = parAll['logChildProcessOnline']
|
||||
waitingTime=parAll['StreamWaitingTime']
|
||||
else:
|
||||
logdir = parAll['logChildProcessOffline']
|
||||
waitingTime=5
|
||||
|
||||
fp_log=create_logFile(logdir=logdir)
|
||||
kafka_par=parIn['kafka_par']
|
||||
producer = KafkaProducer(bootstrap_servers=kafka_par['server'],value_serializer=lambda v: v.encode('utf-8'),metadata_max_age_ms=120000)
|
||||
|
||||
####要先检查视频的有效性
|
||||
###开始的时候,如果在线任务没有流,要发送的心跳消息,msg_h,
|
||||
msg_h= copy.deepcopy(msg_dict_off);
|
||||
msg_h['status']='waiting';msg_h['msg_id']=msgId
|
||||
|
||||
|
||||
if outSource == 'NO':
|
||||
msg_h['type']=1
|
||||
Stream_ok= get_fps_rtmp(inSource,video=True)
|
||||
else:
|
||||
msg_h['type']=2
|
||||
|
||||
msg_h_d = json.dumps(msg_h, ensure_ascii=False)
|
||||
outStrList['success']= '%s waiting stream or video, send heartbeat: taskId:%s msgId:%s send:%s'%('-'*20,taskId, msgId,msg_h);
|
||||
outStrList['failure']='#######kafka ERROR waiting stream or video, send heartbeat'
|
||||
outStrList['Refailure']='##############kafka ERROR waiting stream or video, Re-send heartbeat'
|
||||
Stream_ok=check_stream(inSource,producer,kafka_par,msg_h_d,outStrList,fp_log ,timeMs=waitingTime)
|
||||
|
||||
if Stream_ok:###发送开始信号
|
||||
msg_h['status']='running'
|
||||
msg_h_d = json.dumps(msg_h, ensure_ascii=False)
|
||||
|
||||
outStrList['success']= '%s informing stream/video is ok, taskId:%s msgId:%s send:%s'%('-'*20,taskId, msgId,msg_h);
|
||||
outStrList['failure']='#######kafka ERROR ,when informing stream/video is ok'
|
||||
outStrList['Refailure']='##############kafka ERROR, when re-informing stream/video is ok'
|
||||
|
||||
send_kafka(producer,kafka_par,msg_h_d,outStrList,fp_log );
|
||||
|
||||
else:
|
||||
####检测离线视频是否有效,无效要报错
|
||||
outstr='############# offline vedio or live stream Error:%s #################'%(inSource)
|
||||
outstr=wrtiteLog(fp_log,outstr);print( outstr);
|
||||
|
||||
msg_h['error']=str(1001);msg_h['status']='failed';
|
||||
msg_h_d = json.dumps(msg_h, ensure_ascii=False);
|
||||
outStrList['success']= '%s informing invaid video or stream success : taskId:%s msgId:%s send:%s'%('-'*20,taskId, msgId,msg_h);
|
||||
outStrList['failure']='#######kafka ERROR, when informing invaid video or stream'
|
||||
outStrList['Refailure']='##############kafka ERROR,when re-informing invaid video or stream'
|
||||
send_kafka(producer,kafka_par,msg_h_d,outStrList,fp_log );
|
||||
childCallback.send(' offline vedio or live stream Error')
|
||||
continue
|
||||
|
||||
|
||||
|
||||
if (inSource.endswith('.MP4')) or (inSource.endswith('.mp4')):
|
||||
fps,outW,outH,totalcnt=get_fps_rtmp(inSource,video=True)[0:4]
|
||||
else:
|
||||
fps,outW,outH,totalcnt=get_fps_rtmp(inSource,video=False)[0:4]
|
||||
fps = int(fps+0.5)
|
||||
if outSource != 'NO':
|
||||
command=['ffmpeg','-y','-f', 'rawvideo','-vcodec','rawvideo','-pix_fmt', 'bgr24',
|
||||
'-s', "{}x{}".format(outW,outH),# 图片分辨率
|
||||
'-r', str(fps),# 视频帧率
|
||||
'-i', '-','-c:v', 'libx264','-pix_fmt', 'yuv420p',
|
||||
'-f', 'flv',outSource
|
||||
]
|
||||
video_flag = videoSave['onLine']
|
||||
logdir = parAll['logChildProcessOnline']
|
||||
waitingTime=parAll['StreamWaitingTime']
|
||||
else:
|
||||
video_flag = videoSave['offLine'] ;logdir = parAll['logChildProcessOffline']
|
||||
waitingTime=5
|
||||
|
||||
fp_log=create_logFile(logdir=logdir)
|
||||
|
||||
|
||||
device = select_device(parIn['device'])
|
||||
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)
|
||||
|
||||
|
||||
|
||||
# 管道配置,其中用到管道
|
||||
if outSource !='NO' :
|
||||
ppipe = sp.Popen(command, stdin=sp.PIPE)
|
||||
|
||||
|
||||
##后处理参数
|
||||
par=parAll['post_process']
|
||||
conf_thres,iou_thres,classes=par['conf_thres'],par['iou_thres'],par['classes']
|
||||
outImaDir = par['outImaDir']
|
||||
outVideoDir = par['outVideoDir']
|
||||
labelnames=par['labelnames']
|
||||
rainbows=par['rainbows']
|
||||
fpsample = par['fpsample']
|
||||
names=get_labelnames(labelnames)
|
||||
label_arraylist = get_label_arrays(names,rainbows,outfontsize=40)
|
||||
|
||||
dataset = LoadStreams(inSource, img_size=640, stride=32)
|
||||
|
||||
|
||||
childCallback.send('####model load success####')
|
||||
if (outVideoDir!='NO') and video_flag:
|
||||
msg_id = streamName.split('-')[2]
|
||||
save_path = os.path.join(outVideoDir,msg_id+'.MP4')
|
||||
vid_writer = cv2.VideoWriter(save_path, cv2.VideoWriter_fourcc(*'mp4v'), fps, (outW,outH))
|
||||
|
||||
iframe = 0;post_results=[];time_beg=time.time()
|
||||
|
||||
t00=time.time()
|
||||
time_kafka0=time.time()
|
||||
for path, img, im0s, vid_cap in dataset:
|
||||
|
||||
t0= time_synchronized()
|
||||
if not path:
|
||||
EndUrl='%s/%s_frame-9999-9999_type-结束_9999999999999999_s-%s_AI.jpg'%(outImaDir,time_str(),streamName)
|
||||
EndUrl = EndUrl.replace(' ','-').replace(':','-')
|
||||
img_end=np.zeros((100,100),dtype=np.uint8);cv2.imwrite(EndUrl,img_end)
|
||||
if imageTxtFile:
|
||||
EndUrl_txt = EndUrl.replace('.jpg','.txt')
|
||||
fp_t=open(EndUrl_txt,'w');fp_t.write(EndUrl+'\n');fp_t.close()
|
||||
|
||||
EndUrl='%s/%s_frame-9999-9999_type-结束_9999999999999999_s-%s_OR.jpg'%(outImaDir,time_str(),streamName)
|
||||
EndUrl = EndUrl.replace(' ','-').replace(':','-')
|
||||
ret = cv2.imwrite(EndUrl,img_end)
|
||||
if imageTxtFile:
|
||||
EndUrl_txt = EndUrl.replace('.jpg','.txt')
|
||||
fp_t=open(EndUrl_txt,'w');fp_t.write(EndUrl+'\n');fp_t.close()
|
||||
|
||||
#print(EndUrl,ret)
|
||||
childCallback.send('####strem ends####')
|
||||
if (outVideoDir!='NO') and video_flag:
|
||||
vid_writer.release()
|
||||
break###断流或者到终点
|
||||
|
||||
if outSource == 'NO':###如果不推流,则显示进度条
|
||||
view_bar(iframe,totalcnt,time_beg ,parIn['process_uid'] )
|
||||
|
||||
###直播和离线都是1分钟发一次消息。直播发
|
||||
time_kafka1 = time.time()
|
||||
if time_kafka1 - time_kafka0 >60:
|
||||
time_kafka0 = time_kafka1
|
||||
###发送状态信息waiting
|
||||
msg = copy.deepcopy(msg_dict_off);
|
||||
msg['msg_id']= msgId; msg
|
||||
if outSource == 'NO':
|
||||
msg['progressbar']= '%.4f'%(iframe*1.0/totalcnt)
|
||||
msg['type']=1
|
||||
else:
|
||||
msg['progressbarOn']= str(iframe)
|
||||
msg['type']=2
|
||||
|
||||
msg = json.dumps(msg, ensure_ascii=False)
|
||||
'''
|
||||
try:
|
||||
record_metadata = producer.send(kafka_par['topic'], msg).get()
|
||||
outstr='%s processing send progressbar or heartBeat to kafka: taskId:%s msgId:%s send:%s'%('-'*20,taskId, msgId,msg);
|
||||
wrtiteLog(fp_log,outstr);print( outstr);
|
||||
except Exception as e:
|
||||
outstr='#######kafka ERROR when processing sending progressbar or heartBeat:, error: %s'%(str(e))
|
||||
wrtiteLog(fp_log,outstr);print( outstr);
|
||||
try:
|
||||
producer = KafkaProducer(bootstrap_servers=par['server'], value_serializer=lambda v: v.encode('utf-8')).get()
|
||||
future = producer.send(par['topic'][2], msg).get()
|
||||
except Exception as e:
|
||||
outstr='%s re-send progressbar or heartBeat kafka,processing video or stream: taskId:%s msgId:%s send:%s'%('-'*20,taskId, msgId,msg);
|
||||
wrtiteLog(fp_log,outstr);print( outstr);
|
||||
'''
|
||||
|
||||
|
||||
###发送状态信息waiting
|
||||
outStrList['success']= '%s processing send progressbar or heartBeat to kafka: taskId:%s msgId:%s send:%s'%('-'*20,taskId, msgId,msg);
|
||||
outStrList['failure']='#######kafka ERROR when processing sending progressbar or heartBeat'
|
||||
outStrList['Refailure']='%s re-send progressbar or heartBeat kafka,processing video or stream: taskId:%s msgId:%s send:%s'%('-'*20,taskId, msgId,msg);
|
||||
send_kafka(producer,kafka_par,msg,outStrList,fp_log );
|
||||
|
||||
|
||||
|
||||
time0=time.time()
|
||||
iframe +=1
|
||||
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
|
||||
|
||||
timeseg0 = time.time()
|
||||
seg_pred,segstr = segmodel.eval(im0s[0] )
|
||||
timeseg1 = time.time()
|
||||
|
||||
t1= time_synchronized()
|
||||
pred = model(img,augment=False)[0]
|
||||
time4 = time.time()
|
||||
datas = [path, img, im0s, vid_cap,pred,seg_pred,iframe]
|
||||
|
||||
p_result,timeOut = post_process_(datas,conf_thres, iou_thres,names,label_arraylist,rainbows,iframe)
|
||||
t2= time_synchronized()
|
||||
|
||||
#print('###line138:',timeOut,outSource,outVideoDir)
|
||||
##每隔 fpsample帧处理一次,如果有问题就保存图片
|
||||
if (iframe % fpsample == 0) and (len(post_results)>0) :
|
||||
parImage=save_problem_images(post_results,iframe,names,streamName=streamName,outImaDir='problems/images_tmp',imageTxtFile=imageTxtFile)
|
||||
post_results=[]
|
||||
|
||||
if len(p_result[2] )>0: ##
|
||||
post_results.append(p_result)
|
||||
t3= time_synchronized()
|
||||
image_array = p_result[1]
|
||||
if outSource!='NO':
|
||||
ppipe.stdin.write(image_array.tobytes())
|
||||
|
||||
if (outVideoDir!='NO') and video_flag:
|
||||
ret = vid_writer.write(image_array)
|
||||
t4= time_synchronized()
|
||||
|
||||
timestr2 = time.strftime("%Y-%m-%d-%H-%M-%S", time.localtime())
|
||||
if iframe%100==0:
|
||||
outstr='%s,,read:%.1f ms,copy:%.1f, infer:%.1f ms, detinfer:%.1f ms,draw:%.1f ms, save:%.1f ms total:%.1f ms \n'%(timestr2,(t0 - t00)*1000,(timeseg0-t0)*1000, (t1 - timeseg0)*1000,(t2-t1)*1000, (t3 - t2)*1000,(t4-t3)*1000, (t4-t00)*1000)
|
||||
wrtiteLog(fp_log,outstr);
|
||||
#print(outstr)
|
||||
t00 = t4;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
##模型加载之类的错误
|
||||
#except Exception as e:
|
||||
|
||||
# print(time.strftime("%Y-%m-%d %H:%M:%S ", time.localtime()) ,'*'*20,'###line177 ERROR:',e)
|
||||
# childCallback.send(e) #将异常通过管道送出
|
||||
|
||||
|
||||
def lauch_process(gpuid,inSource,outSource,taskId,msgId,modelJson,kafka_par):
|
||||
|
||||
if outSource=='NO':
|
||||
streamName='off-%s-%s'%(taskId,msgId)
|
||||
else:
|
||||
streamName='live-%s-%s'%(taskId,msgId)
|
||||
dataPar ={
|
||||
'imgData':'',
|
||||
'imgName':'testW',
|
||||
'streamName':streamName,
|
||||
'taskId':taskId,
|
||||
'msgId':msgId,
|
||||
'device':str(gpuid),
|
||||
'modelJson':modelJson,
|
||||
'kafka_par':kafka_par,
|
||||
}
|
||||
#dataPar['inSource'] = 'http://images.5gai.taauav.com/video/8bc32984dd893930dabb2856eb92b4d1.mp4';dataPar['outSource'] = None
|
||||
dataPar['inSource'] = inSource;dataPar['outSource'] = outSource
|
||||
process_uid=''.join(random.sample(string.ascii_letters + string.digits, 16));dataPar['process_uid']=process_uid
|
||||
parent_conn, child_conn = multiprocessing.Pipe();dataPar['callback']=child_conn
|
||||
gpuProcess=Process(target=onlineModelProcess,name='process:%s'%( process_uid ),args=(dataPar,))
|
||||
gpuProcess.start()
|
||||
#print(dir(gpuProcess))
|
||||
#child_return = parent_conn.recv()
|
||||
#timestr2=time.strftime("%Y-%m-%d %H:%M:%S ", time.localtime())
|
||||
#print(timestr2,'-'*20,'progress:%s ,msgId:%s , taskId:%s return:'%(process_uid,msgId,taskId),child_return)
|
||||
|
||||
return gpuProcess
|
||||
|
||||
|
||||
msg_dict_offline = {
|
||||
|
||||
"biz_id":"hehuzhang",
|
||||
"mod_id":"ai",
|
||||
"msg_id":'bb'+''.join(random.sample(string.ascii_letters ,30) ) ,
|
||||
"offering_id":"http://vod.play.t-aaron.com/customerTrans/c49a2c620795d124f2ae4b10197b8d0e/303b7a58-17f3ef4494e-0004-f90c-f2c-7ec68.mp4",
|
||||
"offering_type":"mp4",
|
||||
"results_base_dir": "XJRW202203171535"+str(random.randint(10,99)),
|
||||
|
||||
'outSource':'NO'
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
def detector(par):
|
||||
####初始化信息列表
|
||||
consumer = KafkaConsumer(bootstrap_servers=par['server'],client_id='AI_server',group_id=par['group_id'],auto_offset_reset='earliest')
|
||||
|
||||
|
||||
consumer.subscribe( par['topic'][0:2])
|
||||
'''
|
||||
client = KafkaClient(hosts=par['server'])
|
||||
consumer_pys=[]
|
||||
for topic_name in par['topic'][0:2]:
|
||||
consumer_pys.append(client.topics[ topic_name ].get_simple_consumer(consumer_group=par['group_id'],timeout=30))
|
||||
|
||||
'''
|
||||
|
||||
kafka_par ={ 'server':par['server'],'topic':par['topic'][2] }
|
||||
producer = KafkaProducer(
|
||||
bootstrap_servers=par['server'],#tencent yun
|
||||
value_serializer=lambda v: v.encode('utf-8'),
|
||||
metadata_max_age_ms=120000)
|
||||
|
||||
taskStatus={}
|
||||
taskStatus['onLine'] = Queue(100)
|
||||
taskStatus['offLine']= Queue(100)
|
||||
taskStatus['pidInfos']= {}
|
||||
|
||||
fp_log=create_logFile(logdir=par['logDir'])
|
||||
wrtiteLog(fp_log,'###########masster starts in line222######\n')
|
||||
|
||||
timeSleep=1
|
||||
|
||||
#taskStatus['pidInfos'][31897]={'gpuProcess':'onlineProcess','type':'onLine'}
|
||||
|
||||
|
||||
time0=time.time()
|
||||
time0_kafQuery=time.time()
|
||||
time0_taskQuery=time.time()
|
||||
time0_sleep=time.time()
|
||||
time_interval=10; outStrList={}
|
||||
while True:###每隔timeSleep秒,轮询一次
|
||||
#for isleep in range(1):
|
||||
'''
|
||||
##1-读取kafka,更新任务类别
|
||||
try:
|
||||
|
||||
msgs = getAllRecords(consumer,par['topic'])
|
||||
except Exception as e:
|
||||
outstr='%s kafka connecting error:%s '%('#'*20,e)
|
||||
outstr=wrtiteLog(fp_log,outstr);print( outstr);
|
||||
time.sleep(timeSleep)
|
||||
continue
|
||||
#if get_whether_gpuProcess():
|
||||
|
||||
time0_kafQuery,printFlag = check_time_interval(time0_kafQuery,time_interval)
|
||||
if printFlag:
|
||||
outstr_kafka=' ##### kafka Left %d records####'%(len(msgs));
|
||||
outstr_kafka=wrtiteLog(fp_log,outstr_kafka)
|
||||
|
||||
'''
|
||||
|
||||
for ii,msg in enumerate(consumer):
|
||||
#for ii,msg in enumerate(msgs):
|
||||
##读取消息
|
||||
try:
|
||||
|
||||
taskInfos = eval(msg.value.decode('utf-8') )
|
||||
|
||||
except:
|
||||
|
||||
outstr='%s msg format error,value:%s,offset:%d partition:%s topic:%s'%('#'*20,msg.value,msg.offset,msg.topic,msg.topic)
|
||||
continue
|
||||
|
||||
if msg.topic == par['topic'][0]: ##
|
||||
|
||||
taskInfos['inSource']= taskInfos['pull_channel'];
|
||||
taskInfos['outSource']= get_push_address(taskInfos['push_channel']) ;
|
||||
|
||||
taskStatus['onLine'].put( taskInfos )
|
||||
save_message(par['kafka'],taskInfos)
|
||||
|
||||
###发送状态信息waiting
|
||||
msg = create_status_msg(msg_dict_on,taskInfos,sts='waiting')
|
||||
outStrList['success']= '%s read from kafka online task and back to kafka: taskId:%s msgId:%s send:%s'%('-'*20,taskInfos['results_base_dir'], taskInfos['msg_id'],msg)
|
||||
outStrList['failure']='#######kafka ERROR when read from kafka online task and back to kafka'
|
||||
outStrList['Refailure']='##############kafka ERROR when read from kafka online task and resend back to kafka:'
|
||||
send_kafka(producer,kafka_par,msg,outStrList,fp_log );
|
||||
|
||||
else:
|
||||
|
||||
taskInfos['inSource']= taskInfos['offering_id'];
|
||||
taskInfos['outSource']= 'NO'
|
||||
|
||||
taskStatus['offLine'].put( taskInfos )
|
||||
save_message(par['kafka'],taskInfos)
|
||||
|
||||
###发送状态信息waiting
|
||||
msg = create_status_msg(msg_dict_off,taskInfos,sts='waiting')
|
||||
|
||||
|
||||
outStrList['success']= '%s read from kafka offline task and back to kafka: taskId:%s msgId:%s send:%s'%('-'*20,taskInfos['results_base_dir'], taskInfos['msg_id'],msg)
|
||||
outStrList['failure']='#######kkafka ERROR when read from kafka offline task and back to kafka:,'
|
||||
outStrList['Refailure']='##############kafka ERROR when read from kafka offline task and resend back to kafka:'
|
||||
send_kafka(producer,kafka_par,msg,outStrList,fp_log );
|
||||
|
||||
|
||||
|
||||
time0_taskQuery,printFlag = check_time_interval(time0_taskQuery,time_interval)
|
||||
outstr_task= ' task queue onLine cnt:%d offLine:%d'%(taskStatus['onLine'].qsize(), taskStatus['offLine'].qsize())
|
||||
|
||||
##2-更新显卡信息
|
||||
gpuStatus = getGPUInfos()
|
||||
|
||||
##3-优先考虑在线任务
|
||||
if not taskStatus['onLine'].empty():
|
||||
###3.1-先判断有没有空闲显卡:
|
||||
cuda = get_available_gpu(gpuStatus)
|
||||
###获取在线任务信息,并执行,lauch process
|
||||
taskInfos = taskStatus['onLine'].get()
|
||||
|
||||
print('################396',cuda)
|
||||
if cuda: ###3.1.1 -有空余显卡
|
||||
#lauch process
|
||||
|
||||
msg= copy.deepcopy(msg_dict_on);
|
||||
|
||||
gpuProcess=lauch_process(cuda,taskInfos['inSource'],taskInfos['outSource'],taskInfos['results_base_dir'],taskInfos['msg_id'],par['modelJson'],kafka_par)
|
||||
|
||||
taskStatus['pidInfos'][gpuProcess.pid] = {'gpuProcess':gpuProcess,'type':'onLine','taskInfos':taskInfos}
|
||||
|
||||
|
||||
else:###3.1.2-没有显卡
|
||||
##判断有没有显卡上面都是离线进程的
|
||||
cuda_pid = get_potential_gpu(gpuStatus,taskStatus['pidInfos'])
|
||||
|
||||
if cuda_pid:#3.1.2.1 - ##如果有可以杀死的进程
|
||||
cuda = cuda_pid['cuda']
|
||||
pids = cuda_pid['pids']
|
||||
##kill 离线进程,并更新离线任务表
|
||||
cnt_off_0 = taskStatus['offLine'].qsize()
|
||||
for pid in pids:
|
||||
##kill 离线进程
|
||||
taskStatus['pidInfos'][pid]['gpuProcess'].kill()
|
||||
##更新离线任务表
|
||||
taskStatus['offLine'].put( taskStatus['pidInfos'][pid]['taskInfos'] )
|
||||
taskInfos_off=taskStatus['pidInfos'][pid]['taskInfos']
|
||||
|
||||
##发送离线数据,说明状态变成waiting
|
||||
msg= msg_dict_off;
|
||||
msg=update_json(taskInfos_off,msg,offkeys=["msg_id","biz_id" ,"mod_id"] )
|
||||
msg['results'][0]['original_url']=taskInfos_off['inSource']
|
||||
msg['results'][0]['sign_url']=get_boradcast_address(taskInfos_off['outSource'])
|
||||
msg['status']='waiting'
|
||||
msg = json.dumps(msg, ensure_ascii=False)
|
||||
|
||||
outStrList['success']= '%s start online task after kill offline tasks and back to kafka: pid:%d taskId:%s msgId:%s send:%s'%('-'*20,gpuProcess.pid,taskInfos_off['results_base_dir'], taskInfos_off['msg_id'],msg)
|
||||
outStrList['failure']='#######kafka ERROR when start online task after kill offline tasks and back to kafka'
|
||||
outStrList['Refailure']='##############kkafka ERROR when start online task after kill offline tasks and back to kafka'
|
||||
send_kafka(producer,kafka_par,msg,outStrList,fp_log );
|
||||
|
||||
|
||||
cnt_off_1 = taskStatus['offLine'].qsize()
|
||||
outstr='%s before killing process, offtask cnt:%d ,after killing, offtask cnt:%d %s'%('-'*20 ,cnt_off_0,cnt_off_1,'*'*20)
|
||||
outstr=wrtiteLog(fp_log,outstr);print( outstr);
|
||||
gpuProcess=lauch_process(cuda,taskInfos['inSource'],taskInfos['outSource'],taskInfos['results_base_dir'],taskInfos['msg_id'],par['modelJson'],kafka_par)
|
||||
|
||||
|
||||
###更新pidinfos,update pidInfos
|
||||
taskStatus['pidInfos'][gpuProcess.pid] = {'gpuProcess':gpuProcess,'type':'onLine','taskInfos':taskInfos}
|
||||
|
||||
|
||||
|
||||
else:
|
||||
outstr='######No available GPUs for onLine####'
|
||||
outstr=wrtiteLog(fp_log,outstr);print( outstr);
|
||||
##4-更新显卡信息
|
||||
gpuStatus = getGPUInfos()
|
||||
##5-考虑离线任务
|
||||
if not taskStatus['offLine'].empty():
|
||||
cudaArrange= arrange_offlineProcess(gpuStatus,taskStatus['pidInfos'],modelMemory=1500)
|
||||
outstr='###line342 IN OFF LINE TASKS available cudas:%s'%(cudaArrange)
|
||||
outstr=wrtiteLog(fp_log,outstr);print( outstr);
|
||||
for cuda in cudaArrange:
|
||||
if not taskStatus['offLine'].empty():
|
||||
taskInfos = taskStatus['offLine'].get()
|
||||
|
||||
|
||||
|
||||
gpuProcess=lauch_process(cuda,taskInfos['inSource'],taskInfos['outSource'],taskInfos['results_base_dir'],taskInfos['msg_id'],par['modelJson'],kafka_par)
|
||||
taskStatus['pidInfos'][gpuProcess.pid] = {'gpuProcess':gpuProcess,'type':'offLine','taskInfos':taskInfos}
|
||||
|
||||
|
||||
|
||||
|
||||
if get_whether_gpuProcess():
|
||||
time0_sleep,printFlag = check_time_interval(time0_sleep,time_interval)
|
||||
if printFlag:
|
||||
timestr2=time.strftime("%Y-%m-%d %H:%M:%S ", time.localtime())
|
||||
outstr= timestr2 + '*'*20 +'sleep '+'*'*20;
|
||||
outstr=wrtiteLog(fp_log,outstr);print( outstr);
|
||||
outstr_task=wrtiteLog(fp_log,outstr_task);print( outstr_task);
|
||||
|
||||
time.sleep(timeSleep)
|
||||
print('########sleep 1s #####')
|
||||
print('########Program End#####')
|
||||
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
par={};
|
||||
###topic0--在线,topic1--离线
|
||||
|
||||
#par['server']='212.129.223.66:9092';par['topic']=('thsw','thsw2','testReturn');par['group_id']='test';
|
||||
#101.132.127.1:19092
|
||||
|
||||
'''
|
||||
par['server']='101.132.127.1:19092 ';par['topic']=('alg-online-tasks','alg-offline-tasks','alg-task-results');par['group_id']='test';
|
||||
|
||||
par['kafka']='mintors/kafka'
|
||||
par['modelJson']='conf/model.json'
|
||||
'''
|
||||
masterFile="conf/master.json"
|
||||
assert os.path.exists(masterFile)
|
||||
with open(masterFile,'r') as fp:
|
||||
data=json.load(fp)
|
||||
par=data['par']
|
||||
print(par)
|
||||
detector(par)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1 @@
|
|||
rtmp://demoplay.yunhengzhizao.cn/live/THSA_HD5M 1935
|
||||
|
|
@ -0,0 +1,76 @@
|
|||
|
||||
import cv2
|
||||
import base64
|
||||
import io,os,sys
|
||||
sys.path.append('/home/thsw2/WJ/src/yolov5/utils')
|
||||
from get_offline_url import update_websource_offAndLive
|
||||
import requests
|
||||
import time,json
|
||||
import string,random
|
||||
|
||||
|
||||
def SendPost(txtSource):
|
||||
|
||||
api = 'http://212.129.223.66:8888/detector'
|
||||
filename='THWangJin'
|
||||
for info in txtSource:
|
||||
|
||||
input_ ={
|
||||
'imgData':'',
|
||||
'imgName':filename
|
||||
}
|
||||
if 'live' in info['name']:
|
||||
input_['outSource'] = "rtmp://127.0.0.1:%s/live/test"%(info['port'])
|
||||
else:
|
||||
input_['outSource'] = None
|
||||
input_['inSource'] = info['url']
|
||||
input_['streamName'] = info['name']
|
||||
|
||||
time0=time.time()
|
||||
response=requests.post(api,json=input_).json()
|
||||
time1=time.time()
|
||||
print('###source_query:',response,'time:%.3f s'%(time1-time0))
|
||||
if 'live' in info['name']:
|
||||
print('#####process online video stream######')
|
||||
break
|
||||
|
||||
|
||||
|
||||
def getLogFp(pollLogFile):
|
||||
#print(pollLogFile)
|
||||
#print(os.path.pardir(pollLogFile))
|
||||
if not os.path.exists(pollLogFile):
|
||||
os.makedirs(os.path.dirname(pollLogFile),exist_ok=True)
|
||||
|
||||
fp_log = open(pollLogFile,'w')
|
||||
else:
|
||||
fp_log = open(pollLogFile,'a+')
|
||||
return fp_log
|
||||
|
||||
if __name__=='__main__':
|
||||
|
||||
##建立日志文件
|
||||
pollLogFile='logs/poll/poll.txt'
|
||||
fp_log = getLogFp(pollLogFile)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
platform_query_url='http://47.96.182.154:9051/api/suanfa/getPlatformInfo'
|
||||
sourceFile='/home/thsw2/WJ/src/yolov5/config/source.txt'
|
||||
offlineFile='/home/thsw2/WJ/src/yolov5/mintors/offlines/doneCodes.txt'
|
||||
|
||||
txtSource=update_websource_offAndLive(platform_query_url,sourceFile,offlineFile)
|
||||
|
||||
txtSource=[
|
||||
#{'url': 'rtmp://demoplay.yunhengzhizao.cn/live/THSA_HD5M', 'port': '1935', 'name': 'live-THSAHD5M'}]
|
||||
|
||||
{'url': 'http://images.5gai.taauav.com/video/DJI_20220111115516_0001_ZBJ.MP4', 'port': '1935', 'name': 'off-202202190001'},
|
||||
{'url': 'http://images.5gai.taauav.com/video/8bc32984dd893930dabb2856eb92b4d1.mp4', 'port': '1935', 'name': 'off-202202190002'},
|
||||
{'url': 'http://images.5gai.taauav.com/video/DJI_20220110145546_0003_W.MP4', 'port': '1935', 'name': 'off-202202190002'}
|
||||
]
|
||||
|
||||
print(txtSource)
|
||||
SendPost(txtSource)
|
||||
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
import multiprocessing
|
||||
|
||||
def heavy_load_func(N, child_conn):
|
||||
'''function do heavy computing'''
|
||||
|
||||
try:
|
||||
|
||||
#do_some_heavy_computing
|
||||
return_value=99
|
||||
fp=open('wangjin.txt','r')
|
||||
fp.close()
|
||||
child_conn.send(return_value) #return something
|
||||
|
||||
except Exception as e:
|
||||
child_conn.send(e) #将异常通过管道送出
|
||||
|
||||
|
||||
if __name__=='__main__':
|
||||
'''main function'''
|
||||
try:
|
||||
parent_conn, child_conn = multiprocessing.Pipe()
|
||||
child_process = multiprocessing.Process(target=heavy_load_func, args=(10, child_conn))
|
||||
child_process.start()
|
||||
#child_process.join()
|
||||
child_return = parent_conn.recv()
|
||||
|
||||
print('#####main try:',child_return,type(child_return),dir(child_return),child_return.args)
|
||||
print(str( child_return ))
|
||||
except Exception as e:
|
||||
print('####main exception:',e)
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
{
|
||||
|
||||
"gpu_process":{"det_weights":"../yolov5/weights/best_5classes.pt","seg_nclass":2,"seg_weights": "../yolov5/weights/segmentation/BiSeNet/checkpoint.pth" },
|
||||
|
||||
"post_process":{ "name":"post_process","conf_thres":0.25,"iou_thres":0.45,"classes":5,"labelnames":"../yolov5/config/labelnames.json","fpsample":240,"debug":false , "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]],"outImaDir":"problems/images_tmp","outVideoDir":"problems/videos_save" },
|
||||
|
||||
"push_process":{ "OutVideoW":1920, "OutVideoH":1080 },
|
||||
"AI_video_save": {"onLine":false,"offLine":true },
|
||||
"imageTxtFile":true,
|
||||
"logChildProcessOffline":"logs/logChildProcess/offline",
|
||||
"logChildProcessOnline":"logs/logChildProcess/online",
|
||||
"StreamWaitingTime":240,
|
||||
"StreamRecoveringTime":180
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
{
|
||||
|
||||
"gpu_process":{"det_weights":"../weights/yolov5/class9/weights/best.pt","seg_nclass":2,"seg_weights": "../yolov5/weights/segmentation/BiSeNet/checkpoint.pth" },
|
||||
|
||||
"post_process":{ "name":"post_process","conf_thres":0.25,"iou_thres":0.45,"classes":5,"labelnames":"../weights/yolov5/class9/labelnames.json","fpsample":240,"debug":false , "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]],"outImaDir":"problems/images_tmp","outVideoDir":"problems/videos_save" },
|
||||
|
||||
"push_process":{ "OutVideoW":1920, "OutVideoH":1080 },
|
||||
"AI_video_save": {"onLine":false,"offLine":true },
|
||||
"imageTxtFile":true,
|
||||
"logChildProcessOffline":"logs/logChildProcess/offline",
|
||||
"logChildProcessOnline":"logs/logChildProcess/online",
|
||||
"StreamWaitingTime":240,
|
||||
"StreamRecoveringTime":180
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"101":"video uploading failure",
|
||||
"102":"Stream or video ERROR",
|
||||
"":
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"par":{
|
||||
"server1":"212.129.223.66:19092",
|
||||
"server2":"101.132.127.1:19092",
|
||||
"server":"192.168.11.242:9092",
|
||||
"topic": ["dsp-alg-online-tasks","dsp-alg-offline-tasks","dsp-alg-task-results"],
|
||||
"group_id":"testWw",
|
||||
"kafka":"mintors/kafka",
|
||||
"modelJson":"conf/model.json",
|
||||
"logDir":"logs/master",
|
||||
"StreamWaitingTime":240,
|
||||
"logPrintInterval":60
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
|
||||
"gpu_process":{"det_weights":"weights/yolov5/class5/best_5classes.pt","seg_nclass":2,"seg_weights": "weights/BiSeNet/checkpoint.pth" },
|
||||
|
||||
"post_process":{ "name":"post_process","conf_thres":0.25,"iou_thres":0.45,"classes":5,"labelnames":"weights/yolov5/class5/labelnames.json","fpsample":240,"debug":false , "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]],"outImaDir":"problems/images_tmp","outVideoDir":"problems/videos_save" },
|
||||
|
||||
"push_process":{ "OutVideoW":1920, "OutVideoH":1080 },
|
||||
"AI_video_save": {"onLine":false,"offLine":true },
|
||||
"imageTxtFile":true,
|
||||
"logChildProcessOffline":"logs/logChildProcess/offline",
|
||||
"logChildProcessOnline":"logs/logChildProcess/online",
|
||||
"TaskStatusQueryUrl":"http://192.168.11.241:1011/api/web/serviceInst",
|
||||
"StreamWaitingTime":240,
|
||||
"StreamRecoveringTime":600
|
||||
|
||||
|
||||
}
|
||||
Binary file not shown.
|
|
@ -0,0 +1,20 @@
|
|||
{
|
||||
"indir":"problems/images_tmp",
|
||||
"outdir":"problems/images_save",
|
||||
"jsonDir" : "mintors/kafka/",
|
||||
"hearBeatTimeMs":30,
|
||||
"logdir":"logs/send",
|
||||
"videoBakDir":"problems/videos_save",
|
||||
"ossPar":{"Epoint":"http://oss-cn-shanghai.aliyuncs.com",
|
||||
"AId":"LTAI5tSJ62TLMUb4SZuf285A",
|
||||
"ASt":"MWYynm30filZ7x0HqSHlU3pdLVNeI7",
|
||||
"bucketName":"ta-tech-image"
|
||||
},
|
||||
"vodPar":{
|
||||
"AId":"LTAI5tE7KWN9fsuGU7DyfYF4",
|
||||
"ASt":"yPPCyfsqWgrTuoz5H4sisY0COclx8E"
|
||||
},
|
||||
"kafkaPar":{"boostServer":["192.168.11.242:9092"] ,"boostServer2":["101.132.127.1:19092"], "boostServer3":["212.129.223.66:19092"] ,"topic":"dsp-alg-task-results"},
|
||||
"labelnamesFile":"weights/yolov5/class5/labelnames.json"
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
import traceback
|
||||
from kafka import KafkaProducer, KafkaConsumer,TopicPartition
|
||||
from kafka.errors import kafka_errors
|
||||
import json
|
||||
def get_left_cnt(consumer,topic):
|
||||
partitions = [TopicPartition(topic, p) for p in consumer.partitions_for_topic(topic)]
|
||||
|
||||
# total
|
||||
toff = consumer.end_offsets(partitions)
|
||||
toff = [(key.partition, toff[key]) for key in toff.keys()]
|
||||
toff.sort()
|
||||
|
||||
# current
|
||||
coff = [(x.partition, consumer.committed(x)) for x in partitions]
|
||||
coff.sort()
|
||||
|
||||
# cal sum and left
|
||||
toff_sum = sum([x[1] for x in toff])
|
||||
cur_sum = sum([x[1] for x in coff if x[1] is not None])
|
||||
left_sum = toff_sum - cur_sum
|
||||
|
||||
return left_sum
|
||||
def getAllRecords(consumer,topics):
|
||||
leftCnt = 0
|
||||
for topic in topics[0:2]:
|
||||
leftCnt+=get_left_cnt(consumer,topic)
|
||||
out = []
|
||||
if leftCnt == 0:
|
||||
return []
|
||||
for ii,msg in enumerate(consumer):
|
||||
consumer.commit()
|
||||
out.append(msg)
|
||||
if ii== (leftCnt-1):
|
||||
break###断流或者到终点
|
||||
return out
|
||||
def detector(par):
|
||||
consumer = KafkaConsumer(
|
||||
bootstrap_servers=par['server'],
|
||||
group_id=par['group_id'],
|
||||
auto_offset_reset='earliest',
|
||||
#auto_offset_reset='latest',
|
||||
#isolation_level = 'read_committed',
|
||||
#enable_auto_commit=True
|
||||
)
|
||||
consumer.subscribe( par['topic'][0:2])
|
||||
print( ' Start kafka ')
|
||||
#msgs = getAllRecords(consumer,par['topic'])
|
||||
#print( 'getover cnt',len(msgs))
|
||||
#for ii,msg in enumerate(msgs):
|
||||
for ii,msg in enumerate(consumer):
|
||||
print(msg)
|
||||
try:
|
||||
print('##'*10,ii)
|
||||
taskInfos = eval(msg.value.decode('utf-8'))
|
||||
print(taskInfos )
|
||||
except:
|
||||
print('**'*10,'wrong',ii)
|
||||
print(msg.value.decode('utf-8'))
|
||||
if __name__ == '__main__':
|
||||
par={};
|
||||
###topic0--在线,topic1--离线
|
||||
|
||||
#par['server']='212.129.223.66:9092';par['topic']=('thsw','thsw2','testReturn');par['group_id']='test';
|
||||
|
||||
par['server']='192.168.11.242:9092';par['topic']=('alg-online-tasks', 'alg-task-results','alg-offline-tasks');par['group_id']='testww2';
|
||||
#par['server']='101.132.127.1:19092';par['topic']=('alg-online-tasks','alg-task-results','alg-offline-tasks');par['group_id']='testW11';
|
||||
par['kafka']='mintors/kafka'
|
||||
detector(par)
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
mkdir logs/send/ -p
|
||||
mkdir logs/logChildProcess logs/master
|
||||
mkdir logs/logChildProcess/offline logs/logChildProcess/online
|
||||
touch logs/logChildProcess/offline/gpuprocess.log
|
||||
touch logs/logChildProcess/online/gpuprocess.log
|
||||
touch logs/master/detector.log
|
||||
touch logs/send/SendPics.log
|
||||
mkdir mintors/kafka -p
|
||||
mkdir problems/images_save -p
|
||||
mkdir problems/images_tmp problems/videos_save
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
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.
|
|
@ -0,0 +1,405 @@
|
|||
# YOLOv5 common modules
|
||||
|
||||
import math
|
||||
from copy import copy
|
||||
from pathlib import Path
|
||||
|
||||
import numpy as np
|
||||
import pandas as pd
|
||||
import requests
|
||||
import torch
|
||||
import torch.nn as nn
|
||||
from PIL import Image
|
||||
from torch.cuda import amp
|
||||
|
||||
from utils.datasets import letterbox
|
||||
from utils.general import non_max_suppression, make_divisible, scale_coords, increment_path, xyxy2xywh
|
||||
from utils.plots import color_list, plot_one_box
|
||||
from utils.torch_utils import time_synchronized
|
||||
|
||||
import warnings
|
||||
|
||||
class SPPF(nn.Module):
|
||||
# Spatial Pyramid Pooling - Fast (SPPF) layer for YOLOv5 by Glenn Jocher
|
||||
def __init__(self, c1, c2, k=5): # equivalent to SPP(k=(5, 9, 13))
|
||||
super().__init__()
|
||||
c_ = c1 // 2 # hidden channels
|
||||
self.cv1 = Conv(c1, c_, 1, 1)
|
||||
self.cv2 = Conv(c_ * 4, c2, 1, 1)
|
||||
self.m = nn.MaxPool2d(kernel_size=k, stride=1, padding=k // 2)
|
||||
|
||||
def forward(self, x):
|
||||
x = self.cv1(x)
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter('ignore') # suppress torch 1.9.0 max_pool2d() warning
|
||||
y1 = self.m(x)
|
||||
y2 = self.m(y1)
|
||||
return self.cv2(torch.cat([x, y1, y2, self.m(y2)], 1))
|
||||
|
||||
|
||||
def autopad(k, p=None): # kernel, padding
|
||||
# Pad to 'same'
|
||||
if p is None:
|
||||
p = k // 2 if isinstance(k, int) else [x // 2 for x in k] # auto-pad
|
||||
return p
|
||||
|
||||
|
||||
def DWConv(c1, c2, k=1, s=1, act=True):
|
||||
# Depthwise convolution
|
||||
return Conv(c1, c2, k, s, g=math.gcd(c1, c2), act=act)
|
||||
|
||||
|
||||
class Conv(nn.Module):
|
||||
# Standard convolution
|
||||
def __init__(self, c1, c2, k=1, s=1, p=None, g=1, act=True): # ch_in, ch_out, kernel, stride, padding, groups
|
||||
super(Conv, self).__init__()
|
||||
self.conv = nn.Conv2d(c1, c2, k, s, autopad(k, p), groups=g, bias=False)
|
||||
self.bn = nn.BatchNorm2d(c2)
|
||||
self.act = nn.SiLU() if act is True else (act if isinstance(act, nn.Module) else nn.Identity())
|
||||
|
||||
def forward(self, x):
|
||||
return self.act(self.bn(self.conv(x)))
|
||||
|
||||
def fuseforward(self, x):
|
||||
return self.act(self.conv(x))
|
||||
|
||||
|
||||
class TransformerLayer(nn.Module):
|
||||
# Transformer layer https://arxiv.org/abs/2010.11929 (LayerNorm layers removed for better performance)
|
||||
def __init__(self, c, num_heads):
|
||||
super().__init__()
|
||||
self.q = nn.Linear(c, c, bias=False)
|
||||
self.k = nn.Linear(c, c, bias=False)
|
||||
self.v = nn.Linear(c, c, bias=False)
|
||||
self.ma = nn.MultiheadAttention(embed_dim=c, num_heads=num_heads)
|
||||
self.fc1 = nn.Linear(c, c, bias=False)
|
||||
self.fc2 = nn.Linear(c, c, bias=False)
|
||||
|
||||
def forward(self, x):
|
||||
x = self.ma(self.q(x), self.k(x), self.v(x))[0] + x
|
||||
x = self.fc2(self.fc1(x)) + x
|
||||
return x
|
||||
|
||||
|
||||
class TransformerBlock(nn.Module):
|
||||
# Vision Transformer https://arxiv.org/abs/2010.11929
|
||||
def __init__(self, c1, c2, num_heads, num_layers):
|
||||
super().__init__()
|
||||
self.conv = None
|
||||
if c1 != c2:
|
||||
self.conv = Conv(c1, c2)
|
||||
self.linear = nn.Linear(c2, c2) # learnable position embedding
|
||||
self.tr = nn.Sequential(*[TransformerLayer(c2, num_heads) for _ in range(num_layers)])
|
||||
self.c2 = c2
|
||||
|
||||
def forward(self, x):
|
||||
if self.conv is not None:
|
||||
x = self.conv(x)
|
||||
b, _, w, h = x.shape
|
||||
p = x.flatten(2)
|
||||
p = p.unsqueeze(0)
|
||||
p = p.transpose(0, 3)
|
||||
p = p.squeeze(3)
|
||||
e = self.linear(p)
|
||||
x = p + e
|
||||
|
||||
x = self.tr(x)
|
||||
x = x.unsqueeze(3)
|
||||
x = x.transpose(0, 3)
|
||||
x = x.reshape(b, self.c2, w, h)
|
||||
return x
|
||||
|
||||
|
||||
class Bottleneck(nn.Module):
|
||||
# Standard bottleneck
|
||||
def __init__(self, c1, c2, shortcut=True, g=1, e=0.5): # ch_in, ch_out, shortcut, groups, expansion
|
||||
super(Bottleneck, self).__init__()
|
||||
c_ = int(c2 * e) # hidden channels
|
||||
self.cv1 = Conv(c1, c_, 1, 1)
|
||||
self.cv2 = Conv(c_, c2, 3, 1, g=g)
|
||||
self.add = shortcut and c1 == c2
|
||||
|
||||
def forward(self, x):
|
||||
return x + self.cv2(self.cv1(x)) if self.add else self.cv2(self.cv1(x))
|
||||
|
||||
|
||||
class BottleneckCSP(nn.Module):
|
||||
# CSP Bottleneck https://github.com/WongKinYiu/CrossStagePartialNetworks
|
||||
def __init__(self, c1, c2, n=1, shortcut=True, g=1, e=0.5): # ch_in, ch_out, number, shortcut, groups, expansion
|
||||
super(BottleneckCSP, self).__init__()
|
||||
c_ = int(c2 * e) # hidden channels
|
||||
self.cv1 = Conv(c1, c_, 1, 1)
|
||||
self.cv2 = nn.Conv2d(c1, c_, 1, 1, bias=False)
|
||||
self.cv3 = nn.Conv2d(c_, c_, 1, 1, bias=False)
|
||||
self.cv4 = Conv(2 * c_, c2, 1, 1)
|
||||
self.bn = nn.BatchNorm2d(2 * c_) # applied to cat(cv2, cv3)
|
||||
self.act = nn.LeakyReLU(0.1, inplace=True)
|
||||
self.m = nn.Sequential(*[Bottleneck(c_, c_, shortcut, g, e=1.0) for _ in range(n)])
|
||||
|
||||
def forward(self, x):
|
||||
y1 = self.cv3(self.m(self.cv1(x)))
|
||||
y2 = self.cv2(x)
|
||||
return self.cv4(self.act(self.bn(torch.cat((y1, y2), dim=1))))
|
||||
|
||||
|
||||
class C3(nn.Module):
|
||||
# CSP Bottleneck with 3 convolutions
|
||||
def __init__(self, c1, c2, n=1, shortcut=True, g=1, e=0.5): # ch_in, ch_out, number, shortcut, groups, expansion
|
||||
super(C3, self).__init__()
|
||||
c_ = int(c2 * e) # hidden channels
|
||||
self.cv1 = Conv(c1, c_, 1, 1)
|
||||
self.cv2 = Conv(c1, c_, 1, 1)
|
||||
self.cv3 = Conv(2 * c_, c2, 1) # act=FReLU(c2)
|
||||
self.m = nn.Sequential(*[Bottleneck(c_, c_, shortcut, g, e=1.0) for _ in range(n)])
|
||||
# self.m = nn.Sequential(*[CrossConv(c_, c_, 3, 1, g, 1.0, shortcut) for _ in range(n)])
|
||||
|
||||
def forward(self, x):
|
||||
return self.cv3(torch.cat((self.m(self.cv1(x)), self.cv2(x)), dim=1))
|
||||
|
||||
|
||||
class C3TR(C3):
|
||||
# C3 module with TransformerBlock()
|
||||
def __init__(self, c1, c2, n=1, shortcut=True, g=1, e=0.5):
|
||||
super().__init__(c1, c2, n, shortcut, g, e)
|
||||
c_ = int(c2 * e)
|
||||
self.m = TransformerBlock(c_, c_, 4, n)
|
||||
|
||||
|
||||
class SPP(nn.Module):
|
||||
# Spatial pyramid pooling layer used in YOLOv3-SPP
|
||||
def __init__(self, c1, c2, k=(5, 9, 13)):
|
||||
super(SPP, self).__init__()
|
||||
c_ = c1 // 2 # hidden channels
|
||||
self.cv1 = Conv(c1, c_, 1, 1)
|
||||
self.cv2 = Conv(c_ * (len(k) + 1), c2, 1, 1)
|
||||
self.m = nn.ModuleList([nn.MaxPool2d(kernel_size=x, stride=1, padding=x // 2) for x in k])
|
||||
|
||||
def forward(self, x):
|
||||
x = self.cv1(x)
|
||||
return self.cv2(torch.cat([x] + [m(x) for m in self.m], 1))
|
||||
|
||||
|
||||
class Focus(nn.Module):
|
||||
# Focus wh information into c-space
|
||||
def __init__(self, c1, c2, k=1, s=1, p=None, g=1, act=True): # ch_in, ch_out, kernel, stride, padding, groups
|
||||
super(Focus, self).__init__()
|
||||
self.conv = Conv(c1 * 4, c2, k, s, p, g, act)
|
||||
# self.contract = Contract(gain=2)
|
||||
|
||||
def forward(self, x): # x(b,c,w,h) -> y(b,4c,w/2,h/2)
|
||||
return self.conv(torch.cat([x[..., ::2, ::2], x[..., 1::2, ::2], x[..., ::2, 1::2], x[..., 1::2, 1::2]], 1))
|
||||
# return self.conv(self.contract(x))
|
||||
|
||||
|
||||
class Contract(nn.Module):
|
||||
# Contract width-height into channels, i.e. x(1,64,80,80) to x(1,256,40,40)
|
||||
def __init__(self, gain=2):
|
||||
super().__init__()
|
||||
self.gain = gain
|
||||
|
||||
def forward(self, x):
|
||||
N, C, H, W = x.size() # assert (H / s == 0) and (W / s == 0), 'Indivisible gain'
|
||||
s = self.gain
|
||||
x = x.view(N, C, H // s, s, W // s, s) # x(1,64,40,2,40,2)
|
||||
x = x.permute(0, 3, 5, 1, 2, 4).contiguous() # x(1,2,2,64,40,40)
|
||||
return x.view(N, C * s * s, H // s, W // s) # x(1,256,40,40)
|
||||
|
||||
|
||||
class Expand(nn.Module):
|
||||
# Expand channels into width-height, i.e. x(1,64,80,80) to x(1,16,160,160)
|
||||
def __init__(self, gain=2):
|
||||
super().__init__()
|
||||
self.gain = gain
|
||||
|
||||
def forward(self, x):
|
||||
N, C, H, W = x.size() # assert C / s ** 2 == 0, 'Indivisible gain'
|
||||
s = self.gain
|
||||
x = x.view(N, s, s, C // s ** 2, H, W) # x(1,2,2,16,80,80)
|
||||
x = x.permute(0, 3, 4, 1, 5, 2).contiguous() # x(1,16,80,2,80,2)
|
||||
return x.view(N, C // s ** 2, H * s, W * s) # x(1,16,160,160)
|
||||
|
||||
|
||||
class Concat(nn.Module):
|
||||
# Concatenate a list of tensors along dimension
|
||||
def __init__(self, dimension=1):
|
||||
super(Concat, self).__init__()
|
||||
self.d = dimension
|
||||
|
||||
def forward(self, x):
|
||||
return torch.cat(x, self.d)
|
||||
|
||||
|
||||
class NMS(nn.Module):
|
||||
# Non-Maximum Suppression (NMS) module
|
||||
conf = 0.25 # confidence threshold
|
||||
iou = 0.45 # IoU threshold
|
||||
classes = None # (optional list) filter by class
|
||||
|
||||
def __init__(self):
|
||||
super(NMS, self).__init__()
|
||||
|
||||
def forward(self, x):
|
||||
return non_max_suppression(x[0], conf_thres=self.conf, iou_thres=self.iou, classes=self.classes)
|
||||
|
||||
|
||||
class autoShape(nn.Module):
|
||||
# input-robust model wrapper for passing cv2/np/PIL/torch inputs. Includes preprocessing, inference and NMS
|
||||
conf = 0.25 # NMS confidence threshold
|
||||
iou = 0.45 # NMS IoU threshold
|
||||
classes = None # (optional list) filter by class
|
||||
|
||||
def __init__(self, model):
|
||||
super(autoShape, self).__init__()
|
||||
self.model = model.eval()
|
||||
|
||||
def autoshape(self):
|
||||
print('autoShape already enabled, skipping... ') # model already converted to model.autoshape()
|
||||
return self
|
||||
|
||||
@torch.no_grad()
|
||||
def forward(self, imgs, size=640, augment=False, profile=False):
|
||||
# Inference from various sources. For height=640, width=1280, RGB images example inputs are:
|
||||
# filename: imgs = 'data/images/zidane.jpg'
|
||||
# URI: = 'https://github.com/ultralytics/yolov5/releases/download/v1.0/zidane.jpg'
|
||||
# OpenCV: = cv2.imread('image.jpg')[:,:,::-1] # HWC BGR to RGB x(640,1280,3)
|
||||
# PIL: = Image.open('image.jpg') # HWC x(640,1280,3)
|
||||
# numpy: = np.zeros((640,1280,3)) # HWC
|
||||
# torch: = torch.zeros(16,3,320,640) # BCHW (scaled to size=640, 0-1 values)
|
||||
# multiple: = [Image.open('image1.jpg'), Image.open('image2.jpg'), ...] # list of images
|
||||
|
||||
t = [time_synchronized()]
|
||||
p = next(self.model.parameters()) # for device and type
|
||||
if isinstance(imgs, torch.Tensor): # torch
|
||||
with amp.autocast(enabled=p.device.type != 'cpu'):
|
||||
return self.model(imgs.to(p.device).type_as(p), augment, profile) # inference
|
||||
|
||||
# Pre-process
|
||||
n, imgs = (len(imgs), imgs) if isinstance(imgs, list) else (1, [imgs]) # number of images, list of images
|
||||
shape0, shape1, files = [], [], [] # image and inference shapes, filenames
|
||||
for i, im in enumerate(imgs):
|
||||
f = f'image{i}' # filename
|
||||
if isinstance(im, str): # filename or uri
|
||||
im, f = np.asarray(Image.open(requests.get(im, stream=True).raw if im.startswith('http') else im)), im
|
||||
elif isinstance(im, Image.Image): # PIL Image
|
||||
im, f = np.asarray(im), getattr(im, 'filename', f) or f
|
||||
files.append(Path(f).with_suffix('.jpg').name)
|
||||
if im.shape[0] < 5: # image in CHW
|
||||
im = im.transpose((1, 2, 0)) # reverse dataloader .transpose(2, 0, 1)
|
||||
im = im[:, :, :3] if im.ndim == 3 else np.tile(im[:, :, None], 3) # enforce 3ch input
|
||||
s = im.shape[:2] # HWC
|
||||
shape0.append(s) # image shape
|
||||
g = (size / max(s)) # gain
|
||||
shape1.append([y * g for y in s])
|
||||
imgs[i] = im if im.data.contiguous else np.ascontiguousarray(im) # update
|
||||
shape1 = [make_divisible(x, int(self.stride.max())) for x in np.stack(shape1, 0).max(0)] # inference shape
|
||||
x = [letterbox(im, new_shape=shape1, auto=False)[0] for im in imgs] # pad
|
||||
x = np.stack(x, 0) if n > 1 else x[0][None] # stack
|
||||
x = np.ascontiguousarray(x.transpose((0, 3, 1, 2))) # BHWC to BCHW
|
||||
x = torch.from_numpy(x).to(p.device).type_as(p) / 255. # uint8 to fp16/32
|
||||
t.append(time_synchronized())
|
||||
|
||||
with amp.autocast(enabled=p.device.type != 'cpu'):
|
||||
# Inference
|
||||
y = self.model(x, augment, profile)[0] # forward
|
||||
t.append(time_synchronized())
|
||||
|
||||
# Post-process
|
||||
y = non_max_suppression(y, conf_thres=self.conf, iou_thres=self.iou, classes=self.classes) # NMS
|
||||
for i in range(n):
|
||||
scale_coords(shape1, y[i][:, :4], shape0[i])
|
||||
|
||||
t.append(time_synchronized())
|
||||
return Detections(imgs, y, files, t, self.names, x.shape)
|
||||
|
||||
|
||||
class Detections:
|
||||
# detections class for YOLOv5 inference results
|
||||
def __init__(self, imgs, pred, files, times=None, names=None, shape=None):
|
||||
super(Detections, self).__init__()
|
||||
d = pred[0].device # device
|
||||
gn = [torch.tensor([*[im.shape[i] for i in [1, 0, 1, 0]], 1., 1.], device=d) for im in imgs] # normalizations
|
||||
self.imgs = imgs # list of images as numpy arrays
|
||||
self.pred = pred # list of tensors pred[0] = (xyxy, conf, cls)
|
||||
self.names = names # class names
|
||||
self.files = files # image filenames
|
||||
self.xyxy = pred # xyxy pixels
|
||||
self.xywh = [xyxy2xywh(x) for x in pred] # xywh pixels
|
||||
self.xyxyn = [x / g for x, g in zip(self.xyxy, gn)] # xyxy normalized
|
||||
self.xywhn = [x / g for x, g in zip(self.xywh, gn)] # xywh normalized
|
||||
self.n = len(self.pred) # number of images (batch size)
|
||||
self.t = tuple((times[i + 1] - times[i]) * 1000 / self.n for i in range(3)) # timestamps (ms)
|
||||
self.s = shape # inference BCHW shape
|
||||
|
||||
def display(self, pprint=False, show=False, save=False, render=False, save_dir=''):
|
||||
colors = color_list()
|
||||
for i, (img, pred) in enumerate(zip(self.imgs, self.pred)):
|
||||
str = f'image {i + 1}/{len(self.pred)}: {img.shape[0]}x{img.shape[1]} '
|
||||
if pred is not None:
|
||||
for c in pred[:, -1].unique():
|
||||
n = (pred[:, -1] == c).sum() # detections per class
|
||||
str += f"{n} {self.names[int(c)]}{'s' * (n > 1)}, " # add to string
|
||||
if show or save or render:
|
||||
for *box, conf, cls in pred: # xyxy, confidence, class
|
||||
label = f'{self.names[int(cls)]} {conf:.2f}'
|
||||
plot_one_box(box, img, label=label, color=colors[int(cls) % 10])
|
||||
img = Image.fromarray(img.astype(np.uint8)) if isinstance(img, np.ndarray) else img # from np
|
||||
if pprint:
|
||||
print(str.rstrip(', '))
|
||||
if show:
|
||||
img.show(self.files[i]) # show
|
||||
if save:
|
||||
f = self.files[i]
|
||||
img.save(Path(save_dir) / f) # save
|
||||
print(f"{'Saved' * (i == 0)} {f}", end=',' if i < self.n - 1 else f' to {save_dir}\n')
|
||||
if render:
|
||||
self.imgs[i] = np.asarray(img)
|
||||
|
||||
def print(self):
|
||||
self.display(pprint=True) # print results
|
||||
print(f'Speed: %.1fms pre-process, %.1fms inference, %.1fms NMS per image at shape {tuple(self.s)}' % self.t)
|
||||
|
||||
def show(self):
|
||||
self.display(show=True) # show results
|
||||
|
||||
def save(self, save_dir='runs/hub/exp'):
|
||||
save_dir = increment_path(save_dir, exist_ok=save_dir != 'runs/hub/exp') # increment save_dir
|
||||
Path(save_dir).mkdir(parents=True, exist_ok=True)
|
||||
self.display(save=True, save_dir=save_dir) # save results
|
||||
|
||||
def render(self):
|
||||
self.display(render=True) # render results
|
||||
return self.imgs
|
||||
|
||||
def pandas(self):
|
||||
# return detections as pandas DataFrames, i.e. print(results.pandas().xyxy[0])
|
||||
new = copy(self) # return copy
|
||||
ca = 'xmin', 'ymin', 'xmax', 'ymax', 'confidence', 'class', 'name' # xyxy columns
|
||||
cb = 'xcenter', 'ycenter', 'width', 'height', 'confidence', 'class', 'name' # xywh columns
|
||||
for k, c in zip(['xyxy', 'xyxyn', 'xywh', 'xywhn'], [ca, ca, cb, cb]):
|
||||
a = [[x[:5] + [int(x[5]), self.names[int(x[5])]] for x in x.tolist()] for x in getattr(self, k)] # update
|
||||
setattr(new, k, [pd.DataFrame(x, columns=c) for x in a])
|
||||
return new
|
||||
|
||||
def tolist(self):
|
||||
# return a list of Detections objects, i.e. 'for result in results.tolist():'
|
||||
x = [Detections([self.imgs[i]], [self.pred[i]], self.names, self.s) for i in range(self.n)]
|
||||
for d in x:
|
||||
for k in ['imgs', 'pred', 'xyxy', 'xyxyn', 'xywh', 'xywhn']:
|
||||
setattr(d, k, getattr(d, k)[0]) # pop out of list
|
||||
return x
|
||||
|
||||
def __len__(self):
|
||||
return self.n
|
||||
|
||||
|
||||
class Classify(nn.Module):
|
||||
# Classification head, i.e. x(b,c1,20,20) to x(b,c2)
|
||||
def __init__(self, c1, c2, k=1, s=1, p=None, g=1): # ch_in, ch_out, kernel, stride, padding, groups
|
||||
super(Classify, self).__init__()
|
||||
self.aap = nn.AdaptiveAvgPool2d(1) # to x(b,c1,1,1)
|
||||
self.conv = nn.Conv2d(c1, c2, k, s, autopad(k, p), groups=g) # to x(b,c2,1,1)
|
||||
self.flat = nn.Flatten()
|
||||
|
||||
def forward(self, x):
|
||||
z = torch.cat([self.aap(y) for y in (x if isinstance(x, list) else [x])], 1) # cat if list
|
||||
return self.flat(self.conv(z)) # flatten to x(b,c2)
|
||||
|
|
@ -0,0 +1,134 @@
|
|||
# YOLOv5 experimental modules
|
||||
|
||||
import numpy as np
|
||||
import torch
|
||||
import torch.nn as nn
|
||||
|
||||
from models.common import Conv, DWConv
|
||||
from utils.google_utils import attempt_download
|
||||
|
||||
|
||||
class CrossConv(nn.Module):
|
||||
# Cross Convolution Downsample
|
||||
def __init__(self, c1, c2, k=3, s=1, g=1, e=1.0, shortcut=False):
|
||||
# ch_in, ch_out, kernel, stride, groups, expansion, shortcut
|
||||
super(CrossConv, self).__init__()
|
||||
c_ = int(c2 * e) # hidden channels
|
||||
self.cv1 = Conv(c1, c_, (1, k), (1, s))
|
||||
self.cv2 = Conv(c_, c2, (k, 1), (s, 1), g=g)
|
||||
self.add = shortcut and c1 == c2
|
||||
|
||||
def forward(self, x):
|
||||
return x + self.cv2(self.cv1(x)) if self.add else self.cv2(self.cv1(x))
|
||||
|
||||
|
||||
class Sum(nn.Module):
|
||||
# Weighted sum of 2 or more layers https://arxiv.org/abs/1911.09070
|
||||
def __init__(self, n, weight=False): # n: number of inputs
|
||||
super(Sum, self).__init__()
|
||||
self.weight = weight # apply weights boolean
|
||||
self.iter = range(n - 1) # iter object
|
||||
if weight:
|
||||
self.w = nn.Parameter(-torch.arange(1., n) / 2, requires_grad=True) # layer weights
|
||||
|
||||
def forward(self, x):
|
||||
y = x[0] # no weight
|
||||
if self.weight:
|
||||
w = torch.sigmoid(self.w) * 2
|
||||
for i in self.iter:
|
||||
y = y + x[i + 1] * w[i]
|
||||
else:
|
||||
for i in self.iter:
|
||||
y = y + x[i + 1]
|
||||
return y
|
||||
|
||||
|
||||
class GhostConv(nn.Module):
|
||||
# Ghost Convolution https://github.com/huawei-noah/ghostnet
|
||||
def __init__(self, c1, c2, k=1, s=1, g=1, act=True): # ch_in, ch_out, kernel, stride, groups
|
||||
super(GhostConv, self).__init__()
|
||||
c_ = c2 // 2 # hidden channels
|
||||
self.cv1 = Conv(c1, c_, k, s, None, g, act)
|
||||
self.cv2 = Conv(c_, c_, 5, 1, None, c_, act)
|
||||
|
||||
def forward(self, x):
|
||||
y = self.cv1(x)
|
||||
return torch.cat([y, self.cv2(y)], 1)
|
||||
|
||||
|
||||
class GhostBottleneck(nn.Module):
|
||||
# Ghost Bottleneck https://github.com/huawei-noah/ghostnet
|
||||
def __init__(self, c1, c2, k=3, s=1): # ch_in, ch_out, kernel, stride
|
||||
super(GhostBottleneck, self).__init__()
|
||||
c_ = c2 // 2
|
||||
self.conv = nn.Sequential(GhostConv(c1, c_, 1, 1), # pw
|
||||
DWConv(c_, c_, k, s, act=False) if s == 2 else nn.Identity(), # dw
|
||||
GhostConv(c_, c2, 1, 1, act=False)) # pw-linear
|
||||
self.shortcut = nn.Sequential(DWConv(c1, c1, k, s, act=False),
|
||||
Conv(c1, c2, 1, 1, act=False)) if s == 2 else nn.Identity()
|
||||
|
||||
def forward(self, x):
|
||||
return self.conv(x) + self.shortcut(x)
|
||||
|
||||
|
||||
class MixConv2d(nn.Module):
|
||||
# Mixed Depthwise Conv https://arxiv.org/abs/1907.09595
|
||||
def __init__(self, c1, c2, k=(1, 3), s=1, equal_ch=True):
|
||||
super(MixConv2d, self).__init__()
|
||||
groups = len(k)
|
||||
if equal_ch: # equal c_ per group
|
||||
i = torch.linspace(0, groups - 1E-6, c2).floor() # c2 indices
|
||||
c_ = [(i == g).sum() for g in range(groups)] # intermediate channels
|
||||
else: # equal weight.numel() per group
|
||||
b = [c2] + [0] * groups
|
||||
a = np.eye(groups + 1, groups, k=-1)
|
||||
a -= np.roll(a, 1, axis=1)
|
||||
a *= np.array(k) ** 2
|
||||
a[0] = 1
|
||||
c_ = np.linalg.lstsq(a, b, rcond=None)[0].round() # solve for equal weight indices, ax = b
|
||||
|
||||
self.m = nn.ModuleList([nn.Conv2d(c1, int(c_[g]), k[g], s, k[g] // 2, bias=False) for g in range(groups)])
|
||||
self.bn = nn.BatchNorm2d(c2)
|
||||
self.act = nn.LeakyReLU(0.1, inplace=True)
|
||||
|
||||
def forward(self, x):
|
||||
return x + self.act(self.bn(torch.cat([m(x) for m in self.m], 1)))
|
||||
|
||||
|
||||
class Ensemble(nn.ModuleList):
|
||||
# Ensemble of models
|
||||
def __init__(self):
|
||||
super(Ensemble, self).__init__()
|
||||
|
||||
def forward(self, x, augment=False):
|
||||
y = []
|
||||
for module in self:
|
||||
y.append(module(x, augment)[0])
|
||||
# y = torch.stack(y).max(0)[0] # max ensemble
|
||||
# y = torch.stack(y).mean(0) # mean ensemble
|
||||
y = torch.cat(y, 1) # nms ensemble
|
||||
return y, None # inference, train output
|
||||
|
||||
|
||||
def attempt_load(weights, map_location=None):
|
||||
# Loads an ensemble of models weights=[a,b,c] or a single model weights=[a] or weights=a
|
||||
model = Ensemble()
|
||||
for w in weights if isinstance(weights, list) else [weights]:
|
||||
attempt_download(w)
|
||||
ckpt = torch.load(w, map_location=map_location) # load
|
||||
model.append(ckpt['ema' if ckpt.get('ema') else 'model'].float().fuse().eval()) # FP32 model
|
||||
|
||||
# Compatibility updates
|
||||
for m in model.modules():
|
||||
if type(m) in [nn.Hardswish, nn.LeakyReLU, nn.ReLU, nn.ReLU6, nn.SiLU]:
|
||||
m.inplace = True # pytorch 1.7.0 compatibility
|
||||
elif type(m) is Conv:
|
||||
m._non_persistent_buffers_set = set() # pytorch 1.6.0 compatibility
|
||||
|
||||
if len(model) == 1:
|
||||
return model[-1] # return model
|
||||
else:
|
||||
print('Ensemble created with %s\n' % weights)
|
||||
for k in ['names', 'stride']:
|
||||
setattr(model, k, getattr(model[-1], k))
|
||||
return model # return ensemble
|
||||
|
|
@ -0,0 +1,123 @@
|
|||
"""Exports a YOLOv5 *.pt model to ONNX and TorchScript formats
|
||||
|
||||
Usage:
|
||||
$ export PYTHONPATH="$PWD" && python models/export.py --weights yolov5s.pt --img 640 --batch 1
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import sys
|
||||
import time
|
||||
|
||||
sys.path.append('./') # to run '$ python *.py' files in subdirectories
|
||||
|
||||
import torch
|
||||
import torch.nn as nn
|
||||
|
||||
import models
|
||||
from models.experimental import attempt_load
|
||||
from utils.activations import Hardswish, SiLU
|
||||
from utils.general import colorstr, check_img_size, check_requirements, set_logging
|
||||
from utils.torch_utils import select_device
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('--weights', type=str, default='./yolov5s.pt', help='weights path')
|
||||
parser.add_argument('--img-size', nargs='+', type=int, default=[640, 640], help='image size') # height, width
|
||||
parser.add_argument('--batch-size', type=int, default=1, help='batch size')
|
||||
parser.add_argument('--grid', action='store_true', help='export Detect() layer grid')
|
||||
parser.add_argument('--device', default='cpu', help='cuda device, i.e. 0 or 0,1,2,3 or cpu')
|
||||
parser.add_argument('--dynamic', action='store_true', help='dynamic ONNX axes') # ONNX-only
|
||||
parser.add_argument('--simplify', action='store_true', help='simplify ONNX model') # ONNX-only
|
||||
opt = parser.parse_args()
|
||||
opt.img_size *= 2 if len(opt.img_size) == 1 else 1 # expand
|
||||
print(opt)
|
||||
set_logging()
|
||||
t = time.time()
|
||||
|
||||
# Load PyTorch model
|
||||
device = select_device(opt.device)
|
||||
model = attempt_load(opt.weights, map_location=device) # load FP32 model
|
||||
labels = model.names
|
||||
|
||||
# Checks
|
||||
gs = int(max(model.stride)) # grid size (max stride)
|
||||
opt.img_size = [check_img_size(x, gs) for x in opt.img_size] # verify img_size are gs-multiples
|
||||
|
||||
# Input
|
||||
img = torch.zeros(opt.batch_size, 3, *opt.img_size).to(device) # image size(1,3,320,192) iDetection
|
||||
|
||||
# Update model
|
||||
for k, m in model.named_modules():
|
||||
m._non_persistent_buffers_set = set() # pytorch 1.6.0 compatibility
|
||||
if isinstance(m, models.common.Conv): # assign export-friendly activations
|
||||
if isinstance(m.act, nn.Hardswish):
|
||||
m.act = Hardswish()
|
||||
elif isinstance(m.act, nn.SiLU):
|
||||
m.act = SiLU()
|
||||
# elif isinstance(m, models.yolo.Detect):
|
||||
# m.forward = m.forward_export # assign forward (optional)
|
||||
model.model[-1].export = not opt.grid # set Detect() layer grid export
|
||||
y = model(img) # dry run
|
||||
|
||||
# TorchScript export -----------------------------------------------------------------------------------------------
|
||||
prefix = colorstr('TorchScript:')
|
||||
try:
|
||||
print(f'\n{prefix} starting export with torch {torch.__version__}...')
|
||||
f = opt.weights.replace('.pt', '.torchscript.pt') # filename
|
||||
ts = torch.jit.trace(model, img, strict=False)
|
||||
ts.save(f)
|
||||
print(f'{prefix} export success, saved as {f}')
|
||||
except Exception as e:
|
||||
print(f'{prefix} export failure: {e}')
|
||||
|
||||
# ONNX export ------------------------------------------------------------------------------------------------------
|
||||
prefix = colorstr('ONNX:')
|
||||
try:
|
||||
import onnx
|
||||
|
||||
print(f'{prefix} starting export with onnx {onnx.__version__}...')
|
||||
f = opt.weights.replace('.pt', '.onnx') # filename
|
||||
torch.onnx.export(model, img, f, verbose=False, opset_version=12, input_names=['images'],
|
||||
output_names=['classes', 'boxes'] if y is None else ['output'],
|
||||
dynamic_axes={'images': {0: 'batch', 2: 'height', 3: 'width'}, # size(1,3,640,640)
|
||||
'output': {0: 'batch', 2: 'y', 3: 'x'}} if opt.dynamic else None)
|
||||
|
||||
# Checks
|
||||
model_onnx = onnx.load(f) # load onnx model
|
||||
onnx.checker.check_model(model_onnx) # check onnx model
|
||||
# print(onnx.helper.printable_graph(model_onnx.graph)) # print
|
||||
|
||||
# Simplify
|
||||
if opt.simplify:
|
||||
try:
|
||||
check_requirements(['onnx-simplifier'])
|
||||
import onnxsim
|
||||
|
||||
print(f'{prefix} simplifying with onnx-simplifier {onnxsim.__version__}...')
|
||||
model_onnx, check = onnxsim.simplify(model_onnx,
|
||||
dynamic_input_shape=opt.dynamic,
|
||||
input_shapes={'images': list(img.shape)} if opt.dynamic else None)
|
||||
assert check, 'assert check failed'
|
||||
onnx.save(model_onnx, f)
|
||||
except Exception as e:
|
||||
print(f'{prefix} simplifier failure: {e}')
|
||||
print(f'{prefix} export success, saved as {f}')
|
||||
except Exception as e:
|
||||
print(f'{prefix} export failure: {e}')
|
||||
|
||||
# CoreML export ----------------------------------------------------------------------------------------------------
|
||||
prefix = colorstr('CoreML:')
|
||||
try:
|
||||
import coremltools as ct
|
||||
|
||||
print(f'{prefix} starting export with coremltools {onnx.__version__}...')
|
||||
# convert model from torchscript and apply pixel scaling as per detect.py
|
||||
model = ct.convert(ts, inputs=[ct.ImageType(name='image', shape=img.shape, scale=1 / 255.0, bias=[0, 0, 0])])
|
||||
f = opt.weights.replace('.pt', '.mlmodel') # filename
|
||||
model.save(f)
|
||||
print(f'{prefix} export success, saved as {f}')
|
||||
except Exception as e:
|
||||
print(f'{prefix} export failure: {e}')
|
||||
|
||||
# Finish
|
||||
print(f'\nExport complete ({time.time() - t:.2f}s). Visualize with https://github.com/lutzroeder/netron.')
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
# Default YOLOv5 anchors for COCO data
|
||||
|
||||
|
||||
# P5 -------------------------------------------------------------------------------------------------------------------
|
||||
# P5-640:
|
||||
anchors_p5_640:
|
||||
- [ 10,13, 16,30, 33,23 ] # P3/8
|
||||
- [ 30,61, 62,45, 59,119 ] # P4/16
|
||||
- [ 116,90, 156,198, 373,326 ] # P5/32
|
||||
|
||||
|
||||
# P6 -------------------------------------------------------------------------------------------------------------------
|
||||
# P6-640: thr=0.25: 0.9964 BPR, 5.54 anchors past thr, n=12, img_size=640, metric_all=0.281/0.716-mean/best, past_thr=0.469-mean: 9,11, 21,19, 17,41, 43,32, 39,70, 86,64, 65,131, 134,130, 120,265, 282,180, 247,354, 512,387
|
||||
anchors_p6_640:
|
||||
- [ 9,11, 21,19, 17,41 ] # P3/8
|
||||
- [ 43,32, 39,70, 86,64 ] # P4/16
|
||||
- [ 65,131, 134,130, 120,265 ] # P5/32
|
||||
- [ 282,180, 247,354, 512,387 ] # P6/64
|
||||
|
||||
# P6-1280: thr=0.25: 0.9950 BPR, 5.55 anchors past thr, n=12, img_size=1280, metric_all=0.281/0.714-mean/best, past_thr=0.468-mean: 19,27, 44,40, 38,94, 96,68, 86,152, 180,137, 140,301, 303,264, 238,542, 436,615, 739,380, 925,792
|
||||
anchors_p6_1280:
|
||||
- [ 19,27, 44,40, 38,94 ] # P3/8
|
||||
- [ 96,68, 86,152, 180,137 ] # P4/16
|
||||
- [ 140,301, 303,264, 238,542 ] # P5/32
|
||||
- [ 436,615, 739,380, 925,792 ] # P6/64
|
||||
|
||||
# P6-1920: thr=0.25: 0.9950 BPR, 5.55 anchors past thr, n=12, img_size=1920, metric_all=0.281/0.714-mean/best, past_thr=0.468-mean: 28,41, 67,59, 57,141, 144,103, 129,227, 270,205, 209,452, 455,396, 358,812, 653,922, 1109,570, 1387,1187
|
||||
anchors_p6_1920:
|
||||
- [ 28,41, 67,59, 57,141 ] # P3/8
|
||||
- [ 144,103, 129,227, 270,205 ] # P4/16
|
||||
- [ 209,452, 455,396, 358,812 ] # P5/32
|
||||
- [ 653,922, 1109,570, 1387,1187 ] # P6/64
|
||||
|
||||
|
||||
# P7 -------------------------------------------------------------------------------------------------------------------
|
||||
# P7-640: thr=0.25: 0.9962 BPR, 6.76 anchors past thr, n=15, img_size=640, metric_all=0.275/0.733-mean/best, past_thr=0.466-mean: 11,11, 13,30, 29,20, 30,46, 61,38, 39,92, 78,80, 146,66, 79,163, 149,150, 321,143, 157,303, 257,402, 359,290, 524,372
|
||||
anchors_p7_640:
|
||||
- [ 11,11, 13,30, 29,20 ] # P3/8
|
||||
- [ 30,46, 61,38, 39,92 ] # P4/16
|
||||
- [ 78,80, 146,66, 79,163 ] # P5/32
|
||||
- [ 149,150, 321,143, 157,303 ] # P6/64
|
||||
- [ 257,402, 359,290, 524,372 ] # P7/128
|
||||
|
||||
# P7-1280: thr=0.25: 0.9968 BPR, 6.71 anchors past thr, n=15, img_size=1280, metric_all=0.273/0.732-mean/best, past_thr=0.463-mean: 19,22, 54,36, 32,77, 70,83, 138,71, 75,173, 165,159, 148,334, 375,151, 334,317, 251,626, 499,474, 750,326, 534,814, 1079,818
|
||||
anchors_p7_1280:
|
||||
- [ 19,22, 54,36, 32,77 ] # P3/8
|
||||
- [ 70,83, 138,71, 75,173 ] # P4/16
|
||||
- [ 165,159, 148,334, 375,151 ] # P5/32
|
||||
- [ 334,317, 251,626, 499,474 ] # P6/64
|
||||
- [ 750,326, 534,814, 1079,818 ] # P7/128
|
||||
|
||||
# P7-1920: thr=0.25: 0.9968 BPR, 6.71 anchors past thr, n=15, img_size=1920, metric_all=0.273/0.732-mean/best, past_thr=0.463-mean: 29,34, 81,55, 47,115, 105,124, 207,107, 113,259, 247,238, 222,500, 563,227, 501,476, 376,939, 749,711, 1126,489, 801,1222, 1618,1227
|
||||
anchors_p7_1920:
|
||||
- [ 29,34, 81,55, 47,115 ] # P3/8
|
||||
- [ 105,124, 207,107, 113,259 ] # P4/16
|
||||
- [ 247,238, 222,500, 563,227 ] # P5/32
|
||||
- [ 501,476, 376,939, 749,711 ] # P6/64
|
||||
- [ 1126,489, 801,1222, 1618,1227 ] # P7/128
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
# 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
|
||||
|
||||
# darknet53 backbone
|
||||
backbone:
|
||||
# [from, number, module, args]
|
||||
[[-1, 1, Conv, [32, 3, 1]], # 0
|
||||
[-1, 1, Conv, [64, 3, 2]], # 1-P1/2
|
||||
[-1, 1, Bottleneck, [64]],
|
||||
[-1, 1, Conv, [128, 3, 2]], # 3-P2/4
|
||||
[-1, 2, Bottleneck, [128]],
|
||||
[-1, 1, Conv, [256, 3, 2]], # 5-P3/8
|
||||
[-1, 8, Bottleneck, [256]],
|
||||
[-1, 1, Conv, [512, 3, 2]], # 7-P4/16
|
||||
[-1, 8, Bottleneck, [512]],
|
||||
[-1, 1, Conv, [1024, 3, 2]], # 9-P5/32
|
||||
[-1, 4, Bottleneck, [1024]], # 10
|
||||
]
|
||||
|
||||
# YOLOv3-SPP head
|
||||
head:
|
||||
[[-1, 1, Bottleneck, [1024, False]],
|
||||
[-1, 1, SPP, [512, [5, 9, 13]]],
|
||||
[-1, 1, Conv, [1024, 3, 1]],
|
||||
[-1, 1, Conv, [512, 1, 1]],
|
||||
[-1, 1, Conv, [1024, 3, 1]], # 15 (P5/32-large)
|
||||
|
||||
[-2, 1, Conv, [256, 1, 1]],
|
||||
[-1, 1, nn.Upsample, [None, 2, 'nearest']],
|
||||
[[-1, 8], 1, Concat, [1]], # cat backbone P4
|
||||
[-1, 1, Bottleneck, [512, False]],
|
||||
[-1, 1, Bottleneck, [512, False]],
|
||||
[-1, 1, Conv, [256, 1, 1]],
|
||||
[-1, 1, Conv, [512, 3, 1]], # 22 (P4/16-medium)
|
||||
|
||||
[-2, 1, Conv, [128, 1, 1]],
|
||||
[-1, 1, nn.Upsample, [None, 2, 'nearest']],
|
||||
[[-1, 6], 1, Concat, [1]], # cat backbone P3
|
||||
[-1, 1, Bottleneck, [256, False]],
|
||||
[-1, 2, Bottleneck, [256, False]], # 27 (P3/8-small)
|
||||
|
||||
[[27, 22, 15], 1, Detect, [nc, anchors]], # Detect(P3, P4, P5)
|
||||
]
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
# parameters
|
||||
nc: 80 # number of classes
|
||||
depth_multiple: 1.0 # model depth multiple
|
||||
width_multiple: 1.0 # layer channel multiple
|
||||
|
||||
# anchors
|
||||
anchors:
|
||||
- [10,14, 23,27, 37,58] # P4/16
|
||||
- [81,82, 135,169, 344,319] # P5/32
|
||||
|
||||
# YOLOv3-tiny backbone
|
||||
backbone:
|
||||
# [from, number, module, args]
|
||||
[[-1, 1, Conv, [16, 3, 1]], # 0
|
||||
[-1, 1, nn.MaxPool2d, [2, 2, 0]], # 1-P1/2
|
||||
[-1, 1, Conv, [32, 3, 1]],
|
||||
[-1, 1, nn.MaxPool2d, [2, 2, 0]], # 3-P2/4
|
||||
[-1, 1, Conv, [64, 3, 1]],
|
||||
[-1, 1, nn.MaxPool2d, [2, 2, 0]], # 5-P3/8
|
||||
[-1, 1, Conv, [128, 3, 1]],
|
||||
[-1, 1, nn.MaxPool2d, [2, 2, 0]], # 7-P4/16
|
||||
[-1, 1, Conv, [256, 3, 1]],
|
||||
[-1, 1, nn.MaxPool2d, [2, 2, 0]], # 9-P5/32
|
||||
[-1, 1, Conv, [512, 3, 1]],
|
||||
[-1, 1, nn.ZeroPad2d, [[0, 1, 0, 1]]], # 11
|
||||
[-1, 1, nn.MaxPool2d, [2, 1, 0]], # 12
|
||||
]
|
||||
|
||||
# YOLOv3-tiny head
|
||||
head:
|
||||
[[-1, 1, Conv, [1024, 3, 1]],
|
||||
[-1, 1, Conv, [256, 1, 1]],
|
||||
[-1, 1, Conv, [512, 3, 1]], # 15 (P5/32-large)
|
||||
|
||||
[-2, 1, Conv, [128, 1, 1]],
|
||||
[-1, 1, nn.Upsample, [None, 2, 'nearest']],
|
||||
[[-1, 8], 1, Concat, [1]], # cat backbone P4
|
||||
[-1, 1, Conv, [256, 3, 1]], # 19 (P4/16-medium)
|
||||
|
||||
[[19, 15], 1, Detect, [nc, anchors]], # Detect(P4, P5)
|
||||
]
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
# 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
|
||||
|
||||
# darknet53 backbone
|
||||
backbone:
|
||||
# [from, number, module, args]
|
||||
[[-1, 1, Conv, [32, 3, 1]], # 0
|
||||
[-1, 1, Conv, [64, 3, 2]], # 1-P1/2
|
||||
[-1, 1, Bottleneck, [64]],
|
||||
[-1, 1, Conv, [128, 3, 2]], # 3-P2/4
|
||||
[-1, 2, Bottleneck, [128]],
|
||||
[-1, 1, Conv, [256, 3, 2]], # 5-P3/8
|
||||
[-1, 8, Bottleneck, [256]],
|
||||
[-1, 1, Conv, [512, 3, 2]], # 7-P4/16
|
||||
[-1, 8, Bottleneck, [512]],
|
||||
[-1, 1, Conv, [1024, 3, 2]], # 9-P5/32
|
||||
[-1, 4, Bottleneck, [1024]], # 10
|
||||
]
|
||||
|
||||
# YOLOv3 head
|
||||
head:
|
||||
[[-1, 1, Bottleneck, [1024, False]],
|
||||
[-1, 1, Conv, [512, [1, 1]]],
|
||||
[-1, 1, Conv, [1024, 3, 1]],
|
||||
[-1, 1, Conv, [512, 1, 1]],
|
||||
[-1, 1, Conv, [1024, 3, 1]], # 15 (P5/32-large)
|
||||
|
||||
[-2, 1, Conv, [256, 1, 1]],
|
||||
[-1, 1, nn.Upsample, [None, 2, 'nearest']],
|
||||
[[-1, 8], 1, Concat, [1]], # cat backbone P4
|
||||
[-1, 1, Bottleneck, [512, False]],
|
||||
[-1, 1, Bottleneck, [512, False]],
|
||||
[-1, 1, Conv, [256, 1, 1]],
|
||||
[-1, 1, Conv, [512, 3, 1]], # 22 (P4/16-medium)
|
||||
|
||||
[-2, 1, Conv, [128, 1, 1]],
|
||||
[-1, 1, nn.Upsample, [None, 2, 'nearest']],
|
||||
[[-1, 6], 1, Concat, [1]], # cat backbone P3
|
||||
[-1, 1, Bottleneck, [256, False]],
|
||||
[-1, 2, Bottleneck, [256, False]], # 27 (P3/8-small)
|
||||
|
||||
[[27, 22, 15], 1, Detect, [nc, anchors]], # Detect(P3, P4, P5)
|
||||
]
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
# 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, Bottleneck, [128]],
|
||||
[-1, 1, Conv, [256, 3, 2]], # 3-P3/8
|
||||
[-1, 9, BottleneckCSP, [256]],
|
||||
[-1, 1, Conv, [512, 3, 2]], # 5-P4/16
|
||||
[-1, 9, BottleneckCSP, [512]],
|
||||
[-1, 1, Conv, [1024, 3, 2]], # 7-P5/32
|
||||
[-1, 1, SPP, [1024, [5, 9, 13]]],
|
||||
[-1, 6, BottleneckCSP, [1024]], # 9
|
||||
]
|
||||
|
||||
# YOLOv5 FPN head
|
||||
head:
|
||||
[[-1, 3, BottleneckCSP, [1024, False]], # 10 (P5/32-large)
|
||||
|
||||
[-1, 1, nn.Upsample, [None, 2, 'nearest']],
|
||||
[[-1, 6], 1, Concat, [1]], # cat backbone P4
|
||||
[-1, 1, Conv, [512, 1, 1]],
|
||||
[-1, 3, BottleneckCSP, [512, False]], # 14 (P4/16-medium)
|
||||
|
||||
[-1, 1, nn.Upsample, [None, 2, 'nearest']],
|
||||
[[-1, 4], 1, Concat, [1]], # cat backbone P3
|
||||
[-1, 1, Conv, [256, 1, 1]],
|
||||
[-1, 3, BottleneckCSP, [256, False]], # 18 (P3/8-small)
|
||||
|
||||
[[18, 14, 10], 1, Detect, [nc, anchors]], # Detect(P3, P4, P5)
|
||||
]
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
# parameters
|
||||
nc: 80 # number of classes
|
||||
depth_multiple: 1.0 # model depth multiple
|
||||
width_multiple: 1.0 # layer channel multiple
|
||||
|
||||
# anchors
|
||||
anchors: 3
|
||||
|
||||
# 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, [ 128, 1, 1 ] ],
|
||||
[ -1, 1, nn.Upsample, [ None, 2, 'nearest' ] ],
|
||||
[ [ -1, 2 ], 1, Concat, [ 1 ] ], # cat backbone P2
|
||||
[ -1, 1, C3, [ 128, False ] ], # 21 (P2/4-xsmall)
|
||||
|
||||
[ -1, 1, Conv, [ 128, 3, 2 ] ],
|
||||
[ [ -1, 18 ], 1, Concat, [ 1 ] ], # cat head P3
|
||||
[ -1, 3, C3, [ 256, False ] ], # 24 (P3/8-small)
|
||||
|
||||
[ -1, 1, Conv, [ 256, 3, 2 ] ],
|
||||
[ [ -1, 14 ], 1, Concat, [ 1 ] ], # cat head P4
|
||||
[ -1, 3, C3, [ 512, False ] ], # 27 (P4/16-medium)
|
||||
|
||||
[ -1, 1, Conv, [ 512, 3, 2 ] ],
|
||||
[ [ -1, 10 ], 1, Concat, [ 1 ] ], # cat head P5
|
||||
[ -1, 3, C3, [ 1024, False ] ], # 30 (P5/32-large)
|
||||
|
||||
[ [ 24, 27, 30 ], 1, Detect, [ nc, anchors ] ], # Detect(P3, P4, P5)
|
||||
]
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
# parameters
|
||||
nc: 80 # number of classes
|
||||
depth_multiple: 1.0 # model depth multiple
|
||||
width_multiple: 1.0 # layer channel multiple
|
||||
|
||||
# anchors
|
||||
anchors: 3
|
||||
|
||||
# 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, [ 768, 3, 2 ] ], # 7-P5/32
|
||||
[ -1, 3, C3, [ 768 ] ],
|
||||
[ -1, 1, Conv, [ 1024, 3, 2 ] ], # 9-P6/64
|
||||
[ -1, 1, SPP, [ 1024, [ 3, 5, 7 ] ] ],
|
||||
[ -1, 3, C3, [ 1024, False ] ], # 11
|
||||
]
|
||||
|
||||
# YOLOv5 head
|
||||
head:
|
||||
[ [ -1, 1, Conv, [ 768, 1, 1 ] ],
|
||||
[ -1, 1, nn.Upsample, [ None, 2, 'nearest' ] ],
|
||||
[ [ -1, 8 ], 1, Concat, [ 1 ] ], # cat backbone P5
|
||||
[ -1, 3, C3, [ 768, False ] ], # 15
|
||||
|
||||
[ -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 ] ], # 19
|
||||
|
||||
[ -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 ] ], # 23 (P3/8-small)
|
||||
|
||||
[ -1, 1, Conv, [ 256, 3, 2 ] ],
|
||||
[ [ -1, 20 ], 1, Concat, [ 1 ] ], # cat head P4
|
||||
[ -1, 3, C3, [ 512, False ] ], # 26 (P4/16-medium)
|
||||
|
||||
[ -1, 1, Conv, [ 512, 3, 2 ] ],
|
||||
[ [ -1, 16 ], 1, Concat, [ 1 ] ], # cat head P5
|
||||
[ -1, 3, C3, [ 768, False ] ], # 29 (P5/32-large)
|
||||
|
||||
[ -1, 1, Conv, [ 768, 3, 2 ] ],
|
||||
[ [ -1, 12 ], 1, Concat, [ 1 ] ], # cat head P6
|
||||
[ -1, 3, C3, [ 1024, False ] ], # 32 (P5/64-xlarge)
|
||||
|
||||
[ [ 23, 26, 29, 32 ], 1, Detect, [ nc, anchors ] ], # Detect(P3, P4, P5, P6)
|
||||
]
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
# parameters
|
||||
nc: 80 # number of classes
|
||||
depth_multiple: 1.0 # model depth multiple
|
||||
width_multiple: 1.0 # layer channel multiple
|
||||
|
||||
# anchors
|
||||
anchors: 3
|
||||
|
||||
# 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, [ 768, 3, 2 ] ], # 7-P5/32
|
||||
[ -1, 3, C3, [ 768 ] ],
|
||||
[ -1, 1, Conv, [ 1024, 3, 2 ] ], # 9-P6/64
|
||||
[ -1, 3, C3, [ 1024 ] ],
|
||||
[ -1, 1, Conv, [ 1280, 3, 2 ] ], # 11-P7/128
|
||||
[ -1, 1, SPP, [ 1280, [ 3, 5 ] ] ],
|
||||
[ -1, 3, C3, [ 1280, False ] ], # 13
|
||||
]
|
||||
|
||||
# YOLOv5 head
|
||||
head:
|
||||
[ [ -1, 1, Conv, [ 1024, 1, 1 ] ],
|
||||
[ -1, 1, nn.Upsample, [ None, 2, 'nearest' ] ],
|
||||
[ [ -1, 10 ], 1, Concat, [ 1 ] ], # cat backbone P6
|
||||
[ -1, 3, C3, [ 1024, False ] ], # 17
|
||||
|
||||
[ -1, 1, Conv, [ 768, 1, 1 ] ],
|
||||
[ -1, 1, nn.Upsample, [ None, 2, 'nearest' ] ],
|
||||
[ [ -1, 8 ], 1, Concat, [ 1 ] ], # cat backbone P5
|
||||
[ -1, 3, C3, [ 768, False ] ], # 21
|
||||
|
||||
[ -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 ] ], # 25
|
||||
|
||||
[ -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 ] ], # 29 (P3/8-small)
|
||||
|
||||
[ -1, 1, Conv, [ 256, 3, 2 ] ],
|
||||
[ [ -1, 26 ], 1, Concat, [ 1 ] ], # cat head P4
|
||||
[ -1, 3, C3, [ 512, False ] ], # 32 (P4/16-medium)
|
||||
|
||||
[ -1, 1, Conv, [ 512, 3, 2 ] ],
|
||||
[ [ -1, 22 ], 1, Concat, [ 1 ] ], # cat head P5
|
||||
[ -1, 3, C3, [ 768, False ] ], # 35 (P5/32-large)
|
||||
|
||||
[ -1, 1, Conv, [ 768, 3, 2 ] ],
|
||||
[ [ -1, 18 ], 1, Concat, [ 1 ] ], # cat head P6
|
||||
[ -1, 3, C3, [ 1024, False ] ], # 38 (P6/64-xlarge)
|
||||
|
||||
[ -1, 1, Conv, [ 1024, 3, 2 ] ],
|
||||
[ [ -1, 14 ], 1, Concat, [ 1 ] ], # cat head P7
|
||||
[ -1, 3, C3, [ 1280, False ] ], # 41 (P7/128-xxlarge)
|
||||
|
||||
[ [ 29, 32, 35, 38, 41 ], 1, Detect, [ nc, anchors ] ], # Detect(P3, P4, P5, P6, P7)
|
||||
]
|
||||
|
|
@ -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, BottleneckCSP, [128]],
|
||||
[-1, 1, Conv, [256, 3, 2]], # 3-P3/8
|
||||
[-1, 9, BottleneckCSP, [256]],
|
||||
[-1, 1, Conv, [512, 3, 2]], # 5-P4/16
|
||||
[-1, 9, BottleneckCSP, [512]],
|
||||
[-1, 1, Conv, [1024, 3, 2]], # 7-P5/32
|
||||
[-1, 1, SPP, [1024, [5, 9, 13]]],
|
||||
[-1, 3, BottleneckCSP, [1024, False]], # 9
|
||||
]
|
||||
|
||||
# YOLOv5 PANet 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, BottleneckCSP, [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, BottleneckCSP, [256, False]], # 17 (P3/8-small)
|
||||
|
||||
[-1, 1, Conv, [256, 3, 2]],
|
||||
[[-1, 14], 1, Concat, [1]], # cat head P4
|
||||
[-1, 3, BottleneckCSP, [512, False]], # 20 (P4/16-medium)
|
||||
|
||||
[-1, 1, Conv, [512, 3, 2]],
|
||||
[[-1, 10], 1, Concat, [1]], # cat head P5
|
||||
[-1, 3, BottleneckCSP, [1024, False]], # 23 (P5/32-large)
|
||||
|
||||
[[17, 20, 23], 1, Detect, [nc, anchors]], # Detect(P3, P4, P5)
|
||||
]
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
# parameters
|
||||
nc: 80 # number of classes
|
||||
depth_multiple: 1.0 # model depth multiple
|
||||
width_multiple: 1.0 # layer channel multiple
|
||||
|
||||
# anchors
|
||||
anchors:
|
||||
- [ 19,27, 44,40, 38,94 ] # P3/8
|
||||
- [ 96,68, 86,152, 180,137 ] # P4/16
|
||||
- [ 140,301, 303,264, 238,542 ] # P5/32
|
||||
- [ 436,615, 739,380, 925,792 ] # P6/64
|
||||
|
||||
# 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, [ 768, 3, 2 ] ], # 7-P5/32
|
||||
[ -1, 3, C3, [ 768 ] ],
|
||||
[ -1, 1, Conv, [ 1024, 3, 2 ] ], # 9-P6/64
|
||||
[ -1, 1, SPP, [ 1024, [ 3, 5, 7 ] ] ],
|
||||
[ -1, 3, C3, [ 1024, False ] ], # 11
|
||||
]
|
||||
|
||||
# YOLOv5 head
|
||||
head:
|
||||
[ [ -1, 1, Conv, [ 768, 1, 1 ] ],
|
||||
[ -1, 1, nn.Upsample, [ None, 2, 'nearest' ] ],
|
||||
[ [ -1, 8 ], 1, Concat, [ 1 ] ], # cat backbone P5
|
||||
[ -1, 3, C3, [ 768, False ] ], # 15
|
||||
|
||||
[ -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 ] ], # 19
|
||||
|
||||
[ -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 ] ], # 23 (P3/8-small)
|
||||
|
||||
[ -1, 1, Conv, [ 256, 3, 2 ] ],
|
||||
[ [ -1, 20 ], 1, Concat, [ 1 ] ], # cat head P4
|
||||
[ -1, 3, C3, [ 512, False ] ], # 26 (P4/16-medium)
|
||||
|
||||
[ -1, 1, Conv, [ 512, 3, 2 ] ],
|
||||
[ [ -1, 16 ], 1, Concat, [ 1 ] ], # cat head P5
|
||||
[ -1, 3, C3, [ 768, False ] ], # 29 (P5/32-large)
|
||||
|
||||
[ -1, 1, Conv, [ 768, 3, 2 ] ],
|
||||
[ [ -1, 12 ], 1, Concat, [ 1 ] ], # cat head P6
|
||||
[ -1, 3, C3, [ 1024, False ] ], # 32 (P6/64-xlarge)
|
||||
|
||||
[ [ 23, 26, 29, 32 ], 1, Detect, [ nc, anchors ] ], # Detect(P3, P4, P5, P6)
|
||||
]
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
# parameters
|
||||
nc: 80 # number of classes
|
||||
depth_multiple: 0.67 # model depth multiple
|
||||
width_multiple: 0.75 # layer channel multiple
|
||||
|
||||
# anchors
|
||||
anchors:
|
||||
- [ 19,27, 44,40, 38,94 ] # P3/8
|
||||
- [ 96,68, 86,152, 180,137 ] # P4/16
|
||||
- [ 140,301, 303,264, 238,542 ] # P5/32
|
||||
- [ 436,615, 739,380, 925,792 ] # P6/64
|
||||
|
||||
# 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, [ 768, 3, 2 ] ], # 7-P5/32
|
||||
[ -1, 3, C3, [ 768 ] ],
|
||||
[ -1, 1, Conv, [ 1024, 3, 2 ] ], # 9-P6/64
|
||||
[ -1, 1, SPP, [ 1024, [ 3, 5, 7 ] ] ],
|
||||
[ -1, 3, C3, [ 1024, False ] ], # 11
|
||||
]
|
||||
|
||||
# YOLOv5 head
|
||||
head:
|
||||
[ [ -1, 1, Conv, [ 768, 1, 1 ] ],
|
||||
[ -1, 1, nn.Upsample, [ None, 2, 'nearest' ] ],
|
||||
[ [ -1, 8 ], 1, Concat, [ 1 ] ], # cat backbone P5
|
||||
[ -1, 3, C3, [ 768, False ] ], # 15
|
||||
|
||||
[ -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 ] ], # 19
|
||||
|
||||
[ -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 ] ], # 23 (P3/8-small)
|
||||
|
||||
[ -1, 1, Conv, [ 256, 3, 2 ] ],
|
||||
[ [ -1, 20 ], 1, Concat, [ 1 ] ], # cat head P4
|
||||
[ -1, 3, C3, [ 512, False ] ], # 26 (P4/16-medium)
|
||||
|
||||
[ -1, 1, Conv, [ 512, 3, 2 ] ],
|
||||
[ [ -1, 16 ], 1, Concat, [ 1 ] ], # cat head P5
|
||||
[ -1, 3, C3, [ 768, False ] ], # 29 (P5/32-large)
|
||||
|
||||
[ -1, 1, Conv, [ 768, 3, 2 ] ],
|
||||
[ [ -1, 12 ], 1, Concat, [ 1 ] ], # cat head P6
|
||||
[ -1, 3, C3, [ 1024, False ] ], # 32 (P6/64-xlarge)
|
||||
|
||||
[ [ 23, 26, 29, 32 ], 1, Detect, [ nc, anchors ] ], # Detect(P3, P4, P5, P6)
|
||||
]
|
||||
|
|
@ -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, C3TR, [1024, False]], # 9 <-------- C3TR() Transformer module
|
||||
]
|
||||
|
||||
# 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)
|
||||
]
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
# parameters
|
||||
nc: 80 # number of classes
|
||||
depth_multiple: 0.33 # model depth multiple
|
||||
width_multiple: 0.50 # layer channel multiple
|
||||
|
||||
# anchors
|
||||
anchors:
|
||||
- [ 19,27, 44,40, 38,94 ] # P3/8
|
||||
- [ 96,68, 86,152, 180,137 ] # P4/16
|
||||
- [ 140,301, 303,264, 238,542 ] # P5/32
|
||||
- [ 436,615, 739,380, 925,792 ] # P6/64
|
||||
|
||||
# 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, [ 768, 3, 2 ] ], # 7-P5/32
|
||||
[ -1, 3, C3, [ 768 ] ],
|
||||
[ -1, 1, Conv, [ 1024, 3, 2 ] ], # 9-P6/64
|
||||
[ -1, 1, SPP, [ 1024, [ 3, 5, 7 ] ] ],
|
||||
[ -1, 3, C3, [ 1024, False ] ], # 11
|
||||
]
|
||||
|
||||
# YOLOv5 head
|
||||
head:
|
||||
[ [ -1, 1, Conv, [ 768, 1, 1 ] ],
|
||||
[ -1, 1, nn.Upsample, [ None, 2, 'nearest' ] ],
|
||||
[ [ -1, 8 ], 1, Concat, [ 1 ] ], # cat backbone P5
|
||||
[ -1, 3, C3, [ 768, False ] ], # 15
|
||||
|
||||
[ -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 ] ], # 19
|
||||
|
||||
[ -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 ] ], # 23 (P3/8-small)
|
||||
|
||||
[ -1, 1, Conv, [ 256, 3, 2 ] ],
|
||||
[ [ -1, 20 ], 1, Concat, [ 1 ] ], # cat head P4
|
||||
[ -1, 3, C3, [ 512, False ] ], # 26 (P4/16-medium)
|
||||
|
||||
[ -1, 1, Conv, [ 512, 3, 2 ] ],
|
||||
[ [ -1, 16 ], 1, Concat, [ 1 ] ], # cat head P5
|
||||
[ -1, 3, C3, [ 768, False ] ], # 29 (P5/32-large)
|
||||
|
||||
[ -1, 1, Conv, [ 768, 3, 2 ] ],
|
||||
[ [ -1, 12 ], 1, Concat, [ 1 ] ], # cat head P6
|
||||
[ -1, 3, C3, [ 1024, False ] ], # 32 (P6/64-xlarge)
|
||||
|
||||
[ [ 23, 26, 29, 32 ], 1, Detect, [ nc, anchors ] ], # Detect(P3, P4, P5, P6)
|
||||
]
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
# parameters
|
||||
nc: 80 # number of classes
|
||||
depth_multiple: 1.33 # model depth multiple
|
||||
width_multiple: 1.25 # layer channel multiple
|
||||
|
||||
# anchors
|
||||
anchors:
|
||||
- [ 19,27, 44,40, 38,94 ] # P3/8
|
||||
- [ 96,68, 86,152, 180,137 ] # P4/16
|
||||
- [ 140,301, 303,264, 238,542 ] # P5/32
|
||||
- [ 436,615, 739,380, 925,792 ] # P6/64
|
||||
|
||||
# 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, [ 768, 3, 2 ] ], # 7-P5/32
|
||||
[ -1, 3, C3, [ 768 ] ],
|
||||
[ -1, 1, Conv, [ 1024, 3, 2 ] ], # 9-P6/64
|
||||
[ -1, 1, SPP, [ 1024, [ 3, 5, 7 ] ] ],
|
||||
[ -1, 3, C3, [ 1024, False ] ], # 11
|
||||
]
|
||||
|
||||
# YOLOv5 head
|
||||
head:
|
||||
[ [ -1, 1, Conv, [ 768, 1, 1 ] ],
|
||||
[ -1, 1, nn.Upsample, [ None, 2, 'nearest' ] ],
|
||||
[ [ -1, 8 ], 1, Concat, [ 1 ] ], # cat backbone P5
|
||||
[ -1, 3, C3, [ 768, False ] ], # 15
|
||||
|
||||
[ -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 ] ], # 19
|
||||
|
||||
[ -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 ] ], # 23 (P3/8-small)
|
||||
|
||||
[ -1, 1, Conv, [ 256, 3, 2 ] ],
|
||||
[ [ -1, 20 ], 1, Concat, [ 1 ] ], # cat head P4
|
||||
[ -1, 3, C3, [ 512, False ] ], # 26 (P4/16-medium)
|
||||
|
||||
[ -1, 1, Conv, [ 512, 3, 2 ] ],
|
||||
[ [ -1, 16 ], 1, Concat, [ 1 ] ], # cat head P5
|
||||
[ -1, 3, C3, [ 768, False ] ], # 29 (P5/32-large)
|
||||
|
||||
[ -1, 1, Conv, [ 768, 3, 2 ] ],
|
||||
[ [ -1, 12 ], 1, Concat, [ 1 ] ], # cat head P6
|
||||
[ -1, 3, C3, [ 1024, False ] ], # 32 (P6/64-xlarge)
|
||||
|
||||
[ [ 23, 26, 29, 32 ], 1, Detect, [ nc, anchors ] ], # Detect(P3, P4, P5, P6)
|
||||
]
|
||||
|
|
@ -0,0 +1,277 @@
|
|||
# YOLOv5 YOLO-specific modules
|
||||
|
||||
import argparse
|
||||
import logging
|
||||
import sys
|
||||
from copy import deepcopy
|
||||
|
||||
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 layer
|
||||
super(Detect, self).__init__()
|
||||
self.nc = nc # number of classes
|
||||
self.no = nc + 5 # number of outputs per anchor
|
||||
self.nl = len(anchors) # number of detection layers
|
||||
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 * self.na, 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))
|
||||
|
||||
return x if self.training else (torch.cat(z, 1), x)
|
||||
|
||||
@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)
|
||||
|
||||
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
|
||||
|
|
@ -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)
|
||||
]
|
||||
|
|
@ -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)
|
||||
]
|
||||
|
|
@ -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)
|
||||
]
|
||||
|
|
@ -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)
|
||||
]
|
||||
|
|
@ -0,0 +1,303 @@
|
|||
from PIL import Image
|
||||
import numpy as np
|
||||
import cv2
|
||||
import base64
|
||||
import io,os
|
||||
import requests
|
||||
import time,json
|
||||
import string,random
|
||||
import glob,string,sys
|
||||
from multiprocessing import Process,Queue
|
||||
import oss2
|
||||
from kafka import KafkaProducer, KafkaConsumer
|
||||
##for CeKanYuan
|
||||
#10月21日,通过图像名称判断,是那个平台。方式不好。
|
||||
#10月22日,改成访问固定的地址,从地址中读取,平台的名称与地址。每隔2分钟访问一次。
|
||||
#3月18日,采用OSS阿里云存储桶
|
||||
#platform_query_url='http://47.96.182.154:9051/api/suanfa/getPlatformInfo'
|
||||
platform_query_url='SendLog/platformQuery.json'
|
||||
api = 'http://121.40.249.52:9050/api/taskFile/submitUAVKHQuestion'
|
||||
#api = 'http://47.98.157.120:9040/api/taskFile/submitUAVKHQuestion'
|
||||
|
||||
##这套名字,是联通的。
|
||||
name_dic={
|
||||
"排口":"入河、湖排口",
|
||||
"疑似污口": "入河、湖排口",
|
||||
"水生植被": "水生植物",
|
||||
"漂浮物": "有大面积漂物",
|
||||
"结束": "结束",
|
||||
'其它' :'其它'
|
||||
}
|
||||
## for TH river
|
||||
##这套代码是河长制度的。
|
||||
nameID_dic={
|
||||
"排口":'00000',
|
||||
"疑似污口": '8378',
|
||||
"水生植被": '8380',
|
||||
"漂浮物": '8368',
|
||||
"结束":'9999',
|
||||
'其它':'8888'
|
||||
}
|
||||
|
||||
def get_time(filename):
|
||||
#2021-10-09-11-44-51_frame-598-720_type-水生植被.jpg
|
||||
sps=filename.strip().split('_')[0]
|
||||
tsps=sps.split('-')
|
||||
return '%s-%s-%s %s:%s:%s'%(tsps[0],tsps[1],tsps[2],tsps[3],tsps[4],tsps[5])
|
||||
def get_ms(time0,time1):
|
||||
str_time ='%.2f ms'%((time1-time0)*1000)
|
||||
return str_time
|
||||
|
||||
def get_urls( platform_query_url,fp_log ):
|
||||
try:
|
||||
if os.path.exists(platform_query_url):
|
||||
#print('###line49')
|
||||
with open('SendLog/platformQuery.json','r') as fp:
|
||||
res = json.load(fp)
|
||||
else:
|
||||
res = requests.get(platform_query_url,timeout=10).json()
|
||||
#print('###line54')
|
||||
questionUrl = res['data']['questionUrl'] ###直播流时,问题图片的推送地址
|
||||
offlineUrl = res['data']['offlineUrl'] ###http离线视频时,问题图片的推送地址
|
||||
except Exception as ee:
|
||||
timestr=time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
|
||||
print('###### %s: file:send_transfer: error %s ,url:%s #####'%(timestr,ee,platform_query_url))
|
||||
outstr = '\n %s ###### get url platform error : update error:%s , url:%s'%( time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) ,ee,platform_query_url)
|
||||
fp_log.write(outstr);fp_log.flush()
|
||||
questionUrl="http://47.96.182.154:9040/api/taskFile/submitUAVKHQuestion"
|
||||
offlineUrl ="http://47.96.182.154:9040/api/taskFile/submitUAVKHQuestion"
|
||||
return questionUrl,offlineUrl
|
||||
def parse_filename(filename_base):
|
||||
#etc:2022-01-13-16-04-17_frame-823-1440_type-水生植被_hgYFEulc0dPIrG1S_s-off-XJRW20220113154959_AI.jpg
|
||||
uid =filename_base.split('.')[0].split('_')[3].strip()
|
||||
sourceType=filename_base.split('_')[4].split('-')[1]
|
||||
sourceId=filename_base.split('_')[4].split('-')[2]
|
||||
typename=filename_base.split('.')[0].split('_')[2].split('-')[1].strip()
|
||||
return uid,sourceType,sourceId,typename
|
||||
def b64encode_function(filename, filename_OR):
|
||||
if os.path.exists(filename):
|
||||
image_ori=cv2.imread(filename)
|
||||
image_ori_OR=cv2.imread(filename_OR)
|
||||
else:
|
||||
image_ori = filename.copy()
|
||||
image_ori_OR = image_ori_OR.copy()
|
||||
image_pngcode = cv2.imencode('.jpg',image_ori)[-1]
|
||||
image_pngcode_OR = cv2.imencode('.jpg',image_ori_OR)[-1]
|
||||
image_code = str(base64.b64encode(image_pngcode))[2:-1]
|
||||
image_code_OR = str(base64.b64encode(image_pngcode_OR))[2:-1]
|
||||
return image_code, image_code_OR
|
||||
def JsonSend(parIn):
|
||||
|
||||
fp_log = parIn['fp_log']
|
||||
try:
|
||||
response=requests.post(parIn['api'],json=parIn['input_'],timeout=10).json()
|
||||
t3 = time.time()
|
||||
print('\n file:%s encodetime:%.5f request time:%.5f,send to %s ,return code:%s, size:%.2f M \n'%(parIn['filename_base'],parIn['t2']-parIn['t1'],t3-parIn['t2'],api,response['code'],parIn['sizeImage']))
|
||||
outstr = '%s file:%s encodetime:%.5f request time:%.5f,send to %s ,return code:%s,size:%.2f M ,%s\n'%( time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()),parIn['filename_base'],parIn['t2']-parIn['t1'],t3-parIn['t2'],parIn['api'],response['code'],parIn['sizeImage'],parIn['dic_str'])
|
||||
fp_log.write(outstr);fp_log.flush()
|
||||
|
||||
except Exception as ee:
|
||||
print('\n ######file:%s: upload error:%s,size:%.2f M'%(parIn['filename_base'],ee, parIn['sizeImage']))
|
||||
outstr = '\n%s ###### file:%s: upload error:%s , size:%.2f M'%( time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) ,parIn['filename_base'],ee,parIn['sizeImage'])
|
||||
fp_log.write(outstr);fp_log.flush()
|
||||
|
||||
|
||||
def dic2str(dic):
|
||||
st=''
|
||||
for key in dic.keys():
|
||||
st='%s %s:%s,'%(st,key,dic[key])
|
||||
return st
|
||||
def createJsonInput(filename,offlineUrl,questionUrl):
|
||||
flag = True
|
||||
filename_base = os.path.basename(filename)
|
||||
filename_OR=filename.replace('_AI.','_OR.')
|
||||
if not os.path.exists(filename_OR ):
|
||||
return False
|
||||
|
||||
uid,sourceType, sourceId,typename = parse_filename(filename_base)
|
||||
if (typename not in name_dic.keys()) or (typename == '排口'):
|
||||
return False
|
||||
api = questionUrl if sourceType=='live' else offlineUrl
|
||||
|
||||
time_str = get_time(filename_base)
|
||||
input_ ={
|
||||
'imgName':os.path.basename(filename),
|
||||
'imgNameOriginal':os.path.basename(filename_OR),
|
||||
'time':time_str,
|
||||
'fid':uid, ###随机16位字符
|
||||
'type':name_dic[typename],###这次先采用 ["排口","污口","水生植被","漂浮物","其它"]
|
||||
'typeId':nameID_dic[typename]
|
||||
|
||||
}
|
||||
if sourceType!='live':
|
||||
input_['code']=sourceId;###只有离线视频才需要code,
|
||||
|
||||
dic_str = dic2str(input_)
|
||||
t1 = time.time()
|
||||
|
||||
image_code, image_code_OR = b64encode_function(filename, filename_OR)
|
||||
input_['imgData']=image_code
|
||||
input_['imgDataOriginal']=image_code_OR
|
||||
|
||||
sizeImage = (len(image_code) + len(image_code_OR) )/1000000.0
|
||||
|
||||
parOut={};parOut['flag']=True;parOut['input_']=input_;
|
||||
parOut['sizeImage']=sizeImage;parOut['dic_str']=dic_str;
|
||||
parOut['filename']=filename;parOut['filename_OR']=filename_OR;
|
||||
parOut['api']=api ; parOut['t1']=t1 ; parOut['filename_base']= filename_base
|
||||
return parOut
|
||||
|
||||
def getLogFileFp(streamName):
|
||||
logname ='SendLog/'+ time.strftime("%Y-%m-%d", time.localtime())+'_%s.txt'%(streamName)
|
||||
if os.path.exists(logname):
|
||||
fp_log = open(logname,'a+')
|
||||
else:
|
||||
fp_log = open(logname,'w')
|
||||
return
|
||||
|
||||
def lodaMsgInfos(jsonDir,msgId):
|
||||
jsonUrl = os.path.join(jsonDir,msgId+'.json')
|
||||
with open(jsonUrl,'r') as fp:
|
||||
data=json.load(fp)
|
||||
return data
|
||||
|
||||
def parse_filename_for_oss(name):
|
||||
splts=name.split('_')
|
||||
typename=splts[2].split('-')[1].strip()
|
||||
msgId=splts[4].split('-')[3]
|
||||
onLineType=splts[4].split('-')[1]
|
||||
return typename,msgId,onLineType
|
||||
|
||||
msg_dict_off={
|
||||
"msg_id":"bblvgyntTsZCamqjuLArkiSYIbKXEeWx",#消息ID标识
|
||||
"biz_id":"hehuzhang",#业务标识
|
||||
"mod_id":"ai",#模型标识
|
||||
"status":"running",#任务状态
|
||||
"type":str(1),#数据类型:1图片 2视频
|
||||
"error":9999,#错误信息
|
||||
"results":[#问题结果
|
||||
{
|
||||
"original_url":"",#原图地址
|
||||
"sign_url":"",#AI标记地址
|
||||
"category_id":"",#分类标识
|
||||
"description":"",#问题描述
|
||||
"time":"",#时间戳
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
msg_dict_on={
|
||||
"msg_id":"bblvgyntTsZCamqjuLArkiSYIbKXEeWx",#消息ID标识
|
||||
"biz_id":"hehuzhang",#业务标识
|
||||
"mod_id":"qi",#模型标识
|
||||
"status":"running",#任务状态
|
||||
"type":str(2),#数据类型:1图片 2视频
|
||||
"error":9999,#错误信息
|
||||
"results":[#问题结果
|
||||
{
|
||||
"original_url":"",#原视频地址(离线识别时为空不传,实时识别时需要上传)
|
||||
"sign_url":"",#识别后视频地址
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
def update_json(jsonOri,jsonNew,offkeys=["msg_id","biz_id" ,"mod_id" ]):
|
||||
#{'biz_id': 'hehuzhang', 'mod_id': 'ai', 'msg_id': 'bblvgyntTsZCamqjuLArkiSYIbKXEeWx', 'offering_id': 'http://vod.play.t-aaron.com/customerTrans/c49a2c620795d124f2ae4b10197b8d0e/303b7a58-17f3ef4494e-0004-f90c-f2c-7ec68.mp4', 'offering_type': 'mp4', 'results_base_dir': 'XJRW20220317153547', 'inSource': 'http://vod.play.t-aaron.com/customerTrans/c49a2c620795d124f2ae4b10197b8d0e/303b7a58-17f3ef4494e-0004-f90c-f2c-7ec68.mp4', 'outSource': 'NO'}
|
||||
for key in offkeys:
|
||||
jsonNew[key] = jsonOri[key]
|
||||
return jsonNew
|
||||
def test5(indir,outdir,jsonDir,videoBakDir,ossPar,kafkaPar):
|
||||
|
||||
|
||||
time0_0 = time.time()
|
||||
logname ='SendLog/'+ time.strftime("%Y-%m-%d.txt", time.localtime())
|
||||
if os.path.exists(logname):
|
||||
fp_log = open(logname,'a+')
|
||||
else:
|
||||
fp_log = open(logname,'w')
|
||||
ifind=0
|
||||
time0_0 = time.time()
|
||||
|
||||
producer = KafkaProducer(
|
||||
bootstrap_servers=kafkaPar['boostServer'],#tencent yun
|
||||
value_serializer=lambda v: v.encode('utf-8'))
|
||||
|
||||
|
||||
###登陆准备存储桶
|
||||
auth = oss2.Auth(ossPar['AId'], ossPar['ASt'])
|
||||
# Endpoint以杭州为例,其它Region请按实际情况填写。
|
||||
bucket = oss2.Bucket(auth, ossPar['Epoint'], ossPar['bucketName'])
|
||||
|
||||
|
||||
while True:
|
||||
#filelist = os.listdir(indir)
|
||||
filelist_AI = sorted(glob.glob('%s/*_AI.*'%(indir)),key=os.path.getmtime)
|
||||
filelist = filelist_AI
|
||||
|
||||
if len(filelist)!=0:
|
||||
time0 = time.time()
|
||||
for filename in filelist[0:2]:
|
||||
filename_base = os.path.basename(filename)
|
||||
##解析文件名
|
||||
typename,msgId,onLineType = parse_filename_for_oss(filename_base)
|
||||
|
||||
##存储文件
|
||||
filename_OR=filename.replace('_AI.','_OR.')
|
||||
|
||||
|
||||
|
||||
if typename!='结束':
|
||||
ObjectName_AI=os.path.join(ossPar['bucketName'],os.path.basename(filename))
|
||||
ObjectName_OR=os.path.join(ossPar['bucketName'],os.path.basename(filename_OR))
|
||||
bucket.put_object_from_file(ObjectName_AI, filename)
|
||||
bucket.put_object_from_file(ObjectName_OR, filename_OR)
|
||||
taskInfos = lodaMsgInfos(jsonDir,msgId)
|
||||
#print(taskInfos)
|
||||
##发送返回信息
|
||||
#if onLineType=='off':
|
||||
msg = msg_dict_off
|
||||
msg['results'][0]['original_url']= ObjectName_OR
|
||||
msg['results'][0]['sign_url']= ObjectName_AI
|
||||
msg['results'][0]['category_id']= nameID_dic[typename]
|
||||
msg['results'][0]['description']= typename
|
||||
msg['results'][0]['time']= time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
|
||||
msg = update_json(taskInfos,msg)
|
||||
else:
|
||||
msg = msg_dict_on
|
||||
videoList = sorted(glob.glob('%s/*'%(videoBakDir)),key=os.path.getmtime)
|
||||
videoName = os.path.basename(videoList[0])
|
||||
msg["status"]="success";msg["msg_id"]=msgId
|
||||
ObjectName_AI=os.path.join(ossPar['bucketName'],videoName)
|
||||
bucket.put_object_from_file(ObjectName_AI, videoList[0])
|
||||
msg['results'][0]['original_url']= ObjectName_AI
|
||||
msg['results'][0]['sign_url']= ObjectName_AI###最新的视频文件
|
||||
|
||||
print('###'*3,'Send:',filename)
|
||||
msg = json.dumps(msg, ensure_ascii=False)
|
||||
future = producer.send(
|
||||
kafkaPar['topic'],
|
||||
msg
|
||||
)
|
||||
print('***'*20,' Send transfer ',onLineType,msg)
|
||||
|
||||
##上传后的图片,移走到另外一个文件夹###
|
||||
cmd = 'mv \'%s\' \'%s\' '%(filename,outdir); os.system(cmd)
|
||||
cmd = 'mv \'%s\' \'%s\' '%(filename_OR,outdir); os.system(cmd)
|
||||
|
||||
else:
|
||||
time.sleep(1)
|
||||
fp_log.close()
|
||||
|
||||
if __name__=='__main__':
|
||||
indir='problems/images_tmp'
|
||||
outdir='problems/images_save'
|
||||
jsonDir = 'mintors/kafka/'
|
||||
videoBakDir='../../data/video_live_bak/1945'
|
||||
ossPar={'Epoint':'http://oss-cn-shanghai.aliyuncs.com',
|
||||
'AId':'LTAI5tSJ62TLMUb4SZuf285A',
|
||||
'ASt':'MWYynm30filZ7x0HqSHlU3pdLVNeI7',
|
||||
'bucketName':'ta-tech-image',
|
||||
}
|
||||
#kafkaPar={'boostServer':['212.129.223.66:9092'],'topic':'testReturn'}
|
||||
kafkaPar={'boostServer':['101.132.127.1:19092'],'topic':'alg-task-results'}
|
||||
test5(indir,outdir,jsonDir,videoBakDir,ossPar,kafkaPar)
|
||||
|
|
@ -0,0 +1,94 @@
|
|||
from kafka import KafkaProducer, KafkaConsumer
|
||||
from kafka.errors import kafka_errors
|
||||
import traceback
|
||||
import json
|
||||
import time
|
||||
import random,string
|
||||
def producer_demo():
|
||||
|
||||
|
||||
cnt_online=1;cnt_offline=0
|
||||
Tecent=False;
|
||||
|
||||
#topic_on='thsw';topic_off='thsw2';
|
||||
#server=['212.129.223.66:19092'];
|
||||
server=["192.168.11.242:9092"]
|
||||
#server=['101.132.127.1:19092']
|
||||
|
||||
topic_on='dsp-alg-online-tasks';topic_off='dsp-alg-offline-tasks'
|
||||
# 假设生产的消息为键值对(不是一定要键值对),且序列化方式为json
|
||||
producer = KafkaProducer(
|
||||
bootstrap_servers=server,#tencent yun
|
||||
value_serializer=lambda v: v.encode('utf-8'))
|
||||
# 发送三条消息
|
||||
|
||||
if not Tecent:
|
||||
#pull_channel = "rtmp://live.play.t-aaron.com/live/THSA"
|
||||
#push_channel = 'rtmp://live.push.t-aaron.com/live/THSB'
|
||||
#pull_channel = 'rtmp://live.play.t-aaron.com/live/THSAa_hd'
|
||||
pull_channel = 'http://live.play.t-aaron.com/live/THSAc_hd.m3u8'
|
||||
push_channel = "rtmp://live.push.t-aaron.com/live/THSBc"
|
||||
else:
|
||||
pull_channel = "rtmp://demoplay.yunhengzhizao.cn/live/THSA_HD5M"
|
||||
push_channel = "rtmp://127.0.0.1:1935/live/test"
|
||||
#pull_channel = 'rtmp://live.play.t-aaron.com/live/THSAa'
|
||||
#push_channel = 'rtmp://127.0.0.1:1975/live/test'
|
||||
for i in range(0, cnt_online):
|
||||
time.sleep(0.0001)
|
||||
#''.join(random.sample(string.ascii_letters ,16) )
|
||||
msg_dict = {
|
||||
"request_id":'nn'+''.join(random.sample(string.ascii_letters ,30) ) ,
|
||||
"models":[
|
||||
{
|
||||
"id":"001",
|
||||
"config":{"0":"0", "1":"1","2":"1","3":"1","4":"1"
|
||||
}
|
||||
}
|
||||
],
|
||||
"pull_url":pull_channel,
|
||||
"push_url":push_channel,
|
||||
"results_base_dir": "XJRW202111291703"+str(random.randint(10,99)),
|
||||
}
|
||||
msg = json.dumps(msg_dict)
|
||||
#msg = msg_dict
|
||||
future = producer.send(
|
||||
topic_on,
|
||||
#key='count_num', # 同一个key值,会被送至同一个分区
|
||||
msg
|
||||
)
|
||||
|
||||
|
||||
print('online send {}'.format(str(i)))
|
||||
try:
|
||||
future.get(timeout=10) # 监控是否发送成功
|
||||
except kafka_errors: # 发送失败抛出kafka_errors
|
||||
traceback.format_exc()
|
||||
|
||||
for i in range(0, cnt_offline):
|
||||
msg_dict = {
|
||||
|
||||
"request_id":'bb'+''.join(random.sample(string.ascii_letters ,30) ) ,
|
||||
"models":[
|
||||
{
|
||||
"id":"001",
|
||||
"config":{"0":"1", "1":"1","2":"1","3":"1","4":"1"}
|
||||
}
|
||||
],
|
||||
"original_url":"http://vod.play.t-aaron.com/customerTrans/c49a2c620795d124f2ae4b10197b8d0e/303b7a58-17f3ef4494e-0004-f90c-f2c-7ec68.mp4",
|
||||
"original_type":"mp4",
|
||||
"results_base_dir": "XJRW202203171535"+str(random.randint(10,99)),
|
||||
}
|
||||
|
||||
|
||||
|
||||
msg = json.dumps(msg_dict)
|
||||
#msg = msg_dict
|
||||
future = producer.send(topic_off,msg)
|
||||
print('offline send {}'.format(str(i)))
|
||||
try:
|
||||
future.get(timeout=10)
|
||||
except kafka_errors:
|
||||
traceback.format_exc()
|
||||
|
||||
if __name__=='__main__':
|
||||
producer_demo()
|
||||
|
|
@ -0,0 +1,307 @@
|
|||
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):####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_id = get_largest_contours(contours);
|
||||
cv2.fillPoly(water, [contours[max_id][:,0,:]], 1)
|
||||
cv2.drawContours(image_array0,contours,max_id,(0,255,255),3)
|
||||
return image_array0,water
|
||||
|
||||
|
||||
|
||||
def post_process_(datas,conf_thres, iou_thres,names,label_arraylist,rainbows,iframe,object_config=[0,1,2,3,4]):
|
||||
##输入dataset genereate 生成的数据,model预测的结果pred,nms参数
|
||||
##主要操作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]###一次检测一张图片
|
||||
p, s, im0 = path[i], '%g: ' % i, im0s[i].copy()
|
||||
gn = torch.tensor(im0.shape)[[1, 0, 1, 0]] # normalization gain whwh
|
||||
det_xywh=[];
|
||||
#im0_brg=cv2.cvtColor(im0,cv2.COLOR_RGB2BGR);
|
||||
if len(seg_pred)==2:
|
||||
im0,water = illBuildings(seg_pred,im0)
|
||||
else:
|
||||
im0,water = drawWater(seg_pred,im0)
|
||||
time2=time.time()
|
||||
#plt.imshow(im0);plt.show()
|
||||
if len(det)>0:
|
||||
# Rescale boxes from img_size to im0 size
|
||||
det[:, :4] = scale_coords(img.shape[2:], det[:, :4],im0.shape).round()
|
||||
#用seg模型,确定有效检测匡及河道轮廓线
|
||||
if segmodel:
|
||||
'''contours, hierarchy = cv2.findContours(seg_pred,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
|
||||
if len(contours)>0:
|
||||
max_id = get_largest_contours(contours)
|
||||
seg_pred[:,:] = 0
|
||||
cv2.fillPoly(seg_pred, [contours[max_id][:,0,:]], 1)
|
||||
cv2.drawContours(im0,contours,max_id,(0,255,255),3)'''
|
||||
det_c = det.clone(); det_c=det_c.cpu().numpy()
|
||||
area_factors = np.array([np.sum(water[int(x[1]):int(x[3]), int(x[0]):int(x[2])] )/((x[2]-x[0])*(x[3]-x[1])) for x in det_c] )
|
||||
det = det[area_factors>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],line_thickness=None)
|
||||
time3=time.time()
|
||||
strout='nms:%s illBuilding:%s detDraw:%s '%(get_ms(time0,time1),get_ms(time1,time2), 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)
|
||||
|
|
@ -0,0 +1,501 @@
|
|||
#@@ -1,43 +1,43 @@
|
||||
# GPUtil - GPU utilization
|
||||
#
|
||||
# A Python module for programmically getting the GPU utilization from NVIDA GPUs using nvidia-smi
|
||||
#
|
||||
# Author: Anders Krogh Mortensen (anderskm)
|
||||
# Date: 16 January 2017
|
||||
# Web: https://github.com/anderskm/gputil
|
||||
#
|
||||
# LICENSE
|
||||
#
|
||||
# MIT License
|
||||
#
|
||||
# Copyright (c) 2017 anderskm
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in all
|
||||
# copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
|
||||
from subprocess import Popen, PIPE
|
||||
from distutils import spawn
|
||||
import os
|
||||
import math
|
||||
import random
|
||||
import time
|
||||
import sys
|
||||
import platform
|
||||
import subprocess
|
||||
import numpy as np
|
||||
|
||||
|
||||
__version__ = '1.4.0'
|
||||
class GPU:
|
||||
def __init__(self, ID, uuid, load, memoryTotal, memoryUsed, memoryFree, driver, gpu_name, serial, display_mode, display_active, temp_gpu):
|
||||
self.id = ID
|
||||
self.uuid = uuid
|
||||
self.load = load
|
||||
self.memoryUtil = float(memoryUsed)/float(memoryTotal)
|
||||
self.memoryTotal = memoryTotal
|
||||
self.memoryUsed = memoryUsed
|
||||
self.memoryFree = memoryFree
|
||||
self.driver = driver
|
||||
self.name = gpu_name
|
||||
self.serial = serial
|
||||
self.display_mode = display_mode
|
||||
self.display_active = display_active
|
||||
self.temperature = temp_gpu
|
||||
|
||||
def __str__(self):
|
||||
return str(self.__dict__)
|
||||
|
||||
|
||||
class GPUProcess:
|
||||
def __init__(self, pid, processName, gpuId, gpuUuid, gpuName, usedMemory,
|
||||
uid, uname):
|
||||
self.pid = pid
|
||||
self.processName = processName
|
||||
self.gpuId = gpuId
|
||||
self.gpuUuid = gpuUuid
|
||||
self.gpuName = gpuName
|
||||
self.usedMemory = usedMemory
|
||||
self.uid = uid
|
||||
self.uname = uname
|
||||
|
||||
def __str__(self):
|
||||
return str(self.__dict__)
|
||||
|
||||
def safeFloatCast(strNumber):
|
||||
try:
|
||||
number = float(strNumber)
|
||||
except ValueError:
|
||||
number = float('nan')
|
||||
return number
|
||||
|
||||
#def getGPUs():
|
||||
def getNvidiaSmiCmd():
|
||||
if platform.system() == "Windows":
|
||||
# If the platform is Windows and nvidia-smi
|
||||
# could not be found from the environment path,
|
||||
#@@ -75,57 +94,97 @@ def getGPUs():
|
||||
nvidia_smi = "%s\\Program Files\\NVIDIA Corporation\\NVSMI\\nvidia-smi.exe" % os.environ['systemdrive']
|
||||
else:
|
||||
nvidia_smi = "nvidia-smi"
|
||||
return nvidia_smi
|
||||
|
||||
|
||||
def getGPUs():
|
||||
# Get ID, processing and memory utilization for all GPUs
|
||||
nvidia_smi = getNvidiaSmiCmd()
|
||||
try:
|
||||
p = Popen([nvidia_smi,"--query-gpu=index,uuid,utilization.gpu,memory.total,memory.used,memory.free,driver_version,name,gpu_serial,display_active,display_mode,temperature.gpu", "--format=csv,noheader,nounits"], stdout=PIPE)
|
||||
stdout, stderror = p.communicate()
|
||||
p = subprocess.run([
|
||||
nvidia_smi,
|
||||
"--query-gpu=index,uuid,utilization.gpu,memory.total,memory.used,memory.free,driver_version,name,gpu_serial,display_active,display_mode,temperature.gpu",
|
||||
"--format=csv,noheader,nounits"
|
||||
], stdout=subprocess.PIPE, encoding='utf8')
|
||||
stdout, stderror = p.stdout, p.stderr
|
||||
except:
|
||||
return []
|
||||
output = stdout;#output = stdout.decode('UTF-8')
|
||||
# output = output[2:-1] # Remove b' and ' from string added by python
|
||||
#print(output)
|
||||
output = stdout
|
||||
## Parse output
|
||||
# Split on line break
|
||||
lines = output.split(os.linesep)
|
||||
#print(lines)
|
||||
numDevices = len(lines)-1
|
||||
GPUs = []
|
||||
for g in range(numDevices):
|
||||
line = lines[g]
|
||||
#print(line)
|
||||
vals = line.split(', ')
|
||||
#print(vals)
|
||||
for i in range(12):
|
||||
# print(vals[i])
|
||||
if (i == 0):
|
||||
deviceIds = int(vals[i])
|
||||
elif (i == 1):
|
||||
uuid = vals[i]
|
||||
elif (i == 2):
|
||||
gpuUtil = safeFloatCast(vals[i])/100
|
||||
elif (i == 3):
|
||||
memTotal = safeFloatCast(vals[i])
|
||||
elif (i == 4):
|
||||
memUsed = safeFloatCast(vals[i])
|
||||
elif (i == 5):
|
||||
memFree = safeFloatCast(vals[i])
|
||||
elif (i == 6):
|
||||
driver = vals[i]
|
||||
elif (i == 7):
|
||||
gpu_name = vals[i]
|
||||
elif (i == 8):
|
||||
serial = vals[i]
|
||||
elif (i == 9):
|
||||
display_active = vals[i]
|
||||
elif (i == 10):
|
||||
display_mode = vals[i]
|
||||
elif (i == 11):
|
||||
temp_gpu = safeFloatCast(vals[i]);
|
||||
deviceIds = int(vals[0])
|
||||
uuid = vals[1]
|
||||
gpuUtil = safeFloatCast(vals[2]) / 100
|
||||
memTotal = safeFloatCast(vals[3])
|
||||
memUsed = safeFloatCast(vals[4])
|
||||
memFree = safeFloatCast(vals[5])
|
||||
driver = vals[6]
|
||||
gpu_name = vals[7]
|
||||
serial = vals[8]
|
||||
display_active = vals[9]
|
||||
display_mode = vals[10]
|
||||
temp_gpu = safeFloatCast(vals[11]);
|
||||
GPUs.append(GPU(deviceIds, uuid, gpuUtil, memTotal, memUsed, memFree, driver, gpu_name, serial, display_mode, display_active, temp_gpu))
|
||||
return GPUs # (deviceIds, gpuUtil, memUtil)
|
||||
|
||||
|
||||
|
||||
def getGPUProcesses():
|
||||
"""Get all gpu compute processes."""
|
||||
|
||||
global gpuUuidToIdMap
|
||||
gpuUuidToIdMap = {}
|
||||
try:
|
||||
gpus = getGPUs()
|
||||
for gpu in gpus:
|
||||
gpuUuidToIdMap[gpu.uuid] = gpu.id
|
||||
del gpus
|
||||
except:
|
||||
pass
|
||||
|
||||
|
||||
nvidia_smi = getNvidiaSmiCmd()
|
||||
try:
|
||||
p = subprocess.run([
|
||||
nvidia_smi,
|
||||
"--query-compute-apps=pid,process_name,gpu_uuid,gpu_name,used_memory",
|
||||
"--format=csv,noheader,nounits"
|
||||
], stdout=subprocess.PIPE, encoding='utf8')
|
||||
stdout, stderror = p.stdout, p.stderr
|
||||
except:
|
||||
return []
|
||||
output = stdout
|
||||
## Parse output
|
||||
# Split on line break
|
||||
lines = output.split(os.linesep)
|
||||
numProcesses = len(lines) - 1
|
||||
processes = []
|
||||
for g in range(numProcesses):
|
||||
line = lines[g]
|
||||
#print(line)
|
||||
vals = line.split(', ')
|
||||
#print(vals)
|
||||
pid = int(vals[0])
|
||||
processName = vals[1]
|
||||
gpuUuid = vals[2]
|
||||
gpuName = vals[3]
|
||||
usedMemory = safeFloatCast(vals[4])
|
||||
gpuId = gpuUuidToIdMap[gpuUuid]
|
||||
if gpuId is None:
|
||||
gpuId = -1
|
||||
|
||||
# get uid and uname owner of the pid
|
||||
try:
|
||||
p = subprocess.run(['ps', f'-p{pid}', '-oruid=,ruser='],
|
||||
stdout=subprocess.PIPE, encoding='utf8')
|
||||
uid, uname = p.stdout.split()
|
||||
uid = int(uid)
|
||||
except:
|
||||
uid, uname = -1, ''
|
||||
|
||||
processes.append(GPUProcess(pid, processName, gpuId, gpuUuid,
|
||||
gpuName, usedMemory, uid, uname))
|
||||
return processes
|
||||
|
||||
|
||||
def getAvailable(order = 'first', limit=1, maxLoad=0.5, maxMemory=0.5, memoryFree=0, includeNan=False, excludeID=[], excludeUUID=[]):
|
||||
# order = first | last | random | load | memory
|
||||
# first --> select the GPU with the lowest ID (DEFAULT)
|
||||
# last --> select the GPU with the highest ID
|
||||
# random --> select a random available GPU
|
||||
# load --> select the GPU with the lowest load
|
||||
# memory --> select the GPU with the most memory available
|
||||
# limit = 1 (DEFAULT), 2, ..., Inf
|
||||
# Limit sets the upper limit for the number of GPUs to return. E.g. if limit = 2, but only one is available, only one is returned.
|
||||
# Get device IDs, load and memory usage
|
||||
GPUs = getGPUs()
|
||||
# Determine, which GPUs are available
|
||||
GPUavailability = getAvailability(GPUs, maxLoad=maxLoad, maxMemory=maxMemory, memoryFree=memoryFree, includeNan=includeNan, excludeID=excludeID, excludeUUID=excludeUUID)
|
||||
availAbleGPUindex = [idx for idx in range(0,len(GPUavailability)) if (GPUavailability[idx] == 1)]
|
||||
# Discard unavailable GPUs
|
||||
GPUs = [GPUs[g] for g in availAbleGPUindex]
|
||||
# Sort available GPUs according to the order argument
|
||||
if (order == 'first'):
|
||||
GPUs.sort(key=lambda x: float('inf') if math.isnan(x.id) else x.id, reverse=False)
|
||||
elif (order == 'last'):
|
||||
GPUs.sort(key=lambda x: float('-inf') if math.isnan(x.id) else x.id, reverse=True)
|
||||
elif (order == 'random'):
|
||||
GPUs = [GPUs[g] for g in random.sample(range(0,len(GPUs)),len(GPUs))]
|
||||
elif (order == 'load'):
|
||||
GPUs.sort(key=lambda x: float('inf') if math.isnan(x.load) else x.load, reverse=False)
|
||||
elif (order == 'memory'):
|
||||
GPUs.sort(key=lambda x: float('inf') if math.isnan(x.memoryUtil) else x.memoryUtil, reverse=False)
|
||||
# Extract the number of desired GPUs, but limited to the total number of available GPUs
|
||||
GPUs = GPUs[0:min(limit, len(GPUs))]
|
||||
# Extract the device IDs from the GPUs and return them
|
||||
deviceIds = [gpu.id for gpu in GPUs]
|
||||
return deviceIds
|
||||
#def getAvailability(GPUs, maxLoad = 0.5, maxMemory = 0.5, includeNan = False):
|
||||
# # Determine, which GPUs are available
|
||||
# GPUavailability = np.zeros(len(GPUs))
|
||||
# for i in range(len(GPUs)):
|
||||
# if (GPUs[i].load < maxLoad or (includeNan and np.isnan(GPUs[i].load))) and (GPUs[i].memoryUtil < maxMemory or (includeNan and np.isnan(GPUs[i].memoryUtil))):
|
||||
# GPUavailability[i] = 1
|
||||
def getAvailability(GPUs, maxLoad=0.5, maxMemory=0.5, memoryFree=0, includeNan=False, excludeID=[], excludeUUID=[]):
|
||||
# Determine, which GPUs are available
|
||||
GPUavailability = [1 if (gpu.memoryFree>=memoryFree) and (gpu.load < maxLoad or (includeNan and math.isnan(gpu.load))) and (gpu.memoryUtil < maxMemory or (includeNan and math.isnan(gpu.memoryUtil))) and ((gpu.id not in excludeID) and (gpu.uuid not in excludeUUID)) else 0 for gpu in GPUs]
|
||||
return GPUavailability
|
||||
def getFirstAvailable(order = 'first', maxLoad=0.5, maxMemory=0.5, attempts=1, interval=900, verbose=False, includeNan=False, excludeID=[], excludeUUID=[]):
|
||||
#GPUs = getGPUs()
|
||||
#firstAvailableGPU = np.NaN
|
||||
#for i in range(len(GPUs)):
|
||||
# if (GPUs[i].load < maxLoad) & (GPUs[i].memory < maxMemory):
|
||||
# firstAvailableGPU = GPUs[i].id
|
||||
# break
|
||||
#return firstAvailableGPU
|
||||
for i in range(attempts):
|
||||
if (verbose):
|
||||
print('Attempting (' + str(i+1) + '/' + str(attempts) + ') to locate available GPU.')
|
||||
# Get first available GPU
|
||||
available = getAvailable(order=order, limit=1, maxLoad=maxLoad, maxMemory=maxMemory, includeNan=includeNan, excludeID=excludeID, excludeUUID=excludeUUID)
|
||||
# If an available GPU was found, break for loop.
|
||||
if (available):
|
||||
if (verbose):
|
||||
print('GPU ' + str(available) + ' located!')
|
||||
break
|
||||
# If this is not the last attempt, sleep for 'interval' seconds
|
||||
if (i != attempts-1):
|
||||
time.sleep(interval)
|
||||
# Check if an GPU was found, or if the attempts simply ran out. Throw error, if no GPU was found
|
||||
if (not(available)):
|
||||
raise RuntimeError('Could not find an available GPU after ' + str(attempts) + ' attempts with ' + str(interval) + ' seconds interval.')
|
||||
# Return found GPU
|
||||
return available
|
||||
def showUtilization(all=False, attrList=None, useOldCode=False):
|
||||
GPUs = getGPUs()
|
||||
if (all):
|
||||
if (useOldCode):
|
||||
print(' ID | Name | Serial | UUID || GPU util. | Memory util. || Memory total | Memory used | Memory free || Display mode | Display active |')
|
||||
print('------------------------------------------------------------------------------------------------------------------------------')
|
||||
for gpu in GPUs:
|
||||
print(' {0:2d} | {1:s} | {2:s} | {3:s} || {4:3.0f}% | {5:3.0f}% || {6:.0f}MB | {7:.0f}MB | {8:.0f}MB || {9:s} | {10:s}'.format(gpu.id,gpu.name,gpu.serial,gpu.uuid,gpu.load*100,gpu.memoryUtil*100,gpu.memoryTotal,gpu.memoryUsed,gpu.memoryFree,gpu.display_mode,gpu.display_active))
|
||||
else:
|
||||
attrList = [[{'attr':'id','name':'ID'},
|
||||
{'attr':'name','name':'Name'},
|
||||
{'attr':'serial','name':'Serial'},
|
||||
{'attr':'uuid','name':'UUID'}],
|
||||
[{'attr':'temperature','name':'GPU temp.','suffix':'C','transform': lambda x: x,'precision':0},
|
||||
{'attr':'load','name':'GPU util.','suffix':'%','transform': lambda x: x*100,'precision':0},
|
||||
{'attr':'memoryUtil','name':'Memory util.','suffix':'%','transform': lambda x: x*100,'precision':0}],
|
||||
[{'attr':'memoryTotal','name':'Memory total','suffix':'MB','precision':0},
|
||||
{'attr':'memoryUsed','name':'Memory used','suffix':'MB','precision':0},
|
||||
{'attr':'memoryFree','name':'Memory free','suffix':'MB','precision':0}],
|
||||
[{'attr':'display_mode','name':'Display mode'},
|
||||
{'attr':'display_active','name':'Display active'}]]
|
||||
|
||||
else:
|
||||
if (useOldCode):
|
||||
print(' ID GPU MEM')
|
||||
print('--------------')
|
||||
for gpu in GPUs:
|
||||
print(' {0:2d} {1:3.0f}% {2:3.0f}%'.format(gpu.id, gpu.load*100, gpu.memoryUtil*100))
|
||||
else:
|
||||
attrList = [[{'attr':'id','name':'ID'},
|
||||
{'attr':'load','name':'GPU','suffix':'%','transform': lambda x: x*100,'precision':0},
|
||||
{'attr':'memoryUtil','name':'MEM','suffix':'%','transform': lambda x: x*100,'precision':0}],
|
||||
]
|
||||
|
||||
if (not useOldCode):
|
||||
if (attrList is not None):
|
||||
headerString = ''
|
||||
GPUstrings = ['']*len(GPUs)
|
||||
for attrGroup in attrList:
|
||||
#print(attrGroup)
|
||||
for attrDict in attrGroup:
|
||||
headerString = headerString + '| ' + attrDict['name'] + ' '
|
||||
headerWidth = len(attrDict['name'])
|
||||
minWidth = len(attrDict['name'])
|
||||
|
||||
attrPrecision = '.' + str(attrDict['precision']) if ('precision' in attrDict.keys()) else ''
|
||||
attrSuffix = str(attrDict['suffix']) if ('suffix' in attrDict.keys()) else ''
|
||||
attrTransform = attrDict['transform'] if ('transform' in attrDict.keys()) else lambda x : x
|
||||
for gpu in GPUs:
|
||||
attr = getattr(gpu,attrDict['attr'])
|
||||
|
||||
attr = attrTransform(attr)
|
||||
|
||||
if (isinstance(attr,float)):
|
||||
attrStr = ('{0:' + attrPrecision + 'f}').format(attr)
|
||||
elif (isinstance(attr,int)):
|
||||
attrStr = ('{0:d}').format(attr)
|
||||
elif (isinstance(attr,str)):
|
||||
attrStr = attr;
|
||||
elif (sys.version_info[0] == 2):
|
||||
if (isinstance(attr,unicode)):
|
||||
attrStr = attr.encode('ascii','ignore')
|
||||
else:
|
||||
raise TypeError('Unhandled object type (' + str(type(attr)) + ') for attribute \'' + attrDict['name'] + '\'')
|
||||
|
||||
attrStr += attrSuffix
|
||||
|
||||
minWidth = max(minWidth,len(attrStr))
|
||||
|
||||
headerString += ' '*max(0,minWidth-headerWidth)
|
||||
|
||||
minWidthStr = str(minWidth - len(attrSuffix))
|
||||
|
||||
for gpuIdx,gpu in enumerate(GPUs):
|
||||
attr = getattr(gpu,attrDict['attr'])
|
||||
|
||||
attr = attrTransform(attr)
|
||||
|
||||
if (isinstance(attr,float)):
|
||||
attrStr = ('{0:'+ minWidthStr + attrPrecision + 'f}').format(attr)
|
||||
elif (isinstance(attr,int)):
|
||||
attrStr = ('{0:' + minWidthStr + 'd}').format(attr)
|
||||
elif (isinstance(attr,str)):
|
||||
attrStr = ('{0:' + minWidthStr + 's}').format(attr);
|
||||
elif (sys.version_info[0] == 2):
|
||||
if (isinstance(attr,unicode)):
|
||||
attrStr = ('{0:' + minWidthStr + 's}').format(attr.encode('ascii','ignore'))
|
||||
else:
|
||||
raise TypeError('Unhandled object type (' + str(type(attr)) + ') for attribute \'' + attrDict['name'] + '\'')
|
||||
|
||||
attrStr += attrSuffix
|
||||
|
||||
GPUstrings[gpuIdx] += '| ' + attrStr + ' '
|
||||
|
||||
headerString = headerString + '|'
|
||||
for gpuIdx,gpu in enumerate(GPUs):
|
||||
GPUstrings[gpuIdx] += '|'
|
||||
|
||||
headerSpacingString = '-' * len(headerString)
|
||||
print(headerString)
|
||||
print(headerSpacingString)
|
||||
for GPUstring in GPUstrings:
|
||||
print(GPUstring)
|
||||
|
||||
|
||||
# Generate gpu uuid to id map
|
||||
gpuUuidToIdMap = {}
|
||||
try:
|
||||
gpus = getGPUs()
|
||||
for gpu in gpus:
|
||||
gpuUuidToIdMap[gpu.uuid] = gpu.id
|
||||
del gpus
|
||||
except:
|
||||
pass
|
||||
def getGPUInfos():
|
||||
###返回gpus:list,一个GPU为一个元素-对象
|
||||
###########:有属性,'id','load','memoryFree',
|
||||
###########:'memoryTotal','memoryUsed','memoryUtil','name','serial''temperature','uuid',process
|
||||
###其中process:每一个计算进程是一个元素--对象
|
||||
############:有属性,'gpuId','gpuName','gpuUuid',
|
||||
############:'gpuid','pid','processName','uid', 'uname','usedMemory'
|
||||
gpus = getGPUs()
|
||||
gpuUuidToIdMap={}
|
||||
for gpu in gpus:
|
||||
gpuUuidToIdMap[gpu.uuid] = gpu.id
|
||||
gpu.process=[]
|
||||
indexx = [x.id for x in gpus ]
|
||||
|
||||
process = getGPUProcesses()
|
||||
for pre in process:
|
||||
pre.gpuid = gpuUuidToIdMap[pre.gpuUuid]
|
||||
gpuId = indexx.index(pre.gpuid )
|
||||
gpus[gpuId].process.append(pre )
|
||||
return gpus
|
||||
|
||||
def get_available_gpu(gpuStatus):
|
||||
##判断是否有空闲的显卡,如果有返回id,没有返回None
|
||||
cuda=None
|
||||
for gpus in gpuStatus:
|
||||
if len(gpus.process) == 0:
|
||||
cuda = gpus.id
|
||||
return cuda
|
||||
return cuda
|
||||
def get_whether_gpuProcess():
|
||||
##判断是否有空闲的显卡,如果有返回id,没有返回None
|
||||
gpuStatus=getGPUInfos()
|
||||
gpuProcess=True
|
||||
for gpus in gpuStatus:
|
||||
if len(gpus.process) != 0:
|
||||
gpuProcess = False
|
||||
return gpuProcess
|
||||
|
||||
def get_offlineProcess_gpu(gpuStatus,pidInfos):
|
||||
gpu_onLine = []
|
||||
for gpu in gpuStatus:
|
||||
for gpuProcess in gpu.process:
|
||||
pid = gpuProcess.pid
|
||||
if pid in pidInfos.keys():
|
||||
pidType = pidInfos[pid]['type']
|
||||
if pidType == 'onLine':
|
||||
gpu_onLine.append(gpu)
|
||||
gpu_offLine = set(gpuStatus) - set(gpu_onLine)
|
||||
return list(gpu_offLine)
|
||||
def arrange_offlineProcess(gpuStatus,pidInfos,modelMemory=1500):
|
||||
cudaArrange=[]
|
||||
gpu_offLine = get_offlineProcess_gpu(gpuStatus,pidInfos)
|
||||
for gpu in gpu_offLine:
|
||||
leftMemory = gpu.memoryTotal*0.9 - gpu.memoryUsed
|
||||
modelCnt = int(leftMemory// modelMemory)
|
||||
|
||||
cudaArrange.extend( [gpu.id] * modelCnt )
|
||||
return cudaArrange
|
||||
def get_potential_gpu(gpuStatus,pidInfos):
|
||||
###所有GPU上都有计算。需要为“在线任务”空出一块显卡。
|
||||
###step1:查看所有显卡上是否有“在线任务”
|
||||
|
||||
gpu_offLine = get_offlineProcess_gpu(gpuStatus,pidInfos)
|
||||
if len(gpu_offLine) == 0 :
|
||||
return False
|
||||
|
||||
###step2,找出每张显卡上离线进程的数目
|
||||
offLineCnt = [ len(gpu.process) for gpu in gpu_offLine ]
|
||||
minCntIndex =offLineCnt.index( min(offLineCnt))
|
||||
|
||||
pids = [x.pid for x in gpu_offLine[minCntIndex].process]
|
||||
return {'cuda':gpu_offLine[minCntIndex].id,'pids':pids }
|
||||
if __name__=='__main__':
|
||||
#pres = getGPUProcesses()
|
||||
#print('###line404:',pres)
|
||||
gpus = getGPUs()
|
||||
for gpu in gpus:
|
||||
gpuUuidToIdMap[gpu.uuid] = gpu.id
|
||||
print(gpu)
|
||||
print(gpuUuidToIdMap)
|
||||
pres = getGPUProcesses()
|
||||
print('###line404:',pres)
|
||||
for pre in pres:
|
||||
print('#'*20)
|
||||
for ken in ['gpuName','gpuUuid','pid','processName','uid','uname','usedMemory' ]:
|
||||
print(ken,' ',pre.__getattribute__(ken ))
|
||||
print(' ')
|
||||
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -0,0 +1 @@
|
|||
from . import nn, models, utils, data
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -0,0 +1,23 @@
|
|||
"""
|
||||
This module provides data loaders and transformers for popular vision datasets.
|
||||
"""
|
||||
from .mscoco import COCOSegmentation
|
||||
from .cityscapes import CitySegmentation
|
||||
from .ade import ADE20KSegmentation
|
||||
from .pascal_voc import VOCSegmentation
|
||||
from .pascal_aug import VOCAugSegmentation
|
||||
from .sbu_shadow import SBUSegmentation
|
||||
|
||||
datasets = {
|
||||
'ade20k': ADE20KSegmentation,
|
||||
'pascal_voc': VOCSegmentation,
|
||||
'pascal_aug': VOCAugSegmentation,
|
||||
'coco': COCOSegmentation,
|
||||
'citys': CitySegmentation,
|
||||
'sbu': SBUSegmentation,
|
||||
}
|
||||
|
||||
|
||||
def get_segmentation_dataset(name, **kwargs):
|
||||
"""Segmentation Datasets"""
|
||||
return datasets[name.lower()](**kwargs)
|
||||
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.
|
|
@ -0,0 +1,172 @@
|
|||
"""Pascal ADE20K Semantic Segmentation Dataset."""
|
||||
import os
|
||||
import torch
|
||||
import numpy as np
|
||||
|
||||
from PIL import Image
|
||||
from .segbase import SegmentationDataset
|
||||
|
||||
|
||||
class ADE20KSegmentation(SegmentationDataset):
|
||||
"""ADE20K Semantic Segmentation Dataset.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
root : string
|
||||
Path to ADE20K folder. Default is './datasets/ade'
|
||||
split: string
|
||||
'train', 'val' or 'test'
|
||||
transform : callable, optional
|
||||
A function that transforms the image
|
||||
Examples
|
||||
--------
|
||||
>>> from torchvision import transforms
|
||||
>>> import torch.utils.data as data
|
||||
>>> # Transforms for Normalization
|
||||
>>> input_transform = transforms.Compose([
|
||||
>>> transforms.ToTensor(),
|
||||
>>> transforms.Normalize((.485, .456, .406), (.229, .224, .225)),
|
||||
>>> ])
|
||||
>>> # Create Dataset
|
||||
>>> trainset = ADE20KSegmentation(split='train', transform=input_transform)
|
||||
>>> # Create Training Loader
|
||||
>>> train_data = data.DataLoader(
|
||||
>>> trainset, 4, shuffle=True,
|
||||
>>> num_workers=4)
|
||||
"""
|
||||
BASE_DIR = 'ADEChallengeData2016'
|
||||
NUM_CLASS = 150
|
||||
|
||||
def __init__(self, root='../datasets/ade', split='test', mode=None, transform=None, **kwargs):
|
||||
super(ADE20KSegmentation, self).__init__(root, split, mode, transform, **kwargs)
|
||||
root = os.path.join(root, self.BASE_DIR)
|
||||
assert os.path.exists(root), "Please setup the dataset using ../datasets/ade20k.py"
|
||||
self.images, self.masks = _get_ade20k_pairs(root, split)
|
||||
assert (len(self.images) == len(self.masks))
|
||||
if len(self.images) == 0:
|
||||
raise RuntimeError("Found 0 images in subfolders of:" + root + "\n")
|
||||
print('Found {} images in the folder {}'.format(len(self.images), root))
|
||||
|
||||
def __getitem__(self, index):
|
||||
img = Image.open(self.images[index]).convert('RGB')
|
||||
if self.mode == 'test':
|
||||
img = self._img_transform(img)
|
||||
if self.transform is not None:
|
||||
img = self.transform(img)
|
||||
return img, os.path.basename(self.images[index])
|
||||
mask = Image.open(self.masks[index])
|
||||
# synchrosized transform
|
||||
if self.mode == 'train':
|
||||
img, mask = self._sync_transform(img, mask)
|
||||
elif self.mode == 'val':
|
||||
img, mask = self._val_sync_transform(img, mask)
|
||||
else:
|
||||
assert self.mode == 'testval'
|
||||
img, mask = self._img_transform(img), self._mask_transform(mask)
|
||||
# general resize, normalize and to Tensor
|
||||
if self.transform is not None:
|
||||
img = self.transform(img)
|
||||
return img, mask, os.path.basename(self.images[index])
|
||||
|
||||
def _mask_transform(self, mask):
|
||||
return torch.LongTensor(np.array(mask).astype('int32') - 1)
|
||||
|
||||
def __len__(self):
|
||||
return len(self.images)
|
||||
|
||||
@property
|
||||
def pred_offset(self):
|
||||
return 1
|
||||
|
||||
@property
|
||||
def classes(self):
|
||||
"""Category names."""
|
||||
return ("wall", "building, edifice", "sky", "floor, flooring", "tree",
|
||||
"ceiling", "road, route", "bed", "windowpane, window", "grass",
|
||||
"cabinet", "sidewalk, pavement",
|
||||
"person, individual, someone, somebody, mortal, soul",
|
||||
"earth, ground", "door, double door", "table", "mountain, mount",
|
||||
"plant, flora, plant life", "curtain, drape, drapery, mantle, pall",
|
||||
"chair", "car, auto, automobile, machine, motorcar",
|
||||
"water", "painting, picture", "sofa, couch, lounge", "shelf",
|
||||
"house", "sea", "mirror", "rug, carpet, carpeting", "field", "armchair",
|
||||
"seat", "fence, fencing", "desk", "rock, stone", "wardrobe, closet, press",
|
||||
"lamp", "bathtub, bathing tub, bath, tub", "railing, rail", "cushion",
|
||||
"base, pedestal, stand", "box", "column, pillar", "signboard, sign",
|
||||
"chest of drawers, chest, bureau, dresser", "counter", "sand", "sink",
|
||||
"skyscraper", "fireplace, hearth, open fireplace", "refrigerator, icebox",
|
||||
"grandstand, covered stand", "path", "stairs, steps", "runway",
|
||||
"case, display case, showcase, vitrine",
|
||||
"pool table, billiard table, snooker table", "pillow",
|
||||
"screen door, screen", "stairway, staircase", "river", "bridge, span",
|
||||
"bookcase", "blind, screen", "coffee table, cocktail table",
|
||||
"toilet, can, commode, crapper, pot, potty, stool, throne",
|
||||
"flower", "book", "hill", "bench", "countertop",
|
||||
"stove, kitchen stove, range, kitchen range, cooking stove",
|
||||
"palm, palm tree", "kitchen island",
|
||||
"computer, computing machine, computing device, data processor, "
|
||||
"electronic computer, information processing system",
|
||||
"swivel chair", "boat", "bar", "arcade machine",
|
||||
"hovel, hut, hutch, shack, shanty",
|
||||
"bus, autobus, coach, charabanc, double-decker, jitney, motorbus, "
|
||||
"motorcoach, omnibus, passenger vehicle",
|
||||
"towel", "light, light source", "truck, motortruck", "tower",
|
||||
"chandelier, pendant, pendent", "awning, sunshade, sunblind",
|
||||
"streetlight, street lamp", "booth, cubicle, stall, kiosk",
|
||||
"television receiver, television, television set, tv, tv set, idiot "
|
||||
"box, boob tube, telly, goggle box",
|
||||
"airplane, aeroplane, plane", "dirt track",
|
||||
"apparel, wearing apparel, dress, clothes",
|
||||
"pole", "land, ground, soil",
|
||||
"bannister, banister, balustrade, balusters, handrail",
|
||||
"escalator, moving staircase, moving stairway",
|
||||
"ottoman, pouf, pouffe, puff, hassock",
|
||||
"bottle", "buffet, counter, sideboard",
|
||||
"poster, posting, placard, notice, bill, card",
|
||||
"stage", "van", "ship", "fountain",
|
||||
"conveyer belt, conveyor belt, conveyer, conveyor, transporter",
|
||||
"canopy", "washer, automatic washer, washing machine",
|
||||
"plaything, toy", "swimming pool, swimming bath, natatorium",
|
||||
"stool", "barrel, cask", "basket, handbasket", "waterfall, falls",
|
||||
"tent, collapsible shelter", "bag", "minibike, motorbike", "cradle",
|
||||
"oven", "ball", "food, solid food", "step, stair", "tank, storage tank",
|
||||
"trade name, brand name, brand, marque", "microwave, microwave oven",
|
||||
"pot, flowerpot", "animal, animate being, beast, brute, creature, fauna",
|
||||
"bicycle, bike, wheel, cycle", "lake",
|
||||
"dishwasher, dish washer, dishwashing machine",
|
||||
"screen, silver screen, projection screen",
|
||||
"blanket, cover", "sculpture", "hood, exhaust hood", "sconce", "vase",
|
||||
"traffic light, traffic signal, stoplight", "tray",
|
||||
"ashcan, trash can, garbage can, wastebin, ash bin, ash-bin, ashbin, "
|
||||
"dustbin, trash barrel, trash bin",
|
||||
"fan", "pier, wharf, wharfage, dock", "crt screen",
|
||||
"plate", "monitor, monitoring device", "bulletin board, notice board",
|
||||
"shower", "radiator", "glass, drinking glass", "clock", "flag")
|
||||
|
||||
|
||||
def _get_ade20k_pairs(folder, mode='train'):
|
||||
img_paths = []
|
||||
mask_paths = []
|
||||
if mode == 'train':
|
||||
img_folder = os.path.join(folder, 'images/training')
|
||||
mask_folder = os.path.join(folder, 'annotations/training')
|
||||
else:
|
||||
img_folder = os.path.join(folder, 'images/validation')
|
||||
mask_folder = os.path.join(folder, 'annotations/validation')
|
||||
for filename in os.listdir(img_folder):
|
||||
basename, _ = os.path.splitext(filename)
|
||||
if filename.endswith(".jpg"):
|
||||
imgpath = os.path.join(img_folder, filename)
|
||||
maskname = basename + '.png'
|
||||
maskpath = os.path.join(mask_folder, maskname)
|
||||
if os.path.isfile(maskpath):
|
||||
img_paths.append(imgpath)
|
||||
mask_paths.append(maskpath)
|
||||
else:
|
||||
print('cannot find the mask:', maskpath)
|
||||
|
||||
return img_paths, mask_paths
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
train_dataset = ADE20KSegmentation()
|
||||
|
|
@ -0,0 +1,137 @@
|
|||
"""Prepare Cityscapes dataset"""
|
||||
import os
|
||||
import torch
|
||||
import numpy as np
|
||||
|
||||
from PIL import Image
|
||||
from .segbase import SegmentationDataset
|
||||
|
||||
|
||||
class CitySegmentation(SegmentationDataset):
|
||||
"""Cityscapes Semantic Segmentation Dataset.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
root : string
|
||||
Path to Cityscapes folder. Default is './datasets/citys'
|
||||
split: string
|
||||
'train', 'val' or 'test'
|
||||
transform : callable, optional
|
||||
A function that transforms the image
|
||||
Examples
|
||||
--------
|
||||
>>> from torchvision import transforms
|
||||
>>> import torch.utils.data as data
|
||||
>>> # Transforms for Normalization
|
||||
>>> input_transform = transforms.Compose([
|
||||
>>> transforms.ToTensor(),
|
||||
>>> transforms.Normalize((.485, .456, .406), (.229, .224, .225)),
|
||||
>>> ])
|
||||
>>> # Create Dataset
|
||||
>>> trainset = CitySegmentation(split='train', transform=input_transform)
|
||||
>>> # Create Training Loader
|
||||
>>> train_data = data.DataLoader(
|
||||
>>> trainset, 4, shuffle=True,
|
||||
>>> num_workers=4)
|
||||
"""
|
||||
BASE_DIR = 'cityscapes'
|
||||
NUM_CLASS = 19
|
||||
|
||||
def __init__(self, root='../datasets/citys', split='train', mode=None, transform=None, **kwargs):
|
||||
super(CitySegmentation, self).__init__(root, split, mode, transform, **kwargs)
|
||||
# self.root = os.path.join(root, self.BASE_DIR)
|
||||
assert os.path.exists(self.root), "Please setup the dataset using ../datasets/cityscapes.py"
|
||||
self.images, self.mask_paths = _get_city_pairs(self.root, self.split)
|
||||
assert (len(self.images) == len(self.mask_paths))
|
||||
if len(self.images) == 0:
|
||||
raise RuntimeError("Found 0 images in subfolders of:" + root + "\n")
|
||||
self.valid_classes = [7, 8, 11, 12, 13, 17, 19, 20, 21, 22,
|
||||
23, 24, 25, 26, 27, 28, 31, 32, 33]
|
||||
self._key = np.array([-1, -1, -1, -1, -1, -1,
|
||||
-1, -1, 0, 1, -1, -1,
|
||||
2, 3, 4, -1, -1, -1,
|
||||
5, -1, 6, 7, 8, 9,
|
||||
10, 11, 12, 13, 14, 15,
|
||||
-1, -1, 16, 17, 18])
|
||||
self._mapping = np.array(range(-1, len(self._key) - 1)).astype('int32')
|
||||
|
||||
def _class_to_index(self, mask):
|
||||
# assert the value
|
||||
values = np.unique(mask)
|
||||
for value in values:
|
||||
assert (value in self._mapping)
|
||||
index = np.digitize(mask.ravel(), self._mapping, right=True)
|
||||
return self._key[index].reshape(mask.shape)
|
||||
|
||||
def __getitem__(self, index):
|
||||
img = Image.open(self.images[index]).convert('RGB')
|
||||
if self.mode == 'test':
|
||||
if self.transform is not None:
|
||||
img = self.transform(img)
|
||||
return img, os.path.basename(self.images[index])
|
||||
mask = Image.open(self.mask_paths[index])
|
||||
# synchrosized transform
|
||||
if self.mode == 'train':
|
||||
img, mask = self._sync_transform(img, mask)
|
||||
elif self.mode == 'val':
|
||||
img, mask = self._val_sync_transform(img, mask)
|
||||
else:
|
||||
assert self.mode == 'testval'
|
||||
img, mask = self._img_transform(img), self._mask_transform(mask)
|
||||
# general resize, normalize and toTensor
|
||||
if self.transform is not None:
|
||||
img = self.transform(img)
|
||||
return img, mask, os.path.basename(self.images[index])
|
||||
|
||||
def _mask_transform(self, mask):
|
||||
target = self._class_to_index(np.array(mask).astype('int32'))
|
||||
return torch.LongTensor(np.array(target).astype('int32'))
|
||||
|
||||
def __len__(self):
|
||||
return len(self.images)
|
||||
|
||||
@property
|
||||
def pred_offset(self):
|
||||
return 0
|
||||
|
||||
|
||||
def _get_city_pairs(folder, split='train'):
|
||||
def get_path_pairs(img_folder, mask_folder):
|
||||
img_paths = []
|
||||
mask_paths = []
|
||||
for root, _, files in os.walk(img_folder):
|
||||
for filename in files:
|
||||
if filename.endswith('.png'):
|
||||
imgpath = os.path.join(root, filename)
|
||||
foldername = os.path.basename(os.path.dirname(imgpath))
|
||||
maskname = filename.replace('leftImg8bit', 'gtFine_labelIds')
|
||||
maskpath = os.path.join(mask_folder, foldername, maskname)
|
||||
if os.path.isfile(imgpath) and os.path.isfile(maskpath):
|
||||
img_paths.append(imgpath)
|
||||
mask_paths.append(maskpath)
|
||||
else:
|
||||
print('cannot find the mask or image:', imgpath, maskpath)
|
||||
print('Found {} images in the folder {}'.format(len(img_paths), img_folder))
|
||||
return img_paths, mask_paths
|
||||
|
||||
if split in ('train', 'val'):
|
||||
img_folder = os.path.join(folder, 'leftImg8bit/' + split)
|
||||
mask_folder = os.path.join(folder, 'gtFine/' + split)
|
||||
img_paths, mask_paths = get_path_pairs(img_folder, mask_folder)
|
||||
return img_paths, mask_paths
|
||||
else:
|
||||
assert split == 'trainval'
|
||||
print('trainval set')
|
||||
train_img_folder = os.path.join(folder, 'leftImg8bit/train')
|
||||
train_mask_folder = os.path.join(folder, 'gtFine/train')
|
||||
val_img_folder = os.path.join(folder, 'leftImg8bit/val')
|
||||
val_mask_folder = os.path.join(folder, 'gtFine/val')
|
||||
train_img_paths, train_mask_paths = get_path_pairs(train_img_folder, train_mask_folder)
|
||||
val_img_paths, val_mask_paths = get_path_pairs(val_img_folder, val_mask_folder)
|
||||
img_paths = train_img_paths + val_img_paths
|
||||
mask_paths = train_mask_paths + val_mask_paths
|
||||
return img_paths, mask_paths
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
dataset = CitySegmentation()
|
||||
|
|
@ -0,0 +1,90 @@
|
|||
"""Look into Person Dataset"""
|
||||
import os
|
||||
import torch
|
||||
import numpy as np
|
||||
|
||||
from PIL import Image
|
||||
from core.data.dataloader.segbase import SegmentationDataset
|
||||
|
||||
|
||||
class LIPSegmentation(SegmentationDataset):
|
||||
"""Look into person parsing dataset """
|
||||
|
||||
BASE_DIR = 'LIP'
|
||||
NUM_CLASS = 20
|
||||
|
||||
def __init__(self, root='../datasets/LIP', split='train', mode=None, transform=None, **kwargs):
|
||||
super(LIPSegmentation, self).__init__(root, split, mode, transform, **kwargs)
|
||||
_trainval_image_dir = os.path.join(root, 'TrainVal_images')
|
||||
_testing_image_dir = os.path.join(root, 'Testing_images')
|
||||
_trainval_mask_dir = os.path.join(root, 'TrainVal_parsing_annotations')
|
||||
if split == 'train':
|
||||
_image_dir = os.path.join(_trainval_image_dir, 'train_images')
|
||||
_mask_dir = os.path.join(_trainval_mask_dir, 'train_segmentations')
|
||||
_split_f = os.path.join(_trainval_image_dir, 'train_id.txt')
|
||||
elif split == 'val':
|
||||
_image_dir = os.path.join(_trainval_image_dir, 'val_images')
|
||||
_mask_dir = os.path.join(_trainval_mask_dir, 'val_segmentations')
|
||||
_split_f = os.path.join(_trainval_image_dir, 'val_id.txt')
|
||||
elif split == 'test':
|
||||
_image_dir = os.path.join(_testing_image_dir, 'testing_images')
|
||||
_split_f = os.path.join(_testing_image_dir, 'test_id.txt')
|
||||
else:
|
||||
raise RuntimeError('Unknown dataset split.')
|
||||
|
||||
self.images = []
|
||||
self.masks = []
|
||||
with open(os.path.join(_split_f), 'r') as lines:
|
||||
for line in lines:
|
||||
_image = os.path.join(_image_dir, line.rstrip('\n') + '.jpg')
|
||||
assert os.path.isfile(_image)
|
||||
self.images.append(_image)
|
||||
if split != 'test':
|
||||
_mask = os.path.join(_mask_dir, line.rstrip('\n') + '.png')
|
||||
assert os.path.isfile(_mask)
|
||||
self.masks.append(_mask)
|
||||
|
||||
if split != 'test':
|
||||
assert (len(self.images) == len(self.masks))
|
||||
print('Found {} {} images in the folder {}'.format(len(self.images), split, root))
|
||||
|
||||
def __getitem__(self, index):
|
||||
img = Image.open(self.images[index]).convert('RGB')
|
||||
if self.mode == 'test':
|
||||
img = self._img_transform(img)
|
||||
if self.transform is not None:
|
||||
img = self.transform(img)
|
||||
return img, os.path.basename(self.images[index])
|
||||
mask = Image.open(self.masks[index])
|
||||
# synchronized transform
|
||||
if self.mode == 'train':
|
||||
img, mask = self._sync_transform(img, mask)
|
||||
elif self.mode == 'val':
|
||||
img, mask = self._val_sync_transform(img, mask)
|
||||
else:
|
||||
assert self.mode == 'testval'
|
||||
img, mask = self._img_transform(img), self._mask_transform(mask)
|
||||
# general resize, normalize and toTensor
|
||||
if self.transform is not None:
|
||||
img = self.transform(img)
|
||||
|
||||
return img, mask, os.path.basename(self.images[index])
|
||||
|
||||
def __len__(self):
|
||||
return len(self.images)
|
||||
|
||||
def _mask_transform(self, mask):
|
||||
target = np.array(mask).astype('int32')
|
||||
return torch.from_numpy(target).long()
|
||||
|
||||
@property
|
||||
def classes(self):
|
||||
"""Category name."""
|
||||
return ('background', 'hat', 'hair', 'glove', 'sunglasses', 'upperclothes',
|
||||
'dress', 'coat', 'socks', 'pants', 'jumpsuits', 'scarf', 'skirt',
|
||||
'face', 'leftArm', 'rightArm', 'leftLeg', 'rightLeg', 'leftShoe',
|
||||
'rightShoe')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
dataset = LIPSegmentation(base_size=280, crop_size=256)
|
||||
|
|
@ -0,0 +1,136 @@
|
|||
"""MSCOCO Semantic Segmentation pretraining for VOC."""
|
||||
import os
|
||||
import pickle
|
||||
import torch
|
||||
import numpy as np
|
||||
|
||||
from tqdm import trange
|
||||
from PIL import Image
|
||||
from .segbase import SegmentationDataset
|
||||
|
||||
|
||||
class COCOSegmentation(SegmentationDataset):
|
||||
"""COCO Semantic Segmentation Dataset for VOC Pre-training.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
root : string
|
||||
Path to ADE20K folder. Default is './datasets/coco'
|
||||
split: string
|
||||
'train', 'val' or 'test'
|
||||
transform : callable, optional
|
||||
A function that transforms the image
|
||||
Examples
|
||||
--------
|
||||
>>> from torchvision import transforms
|
||||
>>> import torch.utils.data as data
|
||||
>>> # Transforms for Normalization
|
||||
>>> input_transform = transforms.Compose([
|
||||
>>> transforms.ToTensor(),
|
||||
>>> transforms.Normalize((.485, .456, .406), (.229, .224, .225)),
|
||||
>>> ])
|
||||
>>> # Create Dataset
|
||||
>>> trainset = COCOSegmentation(split='train', transform=input_transform)
|
||||
>>> # Create Training Loader
|
||||
>>> train_data = data.DataLoader(
|
||||
>>> trainset, 4, shuffle=True,
|
||||
>>> num_workers=4)
|
||||
"""
|
||||
CAT_LIST = [0, 5, 2, 16, 9, 44, 6, 3, 17, 62, 21, 67, 18, 19, 4,
|
||||
1, 64, 20, 63, 7, 72]
|
||||
NUM_CLASS = 21
|
||||
|
||||
def __init__(self, root='../datasets/coco', split='train', mode=None, transform=None, **kwargs):
|
||||
super(COCOSegmentation, self).__init__(root, split, mode, transform, **kwargs)
|
||||
# lazy import pycocotools
|
||||
from pycocotools.coco import COCO
|
||||
from pycocotools import mask
|
||||
if split == 'train':
|
||||
print('train set')
|
||||
ann_file = os.path.join(root, 'annotations/instances_train2017.json')
|
||||
ids_file = os.path.join(root, 'annotations/train_ids.mx')
|
||||
self.root = os.path.join(root, 'train2017')
|
||||
else:
|
||||
print('val set')
|
||||
ann_file = os.path.join(root, 'annotations/instances_val2017.json')
|
||||
ids_file = os.path.join(root, 'annotations/val_ids.mx')
|
||||
self.root = os.path.join(root, 'val2017')
|
||||
self.coco = COCO(ann_file)
|
||||
self.coco_mask = mask
|
||||
if os.path.exists(ids_file):
|
||||
with open(ids_file, 'rb') as f:
|
||||
self.ids = pickle.load(f)
|
||||
else:
|
||||
ids = list(self.coco.imgs.keys())
|
||||
self.ids = self._preprocess(ids, ids_file)
|
||||
self.transform = transform
|
||||
|
||||
def __getitem__(self, index):
|
||||
coco = self.coco
|
||||
img_id = self.ids[index]
|
||||
img_metadata = coco.loadImgs(img_id)[0]
|
||||
path = img_metadata['file_name']
|
||||
img = Image.open(os.path.join(self.root, path)).convert('RGB')
|
||||
cocotarget = coco.loadAnns(coco.getAnnIds(imgIds=img_id))
|
||||
mask = Image.fromarray(self._gen_seg_mask(
|
||||
cocotarget, img_metadata['height'], img_metadata['width']))
|
||||
# synchrosized transform
|
||||
if self.mode == 'train':
|
||||
img, mask = self._sync_transform(img, mask)
|
||||
elif self.mode == 'val':
|
||||
img, mask = self._val_sync_transform(img, mask)
|
||||
else:
|
||||
assert self.mode == 'testval'
|
||||
img, mask = self._img_transform(img), self._mask_transform(mask)
|
||||
# general resize, normalize and toTensor
|
||||
if self.transform is not None:
|
||||
img = self.transform(img)
|
||||
return img, mask, os.path.basename(self.ids[index])
|
||||
|
||||
def _mask_transform(self, mask):
|
||||
return torch.LongTensor(np.array(mask).astype('int32'))
|
||||
|
||||
def _gen_seg_mask(self, target, h, w):
|
||||
mask = np.zeros((h, w), dtype=np.uint8)
|
||||
coco_mask = self.coco_mask
|
||||
for instance in target:
|
||||
rle = coco_mask.frPyObjects(instance['Segmentation'], h, w)
|
||||
m = coco_mask.decode(rle)
|
||||
cat = instance['category_id']
|
||||
if cat in self.CAT_LIST:
|
||||
c = self.CAT_LIST.index(cat)
|
||||
else:
|
||||
continue
|
||||
if len(m.shape) < 3:
|
||||
mask[:, :] += (mask == 0) * (m * c)
|
||||
else:
|
||||
mask[:, :] += (mask == 0) * (((np.sum(m, axis=2)) > 0) * c).astype(np.uint8)
|
||||
return mask
|
||||
|
||||
def _preprocess(self, ids, ids_file):
|
||||
print("Preprocessing mask, this will take a while." + \
|
||||
"But don't worry, it only run once for each split.")
|
||||
tbar = trange(len(ids))
|
||||
new_ids = []
|
||||
for i in tbar:
|
||||
img_id = ids[i]
|
||||
cocotarget = self.coco.loadAnns(self.coco.getAnnIds(imgIds=img_id))
|
||||
img_metadata = self.coco.loadImgs(img_id)[0]
|
||||
mask = self._gen_seg_mask(cocotarget, img_metadata['height'], img_metadata['width'])
|
||||
# more than 1k pixels
|
||||
if (mask > 0).sum() > 1000:
|
||||
new_ids.append(img_id)
|
||||
tbar.set_description('Doing: {}/{}, got {} qualified images'. \
|
||||
format(i, len(ids), len(new_ids)))
|
||||
print('Found number of qualified images: ', len(new_ids))
|
||||
with open(ids_file, 'wb') as f:
|
||||
pickle.dump(new_ids, f)
|
||||
return new_ids
|
||||
|
||||
@property
|
||||
def classes(self):
|
||||
"""Category names."""
|
||||
return ('background', 'airplane', 'bicycle', 'bird', 'boat', 'bottle',
|
||||
'bus', 'car', 'cat', 'chair', 'cow', 'diningtable', 'dog', 'horse',
|
||||
'motorcycle', 'person', 'potted-plant', 'sheep', 'sofa', 'train',
|
||||
'tv')
|
||||
|
|
@ -0,0 +1,104 @@
|
|||
"""Pascal Augmented VOC Semantic Segmentation Dataset."""
|
||||
import os
|
||||
import torch
|
||||
import scipy.io as sio
|
||||
import numpy as np
|
||||
|
||||
from PIL import Image
|
||||
from .segbase import SegmentationDataset
|
||||
|
||||
|
||||
class VOCAugSegmentation(SegmentationDataset):
|
||||
"""Pascal VOC Augmented Semantic Segmentation Dataset.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
root : string
|
||||
Path to VOCdevkit folder. Default is './datasets/voc'
|
||||
split: string
|
||||
'train', 'val' or 'test'
|
||||
transform : callable, optional
|
||||
A function that transforms the image
|
||||
Examples
|
||||
--------
|
||||
>>> from torchvision import transforms
|
||||
>>> import torch.utils.data as data
|
||||
>>> # Transforms for Normalization
|
||||
>>> input_transform = transforms.Compose([
|
||||
>>> transforms.ToTensor(),
|
||||
>>> transforms.Normalize([.485, .456, .406], [.229, .224, .225]),
|
||||
>>> ])
|
||||
>>> # Create Dataset
|
||||
>>> trainset = VOCAugSegmentation(split='train', transform=input_transform)
|
||||
>>> # Create Training Loader
|
||||
>>> train_data = data.DataLoader(
|
||||
>>> trainset, 4, shuffle=True,
|
||||
>>> num_workers=4)
|
||||
"""
|
||||
BASE_DIR = 'VOCaug/dataset/'
|
||||
NUM_CLASS = 21
|
||||
|
||||
def __init__(self, root='../datasets/voc', split='train', mode=None, transform=None, **kwargs):
|
||||
super(VOCAugSegmentation, self).__init__(root, split, mode, transform, **kwargs)
|
||||
# train/val/test splits are pre-cut
|
||||
_voc_root = os.path.join(root, self.BASE_DIR)
|
||||
_mask_dir = os.path.join(_voc_root, 'cls')
|
||||
_image_dir = os.path.join(_voc_root, 'img')
|
||||
if split == 'train':
|
||||
_split_f = os.path.join(_voc_root, 'trainval.txt')
|
||||
elif split == 'val':
|
||||
_split_f = os.path.join(_voc_root, 'val.txt')
|
||||
else:
|
||||
raise RuntimeError('Unknown dataset split: {}'.format(split))
|
||||
|
||||
self.images = []
|
||||
self.masks = []
|
||||
with open(os.path.join(_split_f), "r") as lines:
|
||||
for line in lines:
|
||||
_image = os.path.join(_image_dir, line.rstrip('\n') + ".jpg")
|
||||
assert os.path.isfile(_image)
|
||||
self.images.append(_image)
|
||||
_mask = os.path.join(_mask_dir, line.rstrip('\n') + ".mat")
|
||||
assert os.path.isfile(_mask)
|
||||
self.masks.append(_mask)
|
||||
|
||||
assert (len(self.images) == len(self.masks))
|
||||
print('Found {} images in the folder {}'.format(len(self.images), _voc_root))
|
||||
|
||||
def __getitem__(self, index):
|
||||
img = Image.open(self.images[index]).convert('RGB')
|
||||
target = self._load_mat(self.masks[index])
|
||||
# synchrosized transform
|
||||
if self.mode == 'train':
|
||||
img, target = self._sync_transform(img, target)
|
||||
elif self.mode == 'val':
|
||||
img, target = self._val_sync_transform(img, target)
|
||||
else:
|
||||
raise RuntimeError('unknown mode for dataloader: {}'.format(self.mode))
|
||||
# general resize, normalize and toTensor
|
||||
if self.transform is not None:
|
||||
img = self.transform(img)
|
||||
return img, target, os.path.basename(self.images[index])
|
||||
|
||||
def _mask_transform(self, mask):
|
||||
return torch.LongTensor(np.array(mask).astype('int32'))
|
||||
|
||||
def _load_mat(self, filename):
|
||||
mat = sio.loadmat(filename, mat_dtype=True, squeeze_me=True, struct_as_record=False)
|
||||
mask = mat['GTcls'].Segmentation
|
||||
return Image.fromarray(mask)
|
||||
|
||||
def __len__(self):
|
||||
return len(self.images)
|
||||
|
||||
@property
|
||||
def classes(self):
|
||||
"""Category names."""
|
||||
return ('background', 'airplane', 'bicycle', 'bird', 'boat', 'bottle',
|
||||
'bus', 'car', 'cat', 'chair', 'cow', 'diningtable', 'dog', 'horse',
|
||||
'motorcycle', 'person', 'potted-plant', 'sheep', 'sofa', 'train',
|
||||
'tv')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
dataset = VOCAugSegmentation()
|
||||
|
|
@ -0,0 +1,112 @@
|
|||
"""Pascal VOC Semantic Segmentation Dataset."""
|
||||
import os
|
||||
import torch
|
||||
import numpy as np
|
||||
|
||||
from PIL import Image
|
||||
from .segbase import SegmentationDataset
|
||||
|
||||
|
||||
class VOCSegmentation(SegmentationDataset):
|
||||
"""Pascal VOC Semantic Segmentation Dataset.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
root : string
|
||||
Path to VOCdevkit folder. Default is './datasets/VOCdevkit'
|
||||
split: string
|
||||
'train', 'val' or 'test'
|
||||
transform : callable, optional
|
||||
A function that transforms the image
|
||||
Examples
|
||||
--------
|
||||
>>> from torchvision import transforms
|
||||
>>> import torch.utils.data as data
|
||||
>>> # Transforms for Normalization
|
||||
>>> input_transform = transforms.Compose([
|
||||
>>> transforms.ToTensor(),
|
||||
>>> transforms.Normalize([.485, .456, .406], [.229, .224, .225]),
|
||||
>>> ])
|
||||
>>> # Create Dataset
|
||||
>>> trainset = VOCSegmentation(split='train', transform=input_transform)
|
||||
>>> # Create Training Loader
|
||||
>>> train_data = data.DataLoader(
|
||||
>>> trainset, 4, shuffle=True,
|
||||
>>> num_workers=4)
|
||||
"""
|
||||
BASE_DIR = 'VOC2012'
|
||||
NUM_CLASS = 21
|
||||
|
||||
def __init__(self, root='../datasets/voc', split='train', mode=None, transform=None, **kwargs):
|
||||
super(VOCSegmentation, self).__init__(root, split, mode, transform, **kwargs)
|
||||
_voc_root = os.path.join(root, self.BASE_DIR)
|
||||
_mask_dir = os.path.join(_voc_root, 'SegmentationClass')
|
||||
_image_dir = os.path.join(_voc_root, 'JPEGImages')
|
||||
# train/val/test splits are pre-cut
|
||||
_splits_dir = os.path.join(_voc_root, 'ImageSets/Segmentation')
|
||||
if split == 'train':
|
||||
_split_f = os.path.join(_splits_dir, 'train.txt')
|
||||
elif split == 'val':
|
||||
_split_f = os.path.join(_splits_dir, 'val.txt')
|
||||
elif split == 'test':
|
||||
_split_f = os.path.join(_splits_dir, 'test.txt')
|
||||
else:
|
||||
raise RuntimeError('Unknown dataset split.')
|
||||
|
||||
self.images = []
|
||||
self.masks = []
|
||||
with open(os.path.join(_split_f), "r") as lines:
|
||||
for line in lines:
|
||||
_image = os.path.join(_image_dir, line.rstrip('\n') + ".jpg")
|
||||
assert os.path.isfile(_image)
|
||||
self.images.append(_image)
|
||||
if split != 'test':
|
||||
_mask = os.path.join(_mask_dir, line.rstrip('\n') + ".png")
|
||||
assert os.path.isfile(_mask)
|
||||
self.masks.append(_mask)
|
||||
|
||||
if split != 'test':
|
||||
assert (len(self.images) == len(self.masks))
|
||||
print('Found {} images in the folder {}'.format(len(self.images), _voc_root))
|
||||
|
||||
def __getitem__(self, index):
|
||||
img = Image.open(self.images[index]).convert('RGB')
|
||||
if self.mode == 'test':
|
||||
img = self._img_transform(img)
|
||||
if self.transform is not None:
|
||||
img = self.transform(img)
|
||||
return img, os.path.basename(self.images[index])
|
||||
mask = Image.open(self.masks[index])
|
||||
# synchronized transform
|
||||
if self.mode == 'train':
|
||||
img, mask = self._sync_transform(img, mask)
|
||||
elif self.mode == 'val':
|
||||
img, mask = self._val_sync_transform(img, mask)
|
||||
else:
|
||||
assert self.mode == 'testval'
|
||||
img, mask = self._img_transform(img), self._mask_transform(mask)
|
||||
# general resize, normalize and toTensor
|
||||
if self.transform is not None:
|
||||
img = self.transform(img)
|
||||
|
||||
return img, mask, os.path.basename(self.images[index])
|
||||
|
||||
def __len__(self):
|
||||
return len(self.images)
|
||||
|
||||
def _mask_transform(self, mask):
|
||||
target = np.array(mask).astype('int32')
|
||||
target[target == 255] = -1
|
||||
return torch.from_numpy(target).long()
|
||||
|
||||
@property
|
||||
def classes(self):
|
||||
"""Category names."""
|
||||
return ('background', 'airplane', 'bicycle', 'bird', 'boat', 'bottle',
|
||||
'bus', 'car', 'cat', 'chair', 'cow', 'diningtable', 'dog', 'horse',
|
||||
'motorcycle', 'person', 'potted-plant', 'sheep', 'sofa', 'train',
|
||||
'tv')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
dataset = VOCSegmentation()
|
||||
|
|
@ -0,0 +1,88 @@
|
|||
"""SBU Shadow Segmentation Dataset."""
|
||||
import os
|
||||
import torch
|
||||
import numpy as np
|
||||
|
||||
from PIL import Image
|
||||
from .segbase import SegmentationDataset
|
||||
|
||||
|
||||
class SBUSegmentation(SegmentationDataset):
|
||||
"""SBU Shadow Segmentation Dataset
|
||||
"""
|
||||
NUM_CLASS = 2
|
||||
|
||||
def __init__(self, root='../datasets/sbu', split='train', mode=None, transform=None, **kwargs):
|
||||
super(SBUSegmentation, self).__init__(root, split, mode, transform, **kwargs)
|
||||
assert os.path.exists(self.root)
|
||||
self.images, self.masks = _get_sbu_pairs(self.root, self.split)
|
||||
assert (len(self.images) == len(self.masks))
|
||||
if len(self.images) == 0:
|
||||
raise RuntimeError("Found 0 images in subfolders of:" + root + "\n")
|
||||
|
||||
def __getitem__(self, index):
|
||||
img = Image.open(self.images[index]).convert('RGB')
|
||||
if self.mode == 'test':
|
||||
if self.transform is not None:
|
||||
img = self.transform(img)
|
||||
return img, os.path.basename(self.images[index])
|
||||
mask = Image.open(self.masks[index])
|
||||
# synchrosized transform
|
||||
if self.mode == 'train':
|
||||
img, mask = self._sync_transform(img, mask)
|
||||
elif self.mode == 'val':
|
||||
img, mask = self._val_sync_transform(img, mask)
|
||||
else:
|
||||
assert self.mode == 'testval'
|
||||
img, mask = self._img_transform(img), self._mask_transform(mask)
|
||||
# general resize, normalize and toTensor
|
||||
if self.transform is not None:
|
||||
img = self.transform(img)
|
||||
return img, mask, os.path.basename(self.images[index])
|
||||
|
||||
def _mask_transform(self, mask):
|
||||
target = np.array(mask).astype('int32')
|
||||
target[target > 0] = 1
|
||||
return torch.from_numpy(target).long()
|
||||
|
||||
def __len__(self):
|
||||
return len(self.images)
|
||||
|
||||
@property
|
||||
def pred_offset(self):
|
||||
return 0
|
||||
|
||||
|
||||
def _get_sbu_pairs(folder, split='train'):
|
||||
def get_path_pairs(img_folder, mask_folder):
|
||||
img_paths = []
|
||||
mask_paths = []
|
||||
for root, _, files in os.walk(img_folder):
|
||||
print(root)
|
||||
for filename in files:
|
||||
if filename.endswith('.jpg'):
|
||||
imgpath = os.path.join(root, filename)
|
||||
maskname = filename.replace('.jpg', '.png')
|
||||
maskpath = os.path.join(mask_folder, maskname)
|
||||
if os.path.isfile(imgpath) and os.path.isfile(maskpath):
|
||||
img_paths.append(imgpath)
|
||||
mask_paths.append(maskpath)
|
||||
else:
|
||||
print('cannot find the mask or image:', imgpath, maskpath)
|
||||
print('Found {} images in the folder {}'.format(len(img_paths), img_folder))
|
||||
return img_paths, mask_paths
|
||||
|
||||
if split == 'train':
|
||||
img_folder = os.path.join(folder, 'SBUTrain4KRecoveredSmall/ShadowImages')
|
||||
mask_folder = os.path.join(folder, 'SBUTrain4KRecoveredSmall/ShadowMasks')
|
||||
img_paths, mask_paths = get_path_pairs(img_folder, mask_folder)
|
||||
else:
|
||||
assert split in ('val', 'test')
|
||||
img_folder = os.path.join(folder, 'SBU-Test/ShadowImages')
|
||||
mask_folder = os.path.join(folder, 'SBU-Test/ShadowMasks')
|
||||
img_paths, mask_paths = get_path_pairs(img_folder, mask_folder)
|
||||
return img_paths, mask_paths
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
dataset = SBUSegmentation(base_size=280, crop_size=256)
|
||||
|
|
@ -0,0 +1,93 @@
|
|||
"""Base segmentation dataset"""
|
||||
import random
|
||||
import numpy as np
|
||||
|
||||
from PIL import Image, ImageOps, ImageFilter
|
||||
|
||||
__all__ = ['SegmentationDataset']
|
||||
|
||||
|
||||
class SegmentationDataset(object):
|
||||
"""Segmentation Base Dataset"""
|
||||
|
||||
def __init__(self, root, split, mode, transform, base_size=520, crop_size=480):
|
||||
super(SegmentationDataset, self).__init__()
|
||||
self.root = root
|
||||
self.transform = transform
|
||||
self.split = split
|
||||
self.mode = mode if mode is not None else split
|
||||
self.base_size = base_size
|
||||
self.crop_size = crop_size
|
||||
|
||||
def _val_sync_transform(self, img, mask):
|
||||
outsize = self.crop_size
|
||||
short_size = outsize
|
||||
w, h = img.size
|
||||
if w > h:
|
||||
oh = short_size
|
||||
ow = int(1.0 * w * oh / h)
|
||||
else:
|
||||
ow = short_size
|
||||
oh = int(1.0 * h * ow / w)
|
||||
img = img.resize((ow, oh), Image.BILINEAR)
|
||||
mask = mask.resize((ow, oh), Image.NEAREST)
|
||||
# center crop
|
||||
w, h = img.size
|
||||
x1 = int(round((w - outsize) / 2.))
|
||||
y1 = int(round((h - outsize) / 2.))
|
||||
img = img.crop((x1, y1, x1 + outsize, y1 + outsize))
|
||||
mask = mask.crop((x1, y1, x1 + outsize, y1 + outsize))
|
||||
# final transform
|
||||
img, mask = self._img_transform(img), self._mask_transform(mask)
|
||||
return img, mask
|
||||
|
||||
def _sync_transform(self, img, mask):
|
||||
# random mirror
|
||||
if random.random() < 0.5:
|
||||
img = img.transpose(Image.FLIP_LEFT_RIGHT)
|
||||
mask = mask.transpose(Image.FLIP_LEFT_RIGHT)
|
||||
crop_size = self.crop_size
|
||||
# random scale (short edge)
|
||||
short_size = random.randint(int(self.base_size * 0.5), int(self.base_size * 2.0))
|
||||
w, h = img.size
|
||||
if h > w:
|
||||
ow = short_size
|
||||
oh = int(1.0 * h * ow / w)
|
||||
else:
|
||||
oh = short_size
|
||||
ow = int(1.0 * w * oh / h)
|
||||
img = img.resize((ow, oh), Image.BILINEAR)
|
||||
mask = mask.resize((ow, oh), Image.NEAREST)
|
||||
# pad crop
|
||||
if short_size < crop_size:
|
||||
padh = crop_size - oh if oh < crop_size else 0
|
||||
padw = crop_size - ow if ow < crop_size else 0
|
||||
img = ImageOps.expand(img, border=(0, 0, padw, padh), fill=0)
|
||||
mask = ImageOps.expand(mask, border=(0, 0, padw, padh), fill=0)
|
||||
# random crop crop_size
|
||||
w, h = img.size
|
||||
x1 = random.randint(0, w - crop_size)
|
||||
y1 = random.randint(0, h - crop_size)
|
||||
img = img.crop((x1, y1, x1 + crop_size, y1 + crop_size))
|
||||
mask = mask.crop((x1, y1, x1 + crop_size, y1 + crop_size))
|
||||
# gaussian blur as in PSP
|
||||
if random.random() < 0.5:
|
||||
img = img.filter(ImageFilter.GaussianBlur(radius=random.random()))
|
||||
# final transform
|
||||
img, mask = self._img_transform(img), self._mask_transform(mask)
|
||||
return img, mask
|
||||
|
||||
def _img_transform(self, img):
|
||||
return np.array(img)
|
||||
|
||||
def _mask_transform(self, mask):
|
||||
return np.array(mask).astype('int32')
|
||||
|
||||
@property
|
||||
def num_class(self):
|
||||
"""Number of categories."""
|
||||
return self.NUM_CLASS
|
||||
|
||||
@property
|
||||
def pred_offset(self):
|
||||
return 0
|
||||
|
|
@ -0,0 +1,69 @@
|
|||
import os
|
||||
import hashlib
|
||||
import errno
|
||||
import tarfile
|
||||
from six.moves import urllib
|
||||
from torch.utils.model_zoo import tqdm
|
||||
|
||||
def gen_bar_updater():
|
||||
pbar = tqdm(total=None)
|
||||
|
||||
def bar_update(count, block_size, total_size):
|
||||
if pbar.total is None and total_size:
|
||||
pbar.total = total_size
|
||||
progress_bytes = count * block_size
|
||||
pbar.update(progress_bytes - pbar.n)
|
||||
|
||||
return bar_update
|
||||
|
||||
def check_integrity(fpath, md5=None):
|
||||
if md5 is None:
|
||||
return True
|
||||
if not os.path.isfile(fpath):
|
||||
return False
|
||||
md5o = hashlib.md5()
|
||||
with open(fpath, 'rb') as f:
|
||||
# read in 1MB chunks
|
||||
for chunk in iter(lambda: f.read(1024 * 1024), b''):
|
||||
md5o.update(chunk)
|
||||
md5c = md5o.hexdigest()
|
||||
if md5c != md5:
|
||||
return False
|
||||
return True
|
||||
|
||||
def makedir_exist_ok(dirpath):
|
||||
try:
|
||||
os.makedirs(dirpath)
|
||||
except OSError as e:
|
||||
if e.errno == errno.EEXIST:
|
||||
pass
|
||||
else:
|
||||
pass
|
||||
|
||||
def download_url(url, root, filename=None, md5=None):
|
||||
"""Download a file from a url and place it in root."""
|
||||
root = os.path.expanduser(root)
|
||||
if not filename:
|
||||
filename = os.path.basename(url)
|
||||
fpath = os.path.join(root, filename)
|
||||
|
||||
makedir_exist_ok(root)
|
||||
|
||||
# downloads file
|
||||
if os.path.isfile(fpath) and check_integrity(fpath, md5):
|
||||
print('Using downloaded and verified file: ' + fpath)
|
||||
else:
|
||||
try:
|
||||
print('Downloading ' + url + ' to ' + fpath)
|
||||
urllib.request.urlretrieve(url, fpath, reporthook=gen_bar_updater())
|
||||
except OSError:
|
||||
if url[:5] == 'https':
|
||||
url = url.replace('https:', 'http:')
|
||||
print('Failed download. Trying https -> http instead.'
|
||||
' Downloading ' + url + ' to ' + fpath)
|
||||
urllib.request.urlretrieve(url, fpath, reporthook=gen_bar_updater())
|
||||
|
||||
def download_extract(url, root, filename, md5):
|
||||
download_url(url, root, filename, md5)
|
||||
with tarfile.open(os.path.join(root, filename), "r") as tar:
|
||||
tar.extractall(path=root)
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue