详细教程——LaneNet-Lane-Detection车道检测,训练自己的数据集

写在最前,经历过社会的毒打,才知道这么个好东西:github上除了下载代码,还有好多大神讨论的留言,快来看看有没有你需要的!

Issues · MaybeShewill-CV/lanenet-lane-detection · GitHub

点击closed可以看到更多已经结帖的讨论

(1)源代码:https://github.com/MaybeShewill-CV/lanenet-lane-detection,获取于2020.07.08

GitHub大佬更新的比较勤快,后续更改的还请多看GitHub描述

update in 2020.11.10

我前几天下载的压缩文件中,发现lanenet-lane-detection-master\data\training_data_example下的文件夹名字变了,我大概看了一下代码,好像用的还是以前的文件夹名字,下面第一个是我用的,第二个是现在下载文件里的,运行的时候可以自己看一下代码

(2)环境:ubuntu 16.0.4(x64), python3.5, cuda-9.0, cudnn-7.0,TESLA P100 GPU(阿里云服务器,内存16GB),tensorflow_gpu==1.12.0,requirements.txt中opencv修改成opencv-python

注:环境中没有安装tensorflow,手动安装一个即可,版本最好也是1.12,我在1.12下运行成功了,其他缺啥安装啥即可

安装了tensorflow_gpu==1.12.0即可,tensorflow可以不用安装,安装的版本过高,反而会导致不用GPU训练

CUDNN7.0 貌似有点问题,我自己在Windows上和Ubuntu上运行的时候都报错了,提示的是需要在7.0(或者7.2)以上版本运行,但是7.2好像已经下载不到,不更新了,最后下载的7.3.1运行成功

update in 2020.11.10

经测,目前来说tensorflow版本在2.0及其以上时,程序会有问题,降版本即可,我用的tensorflow2.1,发现t文件无法生成,降版本后成功生成

tensorflow_gpu2.0以上版本是否可用待测

 

(3)labelme标注自己的数据集:网上文章多,比较容易解决

综述在前,实际步骤包括(3.1)(3.2)(3.3)

自己遇到的问题:labelme:缺少生成"info.yaml"文件[实际不影响,可以不进行处理]

添加传送门:https://blog.csdn.net/winter616/article/details/104426111,亲测有效

添加传送门:https://blog.csdn.net/flana/article/details/105098470,这是Lanenet网络Tusimple数据集国内源下载,亲测有效,就是某盘速度感人,but相比国外的源,还是快多了

使用labelme运行labelme_json_to_dataset xxx.json报错TypeError: only integer scalar arrays can be converted

添加传送门:https://blog.csdn.net/nuohanfengyun/article/details/105973104

结果:生成json文件夹,包含img.png、info.yaml、label.png、label_names.txt、label_viz.png五个文件

注:labelme 中选择 create linestrip和create point均可,line也OK,从某位大佬在简书中的评论推测出的,我自己用的create line

此处是迷惑了我许久的地方,网上的TuSimple数据集真的是看起来奇形怪状,而下载TuSimple数据集又太慢,某盘大概需要30H,一般人看不到原始数据集和他处理后的样子,所以自己在处理很多错误的时候不太自信,会怀疑自己的数据集有问题,SO,我还是决定写下这部分的流程,并尽可能的通俗简化。

先贴一下Lanenet网络Tusimple数据集中test_set.zip的文件结构吧,这是原始的压缩文件,我没处理过,有机会试试

 

(3.1)用labelme工具,view中选择create linestrip,标注车道线,最后的成果是一堆Image_Name.json

注:因为需要实例分割,所以应该标注line1,line2,line3,line4……

不同的车道线标注不同的label

(3.2)json数据转换,原理是使用labelme_json_to_dataset.exe Image_Name.json命令,可以找一些批量处理的代码

注意路径!!!注意路径!!!注意路径!!!

 

结果:生成Image_Name_json文件夹,如下

 

每一个Image_Name_json文件夹中的内容如下:

我用的批量处理代码如下:()忘了是哪位大佬的代码了

import os
path = '/.../1/New'  # path为json文件存放的路径
json_file = os.listdir(path)
#os.system("activate envs")    #博主labelme所在的环境名就叫envs,所以修改成了activate envs
for file in json_file: 
    os.system("labelme_json_to_dataset.exe %s"%(path + '/' + file))

 

update in 2020.11.10

运行py文件,闪退,在IDLE中运行提示activate/labelme_json_to_dataset.exe不是内部或者外部命令,也不是可以运行的程序或者批处理文件,但是labelme可以正常启动,是不是很崩溃?

百度提示是环境变量配置不对,经查,因为重装过anaconda,第二次安装的路径与第一次安装的路径差一个大小写字母,所以虽然anaconda+labelme可以用,但是在调用命令的时候会找不到命令

 

 

(3.3)数据集处理:json格式---->TuSimple数据集

这步的目标是,将json格式的数据进行转换,生成我们下面需要的三个文件夹与一个TXT文件

该步与下一步骤息息相关,有做法两种,其核心思想是一样的,只不过可能代码实现的方式略有差异,私以为和数据集的组织方式有关吧,不同版本,反正我自己的数据我没办法组织的和原始数据源一致,我自己采用的第二种

做法一:来源文章::https://blog.csdn.net/qq_40900196/article/details/102840850

步骤:python tools/generate_tusimple_dataset.py --src_dir '数据集存放的路径(解压后)'

update in 2020.11.10

代码作者在评论说了,目前代码已经修改为第二种方式

 

做法二:来源文章::https://blog.csdn.net/qq_26894673/article/details/100052191

参考他的第三步的代码,改一下自己的路径即可,需要注意  gt_image/gt_binary_image/gt_instance_image 的名字有的是代码名称不太一样

下面的代码更适合本文,貌似是少了一个for

import cv2
from skimage import measure, color
from skimage.measure import regionprops
import numpy as np
import os
import copy

def skimageFilter(gray):
    binary_warped = copy.copy(gray)
    binary_warped[binary_warped > 0.1] = 255
    gray = (np.dstack((gray, gray, gray))*255).astype('uint8')
    labels = measure.label(gray[:, :, 0], connectivity=1)
    dst = color.label2rgb(labels,bg_label=0, bg_color=(0,0,0))
    gray = cv2.cvtColor(np.uint8(dst*255), cv2.COLOR_RGB2GRAY)
    return binary_warped, gray

def moveImageTodir(path,targetPath,name):
    if os.path.isdir(path):
        image_name = "gt_image/"+str(name)+".png"
        binary_name = "gt_binary_image/"+str(name)+".png"
        instance_name = "gt_instance_image/"+str(name)+".png"
        train_rows = image_name + " " + binary_name + " " + instance_name + "\n"
        origin_img = cv2.imread(path+"/img.png")
        origin_img = cv2.resize(origin_img, (1280,720))
        cv2.imwrite(targetPath+"/"+image_name, origin_img)
        img = cv2.imread(path+'/label.png')
        img = cv2.resize(img, (1280,720))
        gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
        binary_warped, instance = skimageFilter(gray)
        cv2.imwrite(targetPath+"/"+binary_name, binary_warped)
        cv2.imwrite(targetPath+"/"+instance_name, instance)
        print("success create data name is : ", train_rows)
        return train_rows
    return None

if __name__ == "__main__":
    count = 1
    with open("THE PATH TO YOUR /train.txt", 'w+') as file:
        #for images_dir in os.listdir("./images"):
            dir_name = os.path.join("THE PATH TO YOUR/annotations")
            for annotations_dir in os.listdir(dir_name):
                json_dir = os.path.join(dir_name, annotations_dir)
                if os.path.isdir(json_dir):
                    train_rows = moveImageTodir(json_dir, "THE PATH TO YOUR SAVE DIR", str(count).zfill(4))
                    file.write(train_rows)
                    count += 1

Final,将上述三个文件夹与一个TXT文件拷贝入lanenet-lane-detection-master\data\training_data_example文件夹下

(4)数据集处理:TuSimple数据集---->Tfrecords

这块儿是我比较迷惑的,整理一下既有的类似博客的主流做法,大致有以下几种做法

做法一:来源文章::https://blog.csdn.net/qq_40900196/article/details/102840850

步骤:python data_provider/lanenet_data_feed_pipline.py   --dataset_dir ./data/training_data_example/training/   --tfrecords_dir ./data/training_data_example/tfrecords

思路是先将json格式的数据转换成TuSimple数据集,然后将TuSimple数据集转换成TFRecord

个人感觉这位大佬用的可能是https://github.com/850977164/lanenet-lane-detectionSame person,but different versions)的代码

 

做法二:来源文章::GitHub文章最后

步骤:python tools/make_tusimple_tfrecords.py

思路是先将json格式的数据转换成TuSimple数据集,然后将TuSimple数据集转换成TFRecord

按照我下载的那一版本代码,第二种我成功了,第一种或许会更加适合原始数据集吧

error:from google.protobuf.pyext import _message ImportError: DLL load failed: 找不到指定的程序。

解决:pip install protobuf==3.6.0  

error:

 File "C:\Users\.........\lanenet-lane-detection-master\data_provider\lanenet_data_feed_pipline.py", line 159, in   is_training_sample_index_file_complete
    ops.exists(self._test_example_index_file_path) and \   File "D:\...............\anaconda3\envs\lane\lib\genericpath.py", line 19, in exists
    os.stat(path)
TypeError: stat: path should be string, bytes, os.PathLike or integer, not Config

错误原因,因为yaml文件中缺少TEST_FILE_LIST和    TRAIN_FILE_LIST和    VAL_FILE_LIST中的某一个或某两个路径,就是删除的时候直接把三行中的某一行全删除了

解决:要么补上缺的行,要么自己去修改data_provider/lanenet_data_feed_pipline.py中判断的一些函数

第一个方法简单,第二个方法有收获

 

注:此步骤已经需要更改config文件夹中yaml文件中的路径信息了。。。

(5)训练自己的数据集----Happy

update in 2020.11.10

Add:此处遗忘了需要更改\lanenet-lane-detection-master\config文件夹中的tusimple_lanenet.yaml文件。

 

执行 python tools/train_lanenet_tusimple.py

此处需要更改lanenet-lane-detection-master\config文件夹下的tusimple_lanenet.yaml某些路径,直接记事本打开修改即可

我没有val.txt+test.txt乱起八糟的,我只有train.txt,所以有些loss是nan  

这个可能描述的不对

 

THE END:遇到的问题及解决

(1)执行make_tusimple_tfrecords.py 的 时候提示:OSError: Config file: ./config/tusimple_lanenet.yaml, can not be read

解决办法:执行的是python make_tusimple_tfrecords.py命令 而不是python tools/make_tusimple_tfrecords.py 命令

不要进入tool文件夹下去执行

(2)提示:ImportError: No module named 'local_utils',仔细观察文件夹GitHub下载的文件夹中是有local_utils这个文件夹的,后经大佬提示,解决办法是将下载的代码根目录加到PYTHONPATH环境变量,我用的是Ubuntu系统,

输入:vim .bashrc

输入:i

键入:

#PYTHON

export PYTHONPATH=/root/NEW/:/root/NEW/lanenet-lane-detection-master:$PYTHONPATH

【/root/NEW/:/root/NEW/lanenet-lane-detection-master 是我的路径】

按下:ESC键

键入:wq

键入:source .bashrc

 

update in 2020.11.10

其他类似的问题有ImportError: No module named 'data_provider'等,做法一样

Windows下的做法:直接set PYTHONPATH D:/。。。。。。、/lanenet-lane-detection-master(好像关机后就没了,下次需要重新设置,可以运行前 查一下)

或者在环境变量中将代码根目录添加进去

 

报错:yaml.parser.ParserError: while parsing a block mapping  in "./config/tusimple_lanenet.yaml", line 50, column 5 expected <block end>, but found '<scalar>'   in "./config/tusimple_lanenet.yaml", line 50, column 19

错误原因:据百度是因为不对齐,后来发现是路径的‘’在乱写,有的缺,有的多

 

(3)Train loss: nan的问题

我自己的原因:batch size 大于样本集数目

解决办法:更改lanenet-lane-detection-master\config文件夹下的tusimple_lanenet.yaml中的batch size数目即可

 

update in 2020.11.10

windows下执行python tools/make_tusimple_tfrecords.py,错误:AttributeError: 'NoneType' object has no attribute 'shape'

一般是图片读取失败  

改为全路径,将\改为/

 

(4)训练过程中莫名卡死问题(windows10中使用GTX1660 super开始训练,出现过很多次,内存为6G)

现象:随机卡死,在epoch为几步、几十步、几百步、几千步,随机卡死,最多训练了4000+,然后就是完全卡死,无任何报错,打开任务管理器,cpu使用百分比几乎不变,不像一开始剧烈起伏,GPU使用率也由百分之十左右降为百分之零左右,但GPU内存,仍保持设定比例的占用,点击框,会有是否关闭进程的提示框

尝试一:据查可能是线程互锁导致的,数据量不大,而线程极多,可以尝试减少cpu线程数或者epoch试试,可能不对哈,可以试试,本人试测将bach_size和cup线程数均修改为1,未成功
尝试二:怀疑是数据集问题,经测,应该不是,来回查+重新制作数据集,未成功

尝试三:怀疑是内存不够的问题,我的图片比较大,一张图都在1M以上,重新租用云服务器用16GB的GPU训练,目前训练了16000步,未卡死,将同样的数据集,同样版本的程序放入Windows10运行,卡死,目前没有尝试过在Ubuntu上拿6GB内存的显卡跑过

万万没想到,会因为一个内存不够卡了我整整一个礼拜,没有报错的卡死真的让人崩溃

 

(5)关于mask_image全黑,而binary_image与instance_image分割效果还不错,此处“”binary_image分割效果还不错“”加引号
思路:应该是语义分割效果不错,而实例分割效果太差
做法:观察instance_image中几条车道线的是不是近似于一个颜色,有没有用不同颜色显示不同车道线(大概),如果有的话,就要首先回忆自己制作数据集的时候,是不是标注的line1,line2,line3.....而不是全部只标注了一种line,然后去回忆一下自己得训练过程,i_loss是不是很大(b_loss可能很小),前者是实例分割损失,后者是语义分割损失,如果是的话,证明实例分割那部分训练的确实不好,如果标注的没问题,就加强训练次数吧,我自己的测试结果是,i_loss大于4(我直接跑到了0.2)基本效果都很差,尽量加强次数吧,我翻看github讨论区,看到各位大神动辄几万十几万的训练次数

第N此回忆,跑到了0.2可以用,但是在我的数据集上通用性有点差,我又跑到了b_loss和i_loss均为0.0几这水平


关于i_loss居高不下,次数多了也不咋下降,在GitHub上原作者有回答,修改lanenet_model/lanenet_back_end.py中的
instance_segmentation_loss, l_var, l_dist, l_reg = \
                    lanenet_discriminative_loss.discriminative_loss(
                        pix_embedding, instance_label, self._embedding_dims,
                        pix_image_shape, 0.5, 3.0, 1.0, 1.0, 0.001
                    )
在line 162行
原参数为0.5, 3.0, 1.0, 1.0, 0.001
有人[非作者本人]修改为0.3, 2.0, 1.0, 1.0, 0.001
应根据自己跌数据集进行修改


还可以修改instance的学习率(增大分支学习率),据说需要修改代码,没研究过,有研究过的可爱们,欢迎补充


如果训练效果很nice,loss都很小,mask_image看着也不错,但是最后src_image线乱画,可能是后处理的DBSCAN聚类的参数不合适,把不同车道线聚到了一类,所以会有可能线乱了

(6)另附:如何在训练中断后接着训练(2020年11月1日提交版本)

代码中是这么写的:
if self._cfg.TRAIN.RESTORE_FROM_SNAPSHOT.ENABLE:
            try:
                LOG.info('=> Restoring weights from: {:s} ... '.format(self._initial_weight))
                self._loader.restore(self._sess, self._initial_weight)
                global_step_value = self._sess.run(self._global_step)
                remain_epoch_nums = self._train_epoch_nums - math.floor(global_step_value / self._steps_per_epoch)
                epoch_start_pt = self._train_epoch_nums - remain_epoch_nums

so:直接去修改config/tusimple_lanenet.yaml文件中的配置即可
RESTORE_FROM_SNAPSHOT:
        ENABLE: True
        SNAPSHOT_PATH: '/root/lanenet/final/tusimple_val_miou=0.6803.ckpt-2614'

 

水平太差,大佬请口下留情,勿喷!谢谢!

 

  • 20
    点赞
  • 140
    收藏
    觉得还不错? 一键收藏
  • 54
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值