1。任务目标 在训练目标检测模型时,若数据存在以下情况:图像之间差异小、不同类别数目差异大、有些目标物体的样本图片难以搜集等,需要对数据进行处理。本文以fire类别为例实现对数据的随机贴图增广,生成新的标注文件,或在已有标注文件中添加,且避免覆盖已有标注。2。Python实现2。1将已标注的目标保存 数据存储格式:(路径中不要包含中文) 输入文件夹:datafiredatasetJPEGImages。jpgdatafiredatasetAnnotations。xml 输出文件夹:datafirecut 代码:importosimportcv2importtimeimportargparseimportxml。etree。ElementTreeasETfromtqdmimporttqdmparserargparse。ArgumentParser(descriptionReadboxfromxmlandcropfromimage。)parser。addargument(dstlabel,defaultfire,helplabelboxtocut)parser。addargument(inputpath,defaultdatafiredataset,helpcontainAnnotations,JPEGImagesfolder)parser。addargument(outputpath,defaultdatafirecut,helpoutputpath)argsparser。parseargs()defreadxmlbox(xmlfile):xmlannoET。parse(xmlfile)result〔〕forobjinxmlanno。findall(object):classnameobj。find(name)。text。strip()xminobj。find(bndbox)。find(xmin)。textxmaxobj。find(bndbox)。find(xmax)。textyminobj。find(bndbox)。find(ymin)。textymaxobj。find(bndbox)。find(ymax)。textresult。append(〔classname,int(xmin),int(xmax),int(ymin),int(ymax)〕)returnresultdefmain():xmlpathos。path。join(args。inputpath,Annotations)imgpathos。path。join(args。inputpath,JPEGImages)forimgnameintqdm(os。listdir(imgpath)):xmlname{}。xml。format(imgname。rsplit(。,maxsplit1)〔0〕)xmlfileos。path。join(xmlpath,xmlname)ifnotos。path。exists(xmlfile):print({}notexists。format(xmlname))continueimgcv2。imread(os。path。join(imgpath,imgname))clsboxesreadxmlbox(xmlfile)forclsboxinclsboxes:classname,xmin,xmax,ymin,ymaxclsboxifclassname!args。dstlabel:continuecropimgimg〔ymin:ymax,xmin:xmax,:〕newname{}{}。jpg。format(xmlname〔:4〕,str(time。time())。replace(。,))savepathos。path。join(args。outputpath,classname)ifnotos。path。exists(savepath):os。makedirs(savepath)savenameos。path。join(savepath,newname)print(savename)cv2。imwrite(savename,cropimg)ifnamemain:main() 生成结果: 2。2随机贴图扩充数据 数据存储格式: 输入文件夹:datafirecutdatafirebgJPEGImages。jpgdatafirebgAnnotations。xml 注意:此处作为背景的数据,可以只有图片,没有标注文件。也可以既有图片又有标注文件。若没有标注文件,则生成;若有标注文件,则在贴图时会避免目标框的遮挡。 输出文件夹:dataoutput 输入参数:gennum:生成的图片数目,实际生成数目小于等于该值;clsname:待扩增的类别名称;tietudir:前景图片文件夹,保存fire目标图,是从已标注的fire数据中剪切保存;imgpath:背景图片文件夹,其他含fire目标或不含fire目标的图片;xmlpath:背景图片标注文件夹savepath:保存结果文件夹 代码:importosimporttimeimportrandomimportargparseimportxml。etree。ElementTreeasETfromPILimportImageparserargparse。ArgumentParser()parser。addargument(tietudir,defaultdatafirecutfire,help贴图路径)parser。addargument(xmlpath,defaultdatafirebgAnnotations,help躲避路径)parser。addargument(imgpath,defaultdatafirebgJPEGImages,help底图路径)parser。addargument(savepath,defaultdataoutput,help保存路径)parser。addargument(gennum,default11,help保存个数)parser。addargument(clsname,defaultfire,help目标类别名)argsparser。parseargs()defcreatsrcxml(widthditu,heightditu,box,savepath,name,clsname):xmlnamenamexmlfilesavepathxmlnamexopen(xmlfile,w)x。writelines()x。writelines(folderdatafolder)x。writelines(filenamexmlnamefilename)x。writelines(pathxmlfilepath)x。writelines(source)x。writelines(databaseUnknowndatabase)x。writelines(source)x。writelines(size)x。writelines(widthstr(widthditu)width)x。writelines(heightstr(heightditu)height)x。writelines(depth3depth)x。writelines(size)x。writelines(segmented0segmented)x。writelines(object)x。writelines(nameclsnamename)x。writelines(poseUnspecifiedpose)x。writelines(truncated0truncated)x。writelines(difficult0difficult)x。writelines(bndbox)x。writelines(xminstr(int(box〔0〕))xmin)x。writelines(yminstr(int(box〔1〕))ymin)x。writelines(xmaxstr(int(box〔2〕))xmax)x。writelines(ymaxstr(int(box〔3〕))ymax)x。writelines(bndbox)x。writelines(object)x。writelines(annotation)x。close()defcreatxml(box,savepath,copypath,clsname):readFileopen(copypath,encodingUTF8)linesreadFile。readlines()readFile。close()xopen(savepath,w,encodingUTF8)x。writelines(〔itemforiteminlines〔:1〕〕)x。writelines(object)x。writelines(nameclsnamename)x。writelines(poseUnspecifiedpose)x。writelines(truncated0truncated)x。writelines(difficult0difficult)x。writelines(bndbox)x。writelines(xminstr(int(box〔0〕))xmin)x。writelines(yminstr(int(box〔1〕))ymin)x。writelines(xmaxstr(int(box〔2〕))xmax)x。writelines(ymaxstr(int(box〔3〕))ymax)x。writelines(bndbox)x。writelines(object)x。writelines(annotation)x。close()defreadxmlbox(xmlfile):xmlannoET。parse(xmlfile)result〔〕forobjinxmlanno。findall(object):classnameobj。find(name)。text。strip()xminobj。find(bndbox)。find(xmin)。textxmaxobj。find(bndbox)。find(xmax)。textyminobj。find(bndbox)。find(ymin)。textymaxobj。find(bndbox)。find(ymax)。textresult。append(〔classname,int(xmin),int(ymin),int(xmax),int(ymax)〕)returnresultdefcomputeIOU(rec1,rec2):leftcolumnmaxmax(rec1〔0〕,rec2〔0〕)rightcolumnminmin(rec1〔2〕,rec2〔2〕)uprowmaxmax(rec1〔1〕,rec2〔1〕)downrowminmin(rec1〔3〕,rec2〔3〕)ifleftcolumnmaxrightcolumnminordownrowminuprowmax:return0else:s1(rec1〔2〕rec1〔0〕)(rec1〔3〕rec1〔1〕)s2(rec2〔2〕rec2〔0〕)(rec2〔3〕rec2〔1〕)scross(downrowminuprowmax)(rightcolumnminleftcolumnmax)returnscross(s1s2scross)defrandombox(end1,end2,end3,end4):xminrandom。randint(0,end1)yminrandom。randint(0,end2)xmaxxminend3ymaxyminend4returnxmin,ymin,xmax,ymaxdefgetshufflelist(imgpath,gennum):imgsos。listdir(imgpath)numlen(imgs)ifnotnum:returnNonerandom。shuffle(imgs)times,remainderpmod(gennum,num)namegenimgs〔:remainder〕foriinrange(times):namegen。extend(imgs)random。shuffle(namegen)returnnamegendefprocess(gennum,tietudir,imgpath,xmlpath,savepath,clsname):os。makedirs(savepath,existokTrue)loadfgfggengetshufflelist(tietudir,gennum)loadbgbggengetshufflelist(imgpath,gennum)iffggenisNoneorbggenisNone:returncombinenum0forfg,bginzip(fggen,bggen):num1fgimgImage。open(os。path。join(tietudir,fg))bgimgImage。open(os。path。join(imgpath,bg))savenamebg。rsplit(。,maxsplit1)〔0〕bgxmlname{}。xml。format(savename)bgxmlpathos。path。join(xmlpath,bgxmlname)clsboxes〔〕ifos。path。exists(bgxmlpath):clsboxesreadxmlbox(bgxmlpath)fgwidthfgimg。size〔0〕贴图长宽fgheightfgimg。size〔1〕bgwidthbgimg。size〔0〕底图长宽bgheightbgimg。size〔1〕scale1。0try:box2randombox(bgwidthfgwidth,bgheightfgheight,fgwidth,fgheight)except:scale0。5fgimg。resize((int(fgwidthscale),int(fgheightscale)))fgwidthfgimg。size〔0〕fgheightfgimg。size〔1〕iffgwidthbgwidthorfgheightbgheight:continuebox2randombox(bgwidthfgwidth,bgheightfgheight,fgwidth,fgheight)timer50loopflagTruewhiletimerandloopflagandclsboxes:timer1loopflagFalseforboxinclsboxes:areacomputeIOU(box〔1:5〕,box2)ifarea0:box2randombox(bgwidthfgwidth,bgheightfgheight,fgwidth,fgheight)loopflagTruebreakiftimer0:bgimg。paste(fgimg,(box2〔0〕,box2〔1〕))bgimgaddbgimg。convert(RGB)newname{}{}。format(savename,str(time。time())。replace(。,))bgimgadd。save(os。path。join(savepath,newname。jpg))xmlsavepathos。path。join(savepath,newname。xml)ifnotclsboxes:creatsrcxml(bgwidth,bgheight,box2,savepath,newname。xml,clsname)else:creatxml(box2,xmlsavepath,bgxmlpath,clsname)ifnamemain:process(args。gennum,args。tietudir,args。imgpath,args。xmlpath,args。savepath,args。clsname) 生成结果:(labelimg查看) 智驱力科技驱动生产力