读取voc中的数据集路径修改_基于ROS搭建简易软件框架实现ROV水下目标跟踪(十二)--数据集制作...

本文详细介绍了如何在ROS环境下利用darknet_ros进行目标跟踪,包括数据包录制、视频提取图片、批量修改文件名、使用labelImg进行图片标注,以及将标注数据转换为满足Yolo训练格式的过程。
摘要由CSDN通过智能技术生成

在目标跟踪时,摄像头提供实时的图片信息,我们需要识别出图片目标,且输出目标在图片中的位置,为后续的控制提供条件。在demo中,我是借助darknet_ros实现这一目标。当然,这一模块可以替换成性能更优秀的识别算法。

darknet_ros为yolov3在ros下的一个工具包(链接)。需要对yolov3的使用有所了解(连接)。例程我就不介绍了,可以在网上搜索。在此主要基于demo测试介绍我个人的使用情况,主要包括摄像头驱动、数据集制作、模型训练、模型部署。

本文主要介绍用于yolo训练的数据集的制作。

1、数据包录制

当摄像头能正常工作时,我们就可以录制视频数据。ros下采集数据十分方便,鉴于我们只需要图片数据,由上文说明,图片数据的topic为/usb_cam/image_raw,则利用rosbag record指令:

rosbag record /usb_cam/image_raw -O 001

结果我们在当前路径获得录制好的视频数据包001.bag。我们可以依次录制002、003等等的数据包。

2、视频数据包提取图片

安装图片处理依赖包:

sudo apt-get install mjepgtools
sudo apt-get install ffmpeg

依旧借助image_view(连接)工具:

rosrun image_view extract_images _sec_per_frame:=0.01 image:=<IMAGETOPICINBAGFILE>

其中,IMAGETOICINBAGFILE为图片topic。图像数据保存在当前目录下。以001.bag为例,需要依次新建三个终端执行:

roscore
rosrun image_view extrac_images _sec_per_frame:=0.01 image:=/usb_cam/image_view
rosbag play 001.bag

3、批量修改文件名

借助rename指令:

rename -v ‘s/frame/1_’ *.jpg

结果将使得提取出来的文件夹中的图片文件名由frame0000.jpg、frame0001.jpg修改为1_0000.jpg,1_0001.jpg。

4、图片标注

图片标注的工具非常多,在此我只介绍一下我所使用的labelImg(链接)。按照教程步骤安装即可,然后python labelImg.py。

在使用时报错:

ImportError: No module named PyQt4.QtCore

很容易在网上找到原因及解决方法:

pyqt5没有string这个类,找到解决方法:在labelImg文件夹下编辑 libs/ustr.py这个文件,修改插入如下代码:

try:
    from PyQt4.QtCore import QString  
except ImportError:
    # we are using Python3 so QString is not defined
    QString = str

5、制作满足yolo训练需求格式的数据集

在此我大致列出制作训练demo使用的模型所需的数据集的步骤。在此说明一下,我一共录制了6个数据包,因此得到6个存放图片数据的文件夹。1号文件夹内的图片名为1_0000.jpg,1_0001.jpg,…;2号文件夹内的图片名为2_0000.jpg,2_0001.jpg,…;以此类推;

①在/darknet_ros/darknet路径下新建数据集存放文件夹cabin_data/data;

②在data路径下新建文件夹1存放1号文件夹图片数据;

③在文件夹1内新建文件夹JPEGImages,将1号文件夹图片复制至此路径;

④在文件夹1内新建文件夹Annotations,用于存放labelImg标注数据。

⑤使用labelImg标注图片数据,标注格式为Pascal VOC,存储路径为Annotations文件夹,路径下将得到标注的xml数据,当然labelImg支持yolo标注格式,但我觉得后面使用脚本转换更方便;

⑥在文件夹1内新建labels文件夹,运行xml_to_txt_label.py,将VOC标注数据转成yolo标注数据,路径下将得到转换后的txt数据;

#xml_to_txt_label.py
import os
import os.path
import xml.etree.ElementTree as ET
import glob
 
class_names = ['sea_cucumber']
xmlpath='/home/pcl-02/darknet_ws/src/darknet_ros/darknet/cabin_data/data/1/Annotations'
txtpath='/home/pcl-02/darknet_ws/src/darknet_ros/darknet/cabin_data/data/1/labels'
 
 
def xml_to_txt(xmlpath,txtpath):
 
    os.chdir(xmlpath)
    annotations = os.listdir('.')
    annotations = glob.glob(str(annotations)+'*.xml')
 
    #file_save = 'train' + '.txt'
    #file_txt = os.path.join(txtpath, file_save)
    #f_w = open(file_txt, 'w')
 
    for i,file in enumerate(annotations):
 
        in_file = open(file)
        filename_prefix = file[:-4]
        tree=ET.parse(in_file)
        root = tree.getroot()
 
        file_save = filename_prefix + '.txt'
        file_txt = os.path.join(txtpath, file_save)
        f_w = open(file_txt, 'w')
 
 
        filename = root.find('filename').text
 
        for obj in root.iter('object'):
                current = list()
                name = obj.find('name').text
 
                class_num = class_names.index(name)
 
                xmlbox = obj.find('bndbox')
 
                x1 = xmlbox.find('xmin').text
                x2 = xmlbox.find('xmax').text
                y1 = xmlbox.find('ymin').text
                y2 = xmlbox.find('ymax').text
 
                x = (float(x1) + float(x2)) / 2.0 / 800.0
                y = (float(y1) + float(y2)) / 2.0 / 600.0
                width = (float(x2) - float(x1)) / 800.0
                height = (float(y2) - float(y1)) / 600.0
                #print x,y,width,height
 
                #f_w.write(str(class_num)+','+'x1+','+y1+','+x2+','+y2+','+'n')
                f_w.write(str(class_num)+' '+str(x)+ ' '+str(y)+' '+str(width)+' '+str(height))
 
xml_to_txt(xmlpath,txtpath)
 

⑦在文件夹1内新建ImageSets/Main文件夹,运行train_val_test.py,划分训练集,验证集及测试集,在路径下得到test.txt,train.txt,trainval.txt,val.txt,最后得到cabin_data/data/1路径下情况将如下所示

3b800ee3a5f5cf3573dd31ba357ac475.png
#train_val_test.py
import os
import random
 
test_percent = 0.2
val_percent = 0.2
xmlfilepath = 'Annotations'
txtsavepath = 'ImageSetsMain'
total_xml = os.listdir(xmlfilepath)
num = len(total_xml)
print num
list = range(num)
test_num = int(num * test_percent)
print test_num
val_num = int(num *  val_percent)
print val_num
test_val_num = test_num + val_num
test_vel_f = random.sample(list, test_val_num)
vel_f = random.sample(test_vel_f, val_num)
 
ftrainval = open('ImageSets/Main/trainval.txt', 'w')
ftest = open('ImageSets/Main/test.txt', 'w')
ftrain = open('ImageSets/Main/train.txt', 'w')
fval = open('ImageSets/Main/val.txt', 'w')
 
for i in list:
    name = total_xml[i][:-4] + 'n'
    if i in test_vel_f:
        if i in vel_f:
            ftrainval.write(name)
            fval.write(name)
        else:
            ftest.write(name)
    else:
        ftrainval.write(name)
        ftrain.write(name)
 
ftrainval.close()
ftrain.close()
fval.close()
ftest.close()

⑧在data路径下新建文件夹ImageSets/Main,将文件夹1内ImageSets/Main下的test.txt、train.txt、val.txt复制至此路径下,且修改文件名为1_test.txt,1_train.txt,1_val.txt,剩余几个数据文件夹同理;

⑨运行combine_datasets.py,将各分数据集合并成总数据集,在data/ImageSets/Main下得到train.txt,val.txt用于训练,在此提一下我只将5个数据包用于制作数据集训练,第六个数据包用于测试模型性能,最后得到cabin_data/data路径下情况如图所示:

b0b1130d0a69f71684fda98f9c9556c6.png

data/ImageSets/Main路径下:

c1e4b87e52105528d9666bdf71e950d9.png
#combine_datasets.py
import os
from os import listdir, getcwd
from os.path import join
 
sets=[('1', 'train'), ('1', 'val'), ('1', 'test'), ('2', 'train'), ('2', 'val'), ('2', 'test'),('3', 'train'), ('3', 'val'), ('3', 'test'), ('4', 'train'), ('4', 'val'), ('4', 'test'),('5', 'train'), ('5', 'val'), ('5', 'test')]
 
wd = getcwd()
 
for year, image_set in sets:
    if not os.path.exists('ImageSets/Main'):
        os.makedirs('ImageSets/Main')
    image_ids = open('%s/ImageSets/Main/%s.txt'%(year, image_set)).read().strip().split()
    list_file = open('ImageSets/Main/%s_%s.txt'%(year, image_set), 'w')
    for image_id in image_ids:
        list_file.write('%s/%s/JPEGImages/%s.jpgn'%(wd, year, image_id))
    list_file.close()
 
os.system("cat ImageSets/Main/1_train.txt ImageSets/Main/1_test.txt ImageSets/Main/2_train.txt ImageSets/Main/2_test.txt ImageSets/Main/3_train.txt ImageSets/Main/3_test.txt ImageSets/Main/4_train.txt ImageSets/Main/4_test.txt ImageSets/Main/5_train.txt ImageSets/Main/5_test.txt> ImageSets/Main/train.txt")
os.system("cat ImageSets/Main/1_val.txt ImageSets/Main/2_val.txt ImageSets/Main/3_val.txt ImageSets/Main/4_val.txt ImageSets/Main/5_val.txt> ImageSets/Main/val.txt")
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值