男的做那个视频网站,雷州市网站建设,桐乡网站建设,游戏推广怎么找玩家DroneVehicle数据集转YOLO格式#xff08;一标签对应两模态#xff09;
由于我需要学习多模态融合#xff0c;尤其优化融合模块#xff0c;所以需要将DroneVehicle数据集处理为一标签对应两模态#xff0c;即在处理过程中#xff0c;删除双光标注不一致的标注框。
感谢帖…DroneVehicle数据集转YOLO格式一标签对应两模态由于我需要学习多模态融合尤其优化融合模块所以需要将DroneVehicle数据集处理为一标签对应两模态即在处理过程中删除双光标注不一致的标注框。感谢帖子https://zhuanlan.zhihu.com/p/665126340的鼎立相助Step1 下载数据集https://github.com/VisDrone/DroneVehicle解压得到Step2 去除白边importnumpyasnpimportcv2importosfromtqdmimporttqdmdefcreate_file(output_dir_vi,output_dir_ir):ifnotos.path.exists(output_dir_vi):os.makedirs(output_dir_vi)ifnotos.path.exists(output_dir_ir):os.makedirs(output_dir_ir)print(fCreated folder:({output_dir_vi}); ({output_dir_ir}))defupdate(input_img_path,output_img_path):imagecv2.imread(input_img_path)croppedimage[100:612,100:740]# 裁剪坐标为[y0:y1, x0:x1]cv2.imwrite(output_img_path,cropped)dataset_dir_vi./data/val/valimgoutput_dir_vi./data/dataset/valimg_croppeddataset_dir_ir./data/val/valimgroutput_dir_ir./data/dataset/valimgr_cropped# 检查文件夹是否存在如果不存在则创建create_file(output_dir_vi,output_dir_ir)# 获得需要转化的图片路径并生成目标路径image_filenames_vi[(os.path.join(dataset_dir_vi,x),os.path.join(output_dir_vi,x))forxinos.listdir(dataset_dir_vi)]image_filenames_ir[(os.path.join(dataset_dir_ir,x),os.path.join(output_dir_ir,x))forxinos.listdir(dataset_dir_ir)]# 转化所有图片print(Start transforming vision images...)forpathintqdm(image_filenames_vi):update(path[0],path[1])print(Start transforming infrared images...)forpathintqdm(image_filenames_ir):update(path[0],path[1])Step3 XML数据转TXT数据importosimportxml.etree.ElementTreeasETimportmathimportcv2ascvimportargparsefromtqdmimporttqdm# 图像类别classes[feright_car,car,truck,bus,van]# 定义相关地址参数defparse_args():parserparserargparse.ArgumentParser(descriptionpolygon)parser.add_argument(--in_xml_vi_dir,default./test/testlabel,help可见光 XML 文件地址)parser.add_argument(--in_xml_ir_dir,default./test/testlabelr,help红外光 XML 文件地址)parser.add_argument(--out_vi_txt_dir,default./data_cut/test/testlabel,help可见光 TXT 文件地址)parser.add_argument(--out_ir_txt_dir,default./data_cut/test/testlabelr,help红外光 TXT 文件地址)parser.add_argument(--in_vi_img_dir,default./data_cut/test/images,help裁切后的 vi-img 地址)parser.add_argument(--in_ir_img_dir,default./data_cut/test/images_ir,help裁切后的 ir-img 地址)argsparser.parse_args()returnargs# 根据 xml 文件中的 name 选择生成的 txt 文件中的 iddefselect_id(name):# 标准化转小写、去空格防止大小写或空格问题namename.strip().lower()# 定义映射表支持多种拼写mapping{# car 类car:0,# truck 类truck:1,# bus 类bus:1,# 注意有些数据集把 bus 归为 truck按你需求调整# 如果 bus 是独立类别保留为 2# van 类van:3,# freight/feright 相关统一归为类别 4feright:4,freight:4,feright car:4,feright_car:4,freight car:4,freight_car:4,ferightcar:4,freightcar:4,}ifnameinmapping:returnmapping[name]else:# 打印警告并跳过避免崩溃print(fWarning: unknown class name {name}, skipping this object.)returnNone# YOLO 数据处理defdata_transform(height,width,xmin,ymin,xmax,ymax):# 中心点坐标 x_c,y_cx_c(xminxmax)/2y_c(yminymax)/2# 中心横坐标与图像宽度比值 x_中心纵坐标与图像高度比值 y_bbox 宽度与图像宽度比值 w_bbox 高度与图像高度比值 h_x_x_c/width y_y_c/height w_(xmax-xmin)/width h_(ymax-ymin)/heightreturnx_,y_,w_,h_# xml 文件转 txt 文件defxml2txt(in_xml_dir,xml_name,out_txt_dir,in_img_dir):txt_namexml_name[:-4].txt# 获取生成的 txt 文件名txt_pathout_txt_dir# 获取生成的 txt 文件保存地址# 判断保存 txt 文件的文件夹是否存在如果不存在则创建相应文件夹ifnotos.path.exists(txt_path):os.makedirs(txt_path)txt_fileos.path.join(txt_path,txt_name)# 获取 txt 文件地址保存地址 保存名字img_namexml_name[:-4].jpg# 获取图像名字确保生成的 txt 文件名与图像文件名一致img_pathos.path.join(in_img_dir,img_name)# 获取图像地址imgcv.imread(img_path)# 读取图像信息height,width,_img.shape# 获取图像高度height宽度width通道数_xml_fileos.path.join(in_xml_dir,xml_name)# 获取 xml 文件地址treeET.parse(os.path.join(xml_file))# 使用 ET.parse 方法解析 xml 文件roottree.getroot()# 使用 getroot 方法获取根目录# 生成对应的 txt 文件withopen(txt_file,w,encodingUTF-8)asout_file:forobjinroot.findall(object):# 修改部分标注文件中标注不全的 name 文件nameobj.find(name).textifnameferight_car:nameferight carelse:namename# 从 xml 文件中提取相关数据信息,并进行删除白边数据操作白边宽度 100 像素ifobj.find(polygon):# 创建空列表用于存放需要处理的数据xmin,xmax,ymin,ymax[],[],[],[]polygonobj.find(polygon)# 使用 .find() 方法获取对应 xml 文件中键的键值x1int(polygon.find(x1).text)-100y1int(polygon.find(y1).text)-100x2int(polygon.find(x2).text)-100y2int(polygon.find(y2).text)-100x3int(polygon.find(x3).text)-100y3int(polygon.find(y3).text)-100x4int(polygon.find(x4).text)-100y4int(polygon.find(y4).text)-100# 将获取后的数据填入空列表中foriin[x1,x2,x3,x4]:xmin.append(i)xmax.append(i)forjin[y1,y2,y3,y4]:ymin.append(j)ymax.append(j)# 使用 min()、max() 方法获取最大值最小值xminmin(xmin)xmaxmax(xmax)yminmin(ymin)ymaxmax(ymax)# yolo 格式转换resultdata_transform(height,width,xmin,ymin,xmax,ymax)# id 选择result_idselect_id(name)elifobj.find(bndbox):bndboxobj.find(bndbox)# 使用 .find() 方法获取对应 xml 文件中键的键值xminbndbox.find(xmin).text yminbndbox.find(ymin).text xmaxbndbox.find(xmax).text ymaxbndbox.find(ymax).text x1int(xmin)-100y1int(ymin)-100x3int(xmax)-100y3int(ymax)-100# yolo 格式转换resultdata_transform(height,width,x1,y1,x3,y3)# id 选择result_idselect_id(name)# 创建 txt 文件中的数据if0result[0]1and0result[1]1and0result[2]1and0result[3]1:datastr(result[0]) str(result[1]) str(result[2]) str(result[3])\ndatastr(result_id) data out_file.write(data)else:passif__name____main__:argsparse_args()# 获取命令参数xml_vi_pathargs.in_xml_vi_dir# 获取可见光 xml 文件地址xmlFiles_vios.listdir(xml_vi_path)# 生成可见光 xml 文件名列表xml_ir_pathargs.in_xml_ir_dir# 获取红外 xml 文件地址xmlFiles_iros.listdir(xml_ir_path)# 生成红外 xml 文件名列表print(Start transforming vision labels...)foriintqdm(range(0,len(xmlFiles_vi))):xml2txt(args.in_xml_vi_dir,xmlFiles_vi[i],args.out_vi_txt_dir,args.in_vi_img_dir)print(Finish.)print(Start transforming infrared labels...)foriintqdm(range(0,len(xmlFiles_ir))):xml2txt(args.in_xml_ir_dir,xmlFiles_ir[i],args.out_ir_txt_dir,args.in_ir_img_dir)print(Finish.)Step4 滤除不需要的框该数据集中对可见光和红外光的标注并不严格对齐。比如存在仅在一张图片标注可见光不可见红外光可见位置对齐失败可见光与红外摄像头规格不同或标注框出现偏移。所以我写了一个脚本去除多余的框与位置对齐优化达到可见光和红外光的严格对齐代码如下importosimportcv2importnumpyasnpfrompathlibimportPath# 配置 base_dirD:\BaiduNetdiskDownload\dronevehicle\data_cut# 修改为你的真实路径sets[train,val,test]# 要处理的数据集max_distance0.02# 中心点距离阈值相对坐标# 创建输出目录forsinsets:labels_diros.path.join(base_dir,s,labels)os.makedirs(labels_dir,exist_okTrue)# 读取并解析 YOLO 标签文件defparse_yolo(path):ifnotos.path.exists(path):return[]boxes[]withopen(path,r)asf:forlineinf:lineline.strip()ifnotlineorline.startswith(None):continuepartsline.split()try:clsint(parts[0])cx,cy,w,hmap(float,parts[1:5])ifcx0orcy0orw0orh0:continueboxes.append((cls,cx,cy,w,h))exceptExceptionase:print(f⚠️ 解析失败:{path}-{line}| 错误:{e})returnboxes# 计算两个框的中心点距离defcenter_distance(box1,box2):cx1,cy1box1[1],box1[2]cx2,cy2box2[1],box2[2]returnnp.sqrt((cx1-cx2)**2(cy1-cy2)**2)# 匹配两个列表中的框基于类别 中心点距离defmatch_boxes(vis_boxes,ir_boxes,max_dist0.02):matched[]used_irset()forv_boxinvis_boxes:best_matchNonemin_distfloat(inf)fori,r_boxinenumerate(ir_boxes):ifiinused_ir:continueifv_box[0]!r_box[0]:# 类别不同跳过continuedistcenter_distance(v_box,r_box)ifdistmax_distanddistmin_dist:min_distdist best_match(i,r_box)ifbest_match:idx,r_boxbest_match used_ir.add(idx)# 取平均坐标avg_clsv_box[0]avg_cx(v_box[1]r_box[1])/2avg_cy(v_box[2]r_box[2])/2avg_w(v_box[3]r_box[3])/2avg_h(v_box[4]r_box[4])/2matched.append((avg_cls,avg_cx,avg_cy,avg_w,avg_h))returnmatched# 处理每个数据集fordatasetinsets:# 构造路径trainlabel, trainlabelr 等label_diros.path.join(base_dir,dataset,f{dataset}label)# 如 trainlabellabel_r_diros.path.join(base_dir,dataset,f{dataset}labelr)# 如 trainlabelroutput_label_diros.path.join(base_dir,dataset,labels)# 获取所有样本 ID以 .txt 结尾的文件名去掉后缀sample_idsset()forpathinPath(label_dir).glob(*.txt):sample_ids.add(os.path.basename(path).replace(.txt,))forpathinPath(label_r_dir).glob(*.txt):sample_ids.add(os.path.basename(path).replace(.txt,))print(f 正在处理{dataset}共{len(sample_ids)}个样本...)forsample_idinsample_ids:vis_pathos.path.join(label_dir,f{sample_id}.txt)ir_pathos.path.join(label_r_dir,f{sample_id}.txt)# 读取两个标签vis_boxesparse_yolo(vis_path)ir_boxesparse_yolo(ir_path)# 如果任一方为空跳过iflen(vis_boxes)0orlen(ir_boxes)0:print(f⚠️{sample_id}: 一方无标注跳过)continue# 匹配框matched_boxesmatch_boxes(vis_boxes,ir_boxes,max_distance)# 如果没有匹配跳过iflen(matched_boxes)0:print(f⚠️{sample_id}: 无匹配框跳过)continue# 写入输出文件out_pathos.path.join(output_label_dir,f{sample_id}.txt)withopen(out_path,w)asf:forboxinmatched_boxes:f.write(f{box[0]}{box[1]:.6f}{box[2]:.6f}{box[3]:.6f}{box[4]:.6f}\n)print(f✅{sample_id}: 生成{len(matched_boxes)}个对齐框 →{out_path})print(\n 所有数据集处理完成)Step5 可视化importosimportcv2importnumpyasnpimportrandomfrompathlibimportPath# 配置 base_dirD:\BaiduNetdiskDownload\dronevehicle\data_cut# 修改为你的真实路径sets[train,val,test]# 图像后缀img_exts[.jpg,.jpeg,.png]ir_exts[.png,.jpg]# 红外可能为 pngdefload_image(path,exts):forextinexts:ppathextifos.path.exists(p):returncv2.imread(p)print(f❌ 图像未找到:{path})returnNonedefparse_labels(label_path):boxes[]ifnotos.path.exists(label_path):print(f⚠️ 标签文件不存在:{label_path})returnboxeswithopen(label_path,r)asf:forlineinf:lineline.strip()ifnotlineorline.startswith(None):continuepartsline.split()try:clsint(parts[0])cx,cy,w,hmap(float,parts[1:5])ifcx0orcy0orw0orh0:continueboxes.append((cls,cx,cy,w,h))exceptExceptionase:print(f⚠️ 解析失败:{line}| 错误:{e})returnboxesdefdraw_boxes(img,boxes):在图像上绘制 YOLO 格式的框h,wimg.shape[:2]forcls,cx,cy,w_box,h_boxinboxes:x1int((cx-w_box/2)*w)y1int((cy-h_box/2)*h)x2int((cxw_box/2)*w)y2int((cyh_box/2)*h)color(0,255,0)ifcls0else(0,0,255)cv2.rectangle(img,(x1,y1),(x2,y2),color,2)cv2.putText(img,str(cls),(x1,y1-10),cv2.FONT_HERSHEY_SIMPLEX,0.6,color,2)returnimgdefget_all_samples(base_dir,dataset):获取指定数据集的所有样本 IDlabel_diros.path.join(base_dir,dataset,labels)ifnotos.path.exists(label_dir):return[]return[p.stemforpinPath(label_dir).glob(*.txt)]# 主程序defmain():all_samples[]forsinsets:samplesget_all_samples(base_dir,s)all_samples.extend([(s,sid)forsidinsamples])ifnotall_samples:print(❌ 没有找到任何样本请检查 labels/ 目录)returnprint(f 共找到{len(all_samples)}个样本开始可视化...)random.shuffle(all_samples)current_idx0totallen(all_samples)whileTrue:dataset,sample_idall_samples[current_idx]print(f\n➡️ 当前样本:{dataset}/{sample_id})# 构造路径image_pathos.path.join(base_dir,dataset,images,sample_id)ir_pathos.path.join(base_dir,dataset,images_ir,sample_id)label_pathos.path.join(base_dir,dataset,labels,f{sample_id}.txt)# 加载图像vis_imgload_image(image_path,img_exts)ir_imgload_image(ir_path,ir_exts)ifvis_imgisNoneorir_imgisNone:print(f❌ 图像加载失败跳过{sample_id})current_idx1ifcurrent_idxtotal:current_idx0continue# 加载标签boxesparse_labels(label_path)# 绘制框vis_with_boxesdraw_boxes(vis_img.copy(),boxes)ir_with_boxesdraw_boxes(ir_img.copy(),boxes)# 显示两幅图cv2.imshow(Visible Light,vis_with_boxes)cv2.imshow(Infrared,ir_with_boxes)# 等待按键keycv2.waitKey(0)0xFFifkeyord(q)orkey27:# q 或 ESC 退出breakelifkeyord(n):# n 下一个current_idx1else:current_idx1# 默认按任意键下一页# 循环ifcurrent_idxtotal:current_idx0cv2.destroyAllWindows()if__name____main__:main()用于观察是否达到严格对齐效果不好可以修改max_distance 0.02 # 中心点距离阈值相对坐标效果