YOLO模型训练自己数据-VOC格式数据集制作-ubuntu c++文件夹内图片批量读取与重命名

参考)YOLOv2训练自己的数据集(voc格式)进行实验,基本上是正确的,但其初始给出的代码并非是在linux下可以运行的,因此参考部分博客写了下面的程序,可以实现对文件夹内图片的批量读取以及更改名称符合VOC数据集习惯。另原文有部分小错误,本文已经修改,但后文属于转载,版权属原作者所有,本文仅为记录和交流用。如下文所示。

1 准备数据

首先准备好自己的数据集,最好固定格式,此处以VOC为例,采用jpg格式的图像,在名字上最好使用像VOC一样类似000001.jpg、000002.jpg这样。可使用下面示例代码
#include <dirent.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <opencv2/opencv.hpp>

#define img_num 2000
char img_file[img_num][1000];

int list_dir_name(char* dirname,int tabs)
{
    DIR* dp;
    struct dirent* dirp;
    struct stat st;
    char tab[tabs + 1];
		char img_count=0;

    /* open dirent directory */
    if((dp = opendir(dirname)) == NULL)
    {
        perror("opendir");
        return -1;
    }



    /* fill tab array with tabs */
    memset(tab,'\t',tabs);
    tab[tabs] = 0;

    /**
     * read all files in this dir
     **/
    while((dirp = readdir(dp)) != NULL)

    {
        char fullname[255];
        memset(fullname,sizeof(fullname));

        /* ignore hidden files */
        if(dirp->d_name[0] == '.')
            continue;

        /* display file name */
        //printf("img_name:%s\n",dirp->d_name);

        strncpy(fullname,dirname,sizeof(fullname));
        strncat(fullname,dirp->d_name,sizeof(fullname));
	    strcat(img_file[img_count++],fullname);				
	    printf("Image %3d path:%s\n",img_count-1,img_file[img_count-1]);//fullname=dir+file name,the absolute path of the image file        

				/* get dirent status */
        if(stat(fullname,&st) == -1)
        {
            perror("stat");
            fputs(fullname,stderr);
            return -1;
        }
        /* if dirent is a directory,call itself */
        if(S_ISDIR(st.st_mode) && list_dir_name(fullname,tabs + 1) == -1)
            return -1;
    }
    return img_count;

}

int main(int argc,char* argv[])
{
	char* dir="/home/robot/Downloads/mark_recognition/car_img/simple_3class/";
        printf("%s\n",dir);

        char sum=list_dir_name(dir,1);
	printf("Img total num:%d\n",sum);

	int i;
	char order[1000];

	char txt_path[1000];
	char* txt_name="train.txt";
	memset(txt_path,sizeof(txt_path));
	strcat(txt_path,dir);
	strcat(txt_path,txt_name);
	FILE *fp = fopen(txt_path,"w");

	for (i = 0; i<sum; ++i)
	{
		char img_path[1000];
		memset(img_path,sizeof(img_path));

		printf("Source %s\n",img_file[i]);
		IplImage *pSrc = cvLoadImage(img_file[i]);
		sprintf(order,"%05d.jpg",i);
		strcat(img_path,dir);
		strcat(img_path,order);
		cvSaveImage(img_path,pSrc);
		fprintf(fp,"%05d\n",i);
		
		printf("Save as%s\n",img_path);
		cvReleaseImage(&pSrc);
	}
	fclose(fp);

	

	return 0;
}







准备好了自己的图像后,需要按VOC数据集的结构放置图像文件。VOC的结构如下
[plain] view plain copy
  1. --VOC
  2. --Annotations
  3. --ImageSets
  4. --Main
  5. --Layout
  6. --Segmentation
  7. --JPEGImages
  8. --SegmentationClass
  9. --SegmentationObject
这里面用到的文件夹是 Annotations、ImageSets和JPEGImages。其中文件夹 Annotation中主要存放xml文件,每一个xml对应一张图像,并且每个xml中存放的是标记的各个目标的位置和类别信息,命名通常与对应的原始图像一样;而ImageSets我们只需要用到Main文件夹,这里面存放的是一些文本文件,通常为train.txt、test.txt等,该文本文件里面的内容是需要用来训练或测试的图像的名字(无后缀无路径);JPEGImages文件夹中放我们已按统一规则命名好的原始图像。
因此,首先
1.新建文件夹VOC2007(通常命名为这个,也可以用其他命名,但一定是名字+年份,例如MYDATA2016,无论叫什么后面都需要改相关代码匹配这里,本例中以 VOC2007为例)
2.在VOC2007文件夹下新建三个文件夹 Annotations、ImageSets和JPEGImages,并把准备好的自己的原始图像放在JPEGImages文件夹下
3.在ImageSets文件夹中,新建三个空文件夹Layout、Main、Segmentation,然后把写了训练或测试的图像的名字的文本拷到Main文件夹下,按目的命名,我这里所 有图像用来训练,故而Main文件夹下只有train.txt文件。上面代码运行后会在图片文件夹内生成该文件,把它拷进去即可。

2 用YOLOv2训练

1.生成相关文件

按darknet的说明编译好后,接下来在darknet-master/scripts文件夹中新建文件夹VOCdevkit,然后将整个VOC2007文件夹都拷到VOCdevkit文件夹下。
然后,需要利用scripts文件夹中的voc_label.py文件生成一系列训练文件和label,具体操作如下:
首先需要修改voc_label.py中的代码,这里主要修改数据集名,以及类别信息,我的是VOC2007,并且所有样本用来训练,没有val或test,并且只检测人,故只有一类 目标,因此按如下设置
import xml.etree.ElementTree as ET  
import pickle  
import os  
from os import listdir,getcwd  
from os.path import join  
  
#sets=[('2012','train'),('2012','val'),('2007','test')]  
  
#classes = ["aeroplane","bicycle","bird","boat","bottle","bus","car","cat","chair","cow","diningtable","dog","horse","motorbike","person","pottedplant","sheep","sofa","train","tvmonitor"]  
  
sets=[('2007','train')]  
classes = [ "person"]  
  
  
def convert(size,box):  
    dw = 1./size[0]  
    dh = 1./size[1]  
    x = (box[0] + box[1])/2.0  
    y = (box[2] + box[3])/2.0  
    w = box[1] - box[0]  
    h = box[3] - box[2]  
    x = x*dw  
    w = w*dw  
    y = y*dh  
    h = h*dh  
    return (x,y,w,h)  
  
def convert_annotation(year,image_id):  
    in_file = open('VOCdevkit/VOC%s/Annotations/%s.xml'%(year,image_id))  #(如果使用的不是VOC而是自设置数据集名字,则这里需要修改)  
    out_file = open('VOCdevkit/VOC%s/labels/%s.txt'%(year,image_id),'w')  #(同上)  
    tree=ET.parse(in_file)  
    root = tree.getroot()  
    size = root.find('size')  
    w = int(size.find('width').text)  
    h = int(size.find('height').text)  
  
    for obj in root.iter('object'):  
        difficult = obj.find('difficult').text  
        cls = obj.find('name').text  
        if cls not in classes or int(difficult) == 1:  
            continue  
        cls_id = classes.index(cls)  
        xmlbox = obj.find('bndbox')  
        b = (float(xmlbox.find('xmin').text),float(xmlbox.find('xmax').text),float(xmlbox.find('ymin').text),float(xmlbox.find('ymax').text))  
        bb = convert((w,h),b)  
        out_file.write(str(cls_id) + " " + " ".join([str(a) for a in bb]) + '\n')  
  
wd = getcwd()  
  
for year,image_set in sets:  
    if not os.path.exists('VOCdevkit/VOC%s/labels/'%(year)):  
        os.makedirs('VOCdevkit/VOC%s/labels/'%(year))  
    image_ids = open('VOCdevkit/VOC%s/ImageSets/Main/%s.txt'%(year,image_set)).read().strip().split()  
    list_file = open('%s_%s.txt'%(year,image_set),'w')  
    for image_id in image_ids:  
        list_file.write('%s/VOCdevkit/VOC%s/JPEGImages/%s.jpg\n'%(wd,year,image_id))  
        convert_annotation(year,image_id)  
    list_file.close()

修改好后在该目录下运行命令:python voc_label.py,之后则在文件夹scripts\VOCdevkit\VOC2007下生成了文件夹lable,该文件夹下的画风是这样的

这里包含了类别和对应归一化后的位置(i guess,如有错请指正)。同时在scripts\下应该也生成了train_2007.txt这个文件,里面包含了所有训练样本的绝对路径。

2.配置文件修改

做好了上述准备,就可以根据不同的网络设置(cfg文件)来训练了。在文件夹cfg中有很多cfg文件,应该跟caffe中的prototxt文件是一个意思。这里以tiny-yolo-voc.cfg为例,该网络是yolo-voc的简版,相对速度会快些。主要修改参数如下

copy
    .
  1. .
  2. .
  3. [convolutional]
  4. size=1
  5. stride=1
  6. pad=1
  7. filters=30//修改最后一层卷积层核参数个数,计算公式是依旧自己数据的类别数filter=num×(classes+coords+1)=5×(1+4+1)=30
  8. activation=linear
  9. [region]
  10. anchors=1.08,1.19,3.42,4.41,6.63,11.38,9.42,5.11,16.62,10.52
  11. bias_match=1
  12. classes=1//类别数,本例为1类
  13. coords=4
  14. num=5
  15. softmax=1
  16. jitter=.2
  17. rescore=1
  18. object_scale=5
  19. noobject_scale=1
  20. class_scale=1
  21. coord_scale=1
  22. absolute=1
  23. thresh=.6
  24. random=1
另外也可根据需要修改learning_rate、max_batches等参数。这里歪个楼吐槽一下其他网络配置,一开始是想用tiny.cfg来训练的官网作者说它够小也够快,但是它的网络配置最后几层是这样的画风:

[html] copy
    [convolutional]
  1. filters=1000
  2. size=1
  3. stride=1
  4. pad=1
  5. activation=linear
  6. [avgpool]
  7. [softmax]
  8. groups=1
  9. [cost]
  10. type=sse
这里没有类别数,完全不知道怎么修改,强行把最后一层卷积层卷积核个数修改又跑不通会出错,如有大神知道还望赐教。

修改好了cfg文件之后,就需要修改两个文件,首先是data文件下的voc.names。打开voc.names文件可以看到有20类的名称,本例中只有一类,检测人,因此将原来所有内容清空,仅写上person并保存,备注:若此处为多个类的训练,请同voc_label.py 中顺序一致

接着需要修改cfg文件夹中的voc.data文件。也是按自己需求修改,我的修改之后是这样的画风:

copy
    classes=1//类别数
  1. train=/home/kinglch/darknet-master/scripts/2007_train.txt//训练样本的绝对路径文件,也就是上文2.1中最后生成的
  2. //valid=/home/pjreddie/data/voc/2007_test.txt//本例未用到
  3. names=data/voc.names//上一步修改的voc.names文件
  4. backup=/home/kinglch/darknet-master/results///指示训练后生成的权重放在哪
修改后按原名保存最好,接下来就可以训练了。

ps:yolo v1中这些细节是直接在源代码的yolo.c中修改的,源代码如下

比如这里的类别,训练样本的路径文件和模型保存路径均在此指定,修改后从新编译。而yolov2似乎摈弃了这种做法,所以训练的命令也与v1版本的不一样。

3.运行训练

上面完成了就可以命令训练了,可以在官网上找到一些预训练的模型作为参数初始值,也可以直接训练,训练命令为

./darknet detector train ./cfg/voc.data cfg/tiny-yolo-voc.cfg

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


文章浏览阅读2.3k次,点赞4次,收藏22次。最近安装了CARLA预编译版,总体过程感觉还是挺简单的,但是由于在网上找的参考资料并没有和自己遇到的情况完全一样的,所以把自己的安装过程记录下来,方便和自己一样的后来人进行安装,同时也自己作个记录留作备忘。其实预编译版的CARLA本身几乎不用什么命令行进行安装,主要步骤只有解压缩和拷贝文件,和极少的命令行安装操作。但是相关依赖以及其它的CARLA所使用的一些工具需要一起安装好,下面一起来看看安装步骤吧。_ubuntu22.04安装carla
文章浏览阅读6.3k次,点赞5次,收藏15次。在清华镜像中下载Ubuntu 20 安装包_ubuntu20下载
文章浏览阅读5k次。linux环境, python3.7.问题描述: 安装rally, pip3 install -r requirements.txt 时提示如下: 说明openssl 已安装。解决:1. pip3 install --upgrade pip , 结果输出如下 ..._error: command '/usr/bin/gcc' failed with exit code 1
文章浏览阅读1.1k次。自己刚踩坑装好的W11 WSL2 miniconda_wsl2 cuda
文章浏览阅读4.2k次,点赞4次,收藏17次。要安装这个 standalone的,会有一点区别(不识别 下面的 -localhost no)上面的命令会在~/.vnc/目录下生成一个 passwd文件。具体端口号,可以查看vncserver -list返回结果中的RFB PROT。作用是vncserver启动的时候运行这些命令,把桌面程序启动起来。如果希望用某个用户比如 demo登录,就用su切换到这个用户。桌面版默认就已安装,服务器版需要手动安装,并启动。关闭某个会话可以用下面的命令。远程地址输入ip:port。查看全部的vnc会话。_ubuntu vncserver
文章浏览阅读894次,点赞51次,收藏31次。在安卓使用vscode主要是连接一个远程的code-server服务,code-server服务安装在什么系统,调用的就是什么系统的环境,如这里使用ubuntu进行安装code-server,那使用的就是ubuntu环境,如需要go,python,java开发,需要在Ubuntu安装相关环境,创建的文件夹和项目也是在Ubuntu里面.这种方式其实在访问vscode的时候利于可以随时随地进行连接使用,且不受设备影响。
安装Ubuntu上超好用的终端Terminator。通过添加软件源、更新源、安装Terminator等步骤完成。
文章浏览阅读1.1k次,点赞83次,收藏74次。不要嫌弃Ubuntu的单调的终端界面啦,快来试试这些有意思的命令_ubuntu系统有趣的玩法
文章浏览阅读2.5k次。在ubuntu系统中,swap空间就是虚拟内存,所以考虑在磁盘空间富余的目录下设置虚拟内存swap文件,用来缓解内存不足的问题。通过上面的信息可以看到,/dev/vda2 目录下还剩余45G,那么就可以把swap文件生成在/dev/vda2目录下。在系统监控中发现,当数据库服务程序启动后,占用了大量内存空间,导致系统的剩余的内存往往只有几十MB。# bs 为块的大小,count 创建多少个块。# 执行命令后,删除创建的swap目录即可。#把生成的文件转换成 Swap 文件。2、创建一个swap文件。_ubuntu20修改swap大小
文章浏览阅读2.9k次,点赞2次,收藏10次。记录RV1126的SDK编译错误,以及解决处理_command exited with non-zero status 1
文章浏览阅读1.1w次,点赞22次,收藏101次。【记录】ubuntu20.04安装nvidia显卡驱动_ubuntu20.04安装nvidia显卡驱动
文章浏览阅读727次,点赞6次,收藏27次。在嵌入式Linux开发过程中,可能遇到uboot无法通过nfs服务从Ubuntu下载系统镜像(TTTTTT)的问题。如果你使用的是较新版本的Ubuntu,那么其**默认内核将不支持nfs2**!而**uboot仅支持到nfs2**,因此我们需要修改系统内核以及nfs配置文件,开启nfs2服务。**此问题非常棘手**,因为问题出现的时间太近,并且使用的人少。由于是2023年后才出现的问题,**chatgpt也无法解答**!本文参考网络上多篇博客资料,是解决此问题的最新办法。
ubuntu系统下安装软件的方法有多种,包括使用apt工具、deb软件包安装、源码编译安装以及通过软件中心安装。还有一种以 .run 后缀的软件包也可以在ubuntu系统下安装。具体的安装方法可以通过百度搜索来获取。
文章浏览阅读814次。本篇目的:Xubuntu如何安装pkg-configpkg-config是一个计算机软件包,用于帮助开发人员查找、定位和使用依赖库。它通常用于构建软件时,开发人员需要指定程序所依赖的外部库的位置和版本信息。使用pkg-config,开发人员可以很容易地查找、检索和导出这些依赖库的信息,从而简化了软件的构建过程。_ubuntu中怎么下载pkg-config
文章浏览阅读2k次。ubuntu创建共享文件夹_ubuntu20.04共享文件夹
文章浏览阅读2.9k次,点赞74次,收藏73次。对于有长期远程桌面需求的用户,建议将cpolar套餐升级到专业套餐,支持配置固定的公网TCP端口,且带宽也会相应的增大,支持更高效便捷的远程桌面连接Ubuntu系统。【cpolar内网穿透支持http/https/tcp协议,支持永久免费使用,不限制流量,无需公网IP,也不用进入路由器设置,操作简单。隧道创建成功后,点击左侧仪表盘的状态——在线隧道列表,查看xrdp隧道的所生成的公网TCP端口地址,复制下来。,使用cpolar内网穿透映射3389端口,生成公网TCP端口地址,实现在公网环境下,_ubuntu 局域网桌面
文章浏览阅读3.2k次。而在linux的ubuntu版本中,又多出两类用户:安装ubuntu系统的源用户xxx,其与root具有相同权限,仅在执行命令时,前面加sudo。在ubuntu中,用命令deluser username可以直接删除用户账号及家目录,而用centos7中的命令userdel -r username才能达到同样目的。在ubuntu中,没有moduser命令,centos7中的usermod修改用户信息的命令,同样可以用在ubuntu中。在系统中,创建新的用户或称为账号,一般需要多步操作。_ubuntu创建一个新用户
文章浏览阅读1.6w次,点赞4次,收藏23次。系统的许多日志文件都存储在 /var/log 目录中。你可以使用 ls /var/log 命令来列出可用的日志文件。/var/log/Xorg.0.log:包含 X 服务器的日志信息(图形界面)。打开DASH,搜索日志或者log,打开app,这个是/var/log的界面版。这将显示系统日志的末尾,并提供有关系统崩溃和错误的信息。/var/log/kern.log:包含内核日志信息。/var/log/dmesg:包含开机时的日志信息。/var/log/syslog:包含系统日志信息。_ubuntu查看系统日志
文章浏览阅读857次。首先将source.list复制为source.list.bak备份,然后将source.list内容改为需要的镜像源列表即可。Ubuntu采用apt作为软件安装工具,其镜像源列表记录在/etc/apt/source.list文件中。本节均为 Ubuntu 20.04 的镜像源列表。若为其他版本,将所有focal更改为其他版本代号即可。_apt 国内源