VPGNet数据集解析且将分割标签转化为目标检测标签

VPGNet交通标志数据集

VPGNet是一个包含了四个场景(晴天,夜间,阴雨等)下的交通路况数据集,其主要是针对地面标志(箭头线,人行道)的任务,该数据集一共包括以下17类地面标注

{0:'background',          1:'lane_solid_white',
 2:'lane_broken_white',            3:'lane_double_white', 
 4:'lane_solid_yellow',            5:'lane_broken_yellow',
 6:'lane_double_yellow',            7:'lane_broken_blue',
 8:'lane_slow',            9:'stop_line',
 10:'arrow_left',            11:'arrow_right', 
 12:'arrow_go_straight',            13:'arrow_u_turn',
 14:'speed_bump',            15:'crossWalk',
 16:'safety_zone',            17:'other_road_markings',

该数据集下载地址为:VPGNet数据集下载
下载解压得到的数据集文件格式为
Scene_x
—%datetime_aaa_xxx
-----id.mat
该数据集的所有有用信息均保存在一个(640×480×5)的mat文件中。

VPGNet数据集内容解析

数据集的关键信息均保存在(6404805)的数组中,前三个通道为图片的rgb三通道信息,第四维通道为图像的17类二值分割图像(像素值为0-17),第五维通道为该论文提出的vanish point信息(我这里不需要用)。为了利用该数据集,我们需要将其信息分为原始图像images和标签文件labels两部分。python中的scipy库提供了loadmat函数能解析.mat文件。

from scipy.io import loadmat
m=loadmat(mat_file)

loadmat函数返回的是字典形式的变量,再继续解析字典m即可分别得到images与labels,完整代码如下:

#取.mat文件,并将其转为图片 
import glob
import cv2
import os
import numpy as np
from scipy.io import loadmat
from tqdm import tqdm


root_path='/data/dataset/TrafficMarking/VPGNet/scene_2'   #存放mat文件的地址
#save_path='/data/dataset/TrafficMarking/VPGNet/images'    #保存原始rgb图像地址
save_path='/data/dataset/TrafficMarking/VPGNet/masks/'  #保存原始分割mask图像
datefiles=[os.path.join(root_path,f) for f in os.listdir(root_path)]
pbar=tqdm(datefiles)
for df in pbar:        #mat_file='/data/dataset/TrafficMarking/VPGNet/scene_1/20160512_1424_46/000001.mat' 
   mat_files=glob.glob(df+'/*.mat')
   for mat_file in mat_files:        
   	m=loadmat(mat_file)     #mat文件的读取格式为dict,按照key,values处理      VPGNet图片信息储存在['rgb_seg_vp']里 (480,640,5)        
   	rgb_img=m['rgb_seg_vp'][:,:,:3]        
   	#修改通道 使之恢复为为原始的rgb图像 
   	b=rgb_img[:,:,0]       
   	g=rgb_img[:,:,1]        
   	r=rgb_img[:,:,2]        
   	rgb_img=cv2.merge((r,g,b))        
   	seg=m['rgb_seg_vp'][:,:,3]*15   #*15为了可视化更清楚         
   	vp=m['rgb_seg_vp'][:,:,4]
        file_name=save_path+'/'+root_path.split('/')[-1]+'_'+mat_file.split('/')[-2]+'_'+mat_file.split('/')[-1].split('.')[0]       
        #保存原始mask图像        
        #print(np.unique(seg))        
        cv2.imwrite('%s.png'% file_name,seg)
             
        #保存rgb图像        
        #file_path='%s.png'%file_name        
        #cv2.imwrite('%s.png'% file_name,rgb_img.astype(np.uint8))
        print( 'finish getting segmentations!')

这样即可将图片与分割标签分别保存下来。接下来即按一定比例随机划分训练集与验证集。

import os
import random
import shutil
import numpy as np
from tqdm import tqdm

def split_train_val(filedir):    
	#随机划分训练集与验证集    
	val_dir='/data/dataset/TrafficMarking/VPGNet/val/'    
	np.random.seed(42)    
	pathdirs=os.listdir(filedir)    
	ratio=0.2  #验证集比例    
	number_imgs=len(pathdirs)    
	val_numbers=int(number_imgs*ratio)    
	val_samples=random.sample(pathdirs,val_numbers)    
	for val_sample in val_samples:        
		shutil.move(filedir+val_sample,val_dir+val_sample)    
	return 

def match_train_val(imgs_dir,labels_dir,saved_path):    
	#匹配训练集和验证集的标注信息,对应保存    
	imgs_names=os.listdir(imgs_dir)    
	anno_names=os.listdir(labels_dir)    
	pbar=tqdm(imgs_names)    
	for img_name in pbar:        
		img_name=img_name.split('.')[0]        
		anno_name=img_name+'.png'        #匹配到的mask标签
		#anno_name=img_name+'.txt'        
		if anno_name in anno_names:            
			shutil.move(labels_dir+anno_name,saved_path)    
	return



if __name__=='__main__':
    imgs_dir='/data/dataset/TrafficMarking/VPGNet/images/train'
    labels_dir='/data/dataset/TrafficMarking/VPGNet/masks/'    
    saved_path='/data/dataset/TrafficMarking/VPGNet/masks/train'    
    #filedir='/data/dataset/TrafficMarking/VPGNet/imgs/'    
    #split_train_val(filedir=filedir)    
    match_train_val(imgs_dir,labels_dir,saved_path)

首先修改filedir为保存数据集图片的地址,执行split_train_val()将得到验证集图片,剩下的即作为训练集图片。再修改参数执行两次match_train_val(),其中imgs_dir为保存好的训练集,验证集图片的地址,labels_dir为原始所有mask标签的地址,saved_path为保存训练集验证集标签的最终地址。这样即将VPGNet数据集成功分割成为了训练集与验证集两部分,可用于后续的分割模型的训练。其分割标签图片如下所示:

在这里插入图片描述

分割标签到检测标签的转化

在我们的使用中,需要将mask部分语义分割标签转化为bbox检测标签,我们主要 通过对于mask 的连通域分析,利用opencv的cv2.connectedComponents()函数来完成该功能,以下提供了完整的代码。

我们选取了提取[10,11,12,13,15,16]几个类别,将其语义分割标签转化为检测框标签。

#将seg标注信息转化为bbox信息
import os
import cv2
import torch
import numpy as np
from PIL import Image
import matplotlib.pyplot as plt
from tqdm import tqdm
from scipy.io import loadmat
import glob


def get_seg(root_path):
#返回原始图片,语义分割标签,文件名称

    	  save_path='/data/dataset/TrafficMarking/VPGNet/masks/'  #保存原始分割mask图像    
    	  segs=[]    
	  masks=[]   #rgb原始图像    
	  file_names=[]    
	  datefiles=[os.path.join(root_path,f)   for f in os.listdir(root_path)]
	      #datefiles=[os.path.join(root_path)]    
	  pbar=tqdm(datefiles)
	  for df in pbar:
        	mat_files=glob.glob(df+'/*.mat')        
        	for mat_file in mat_files:            
        	m=loadmat(mat_file)     #mat文件的读取格式为dict,按照key,values处理      VPGNet图片信息储存在['rgb_seg_vp']里 (480,640,5) 分割信息保存在seg            
        	rgb_img=m['rgb_seg_vp'][:,:,:3]            
        	#修改通道 使之恢复为为原始的rgb图像            
        	b=rgb_img[:,:,0]            
        	g=rgb_img[:,:,1]            
        	r=rgb_img[:,:,2]           
        	rgb_img=cv2.merge((r,g,b))            
        	seg=m['rgb_seg_vp'][:,:,3] 
        	#file_name=root_path+'/'+mat_file.split('/')[-1].split('.')[0]     
        	file_name=save_path+'/'+root_path.split('/')[-1]+'_'+mat_file.split('/')[-2]+'_'+mat_file.split('/')[-1].split('.')[0]
        	seg[(seg!=10)&(seg!=11)&(seg!=12)&(seg!=13)&(seg!=15)&(seg!=16)]=0
        	segs.append(seg)            
        	masks.append(rgb_img)            
        	file_names.append(mat_file)              
        print('get segmentations finish!')    
        return masks,segs,file_names
def draw_box(img, boxes, colors,clses):
    """ plots one bounding box on image img """   
    lw = max(round(sum(img.shape) / 2 * 0.003), 2)    
    tf = max(lw - 1, 1)  # font thickness    
    for box, color,cls in zip(boxes, colors,clses):        
    cv2.rectangle(img, (box[0], box[1]), (box[2], box[3]), color, thickness=2, lineType=cv2.LINE_AA)        
    cv2.putText(img,cls , (box[0], box[1] - 2), 0, lw / 3,color, thickness=tf,                        lineType=cv2.LINE_AA)    
    #plt.imshow(img)    
    #plt.axis('off')    
    #plt.show()



def get_bbox(ori_masks,seg_masks,file_names, needed):    
""" get bbox from semantic label """    
	print('start converting')    
	#for mask_2D in seg_masks:    
	for canvas,mask_2D,name in zip(ori_masks,seg_masks,file_names):       
	 #print(canvas,mask_2D)        
	 h=canvas.shape[0]        
	 w=canvas.shape[1]        
	 #保存标注信息的地址       
	 anno_dir='/data/dataset/TrafficMarking/VPGNet/labels'
	 img_name=name.replace('mat','txt')        
	 #print(img_name.split('/'))        
	 anno_name=root_path.split('/')[-1]+'_'+name.split('/')[-2]+'_'+img_name.split('/')[-1]        
	 anno_path=os.path.join(anno_dir,anno_name.strip())        
	 print(anno_path)        
	 mask_to_save = np.zeros_like(mask_2D)        
	 # instances are encoded as different colors        
	 obj_ids = np.unique(mask_2D)        
	 # split the color-encoded mask into a set of binary masks        
	 masks = mask_2D == obj_ids[:, None, None]        
	 # get bounding box coordinates for each mask        
	 num_objs = len(obj_ids)        
	 boxes, colors,clses = [], [],[]        
	 for i in range(num_objs):            
	 	clsid = obj_ids[i]            
	 	#name = list(label_dict.keys())[int(id)]            
	 	if clsid in needed:                
	 		binary = masks[i].astype(np.int8)                
	 		num_labels, labels = cv2.connectedComponents(binary, connectivity=8, ltype=cv2.CV_16U)                
	 		for id_label in range(1, num_labels):                    
	 			temp_mask = labels == id_label                    
	 			pos = np.where(temp_mask)                    
	 			xmin = np.min(pos[1])+5                    
	 			xmax = np.max(pos[1])-5                    
	 			ymin = np.min(pos[0])+5                    
	 			ymax = np.max(pos[0])-5
	 			
                    		#保存为yolo格式的txt信息                 
                        	cx=np.array((xmin+xmax)/(2*w))
                        	cy=np.array((ymin+ymax)/(2*h))
				bw=np.array((xmax-xmin)/w)  
                        	bh=np.array((ymax-ymin)/h) 
           

                   
                        	# filter result by setting threshold of width and hegith: 0.04
                        	if bw >= 0.04 and bh >= 0.04:
                                	boxes.append([xmin, ymin, xmax, ymax])
                                	color = [0,255,0]
                                	colors.append(color)
                                	clses.append(label_dict[clsid])
                                	mask_to_save[pos] = id_label
                                	with open(anno_path,'a+')  as  f:
                                    		f.writelines([str(clsid),' ',str(cx),' ',str(cy),' ',str(bw),' ',str(bh),'\n'])                           
                                    		f.close()


        # draw  bbox        
        #draw_box(canvas, boxes, colors,clses)
        #cv2.imwrite('/home/nianliu/wangxx/yolov5_onnx_inference/bbox.png',canvas
if __name__=='__main__':    
     needed_clsid=[10,11,12,13,15,16]
     root_path='/data/dataset/TrafficMarking/VPGNet/scene_3' #四个scene文件夹分别处理
     ori_masks,segs,file_names=get_seg(root_path)
     get_bbox(ori_masks,segs,file_names,needed_clsid) 
          


通过上面的代码即可将分割标签转化为yolo格式的目标检测bbox标签。

在这里插入图片描述

在这里插入图片描述

  • 0
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 9
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值