keras yolo3训练技巧以及踩过的坑

  我是在windows下安装的,虽然不推荐,但是没有机器装linux,windows用起来还是挺方便。但如果在windows下编译TensorFlow的源代码就很麻烦。下面把我遇到的各种问题和技巧与大家分享。

  • windows环境下各软件版本的问题

    具体的安装步骤就不说了,网上乱七八糟的很多,关键是TensorFlow和CUDA的要匹配,否则使用GPU就会出现各种问题
    
    Keras           2.2.4
    tensorflow      1.12.0(目前最新稳定版)
    tensorflow-gpu  1.12.0(目前最新稳定版)
    CUDA            9.0
    

  • 标注软件的问题

  推荐微软开发的VoTT,可以从官方下载https://github.com/Microsoft/VoTT/releases,使用很简单,这里就不多说
  其他的我用过2个,感觉都没有这个方便,毕竟标注是一件很花时间的体力活,如果工具顺手会节约你很多时间
  
  keras-yolo3自带了一个voc_annotation.py,可以吧voc格式转化成keras-yolo3自己的格式,刚开始我也用voc,但是非常繁琐。
  VoTT可以把数据导出为voc格式,但没有测试成功
  最后发现有个小程序,可以吧VoTT做成的json直接转换成,keras-yolo3格式,不再需要voc_annotation.py,非常方便,代码如下
  
  convert_vott_to_kerasyolo3txt.py

import json
import os


def convert_vott_to_kerasyolo3txt(json_path, image_dir, train_txt_save_path, classes_txt_save_path):

    row_list = []

    with open(json_path) as f:
        dic = json.load(f)
        tag_set = set()

        visited_frames = dic['visitedFrames']

        frames = dic['frames']
        frame_keys = frames.keys()

        for visited in visited_frames:
            if visited in frame_keys:
                img_annotation_list = frames[visited]
                for item in img_annotation_list:
                    tags = item['tags']
                    for t in tags:
                        tag_set.add(t)

        tag_dic = {}
        tag_list = list(tag_set)
        tag_list.sort()
        for i, tag in enumerate(tag_list):
            tag_dic[tag] = i

        for visited in visited_frames:
            if visited in frame_keys:
                img_annotation_list = frames[visited]

                row_text = os.path.join(image_dir, visited)

                for item in img_annotation_list:
                    box = item['box']
                    tags = item['tags']

                    for tag in tags:
                        row_text = row_text + ' {},{},{},{},{}'.format(int(box['x1']),int(box['y1']),int(box['x2']),int(box['y2']), int(tag_dic[tag]))

                if len(img_annotation_list) != 0:
                    row_list.append(row_text)

    train_txt = '\n'.join(row_list)

    print(train_txt)

    f = open(train_txt_save_path, 'w')
    f.write(train_txt)
    f.close()

    classes_txt = '\n'.join(tag_list)

    f = open(classes_txt_save_path, 'w')
    f.write(classes_txt)
    f.close()


def _main():
    json_path = 'C:\\Users\\xxx\\Pictures\\resize_images.json'  # VoTT生成的json
    image_dir = 'C:\\Users\\xxx\\Pictures\\resize_images\\'  # 图片路径
    train_txt_save_path = 'my_train.txt'  # keras-yolo3格式标注
    classes_txt_save_path = 'model_data/my_classes.txt' # keras-yolo3的分类

    convert_vott_to_kerasyolo3txt(
        json_path=json_path,
        image_dir=image_dir,
        train_txt_save_path=train_txt_save_path,
        classes_txt_save_path=classes_txt_save_path
    )

if __name__ == '__main__':
    _main()

记得修改里面的路径,然后运行

python convert_vott_to_kerasyolo3txt.py

就会得到keras-yolo3格式的标注和分类,有了这个就可以训练了

  • 训练图片的大小的问题

keras-yolo3默认大小是416*416,如果在标注前不统一为416,会引起检测精度下降,还有检测到的区域变形

keras yolo3训练技巧以及踩过的坑

我们需要把图片转换成上面的格式,可以使用下面的小程序来转换

resize.py

import os
from glob import glob

from PIL import Image
from yolo3.utils import letterbox_image

def resize_images(images_dir, image_save_dir, image_size):

    os.makedirs(image_save_dir, exist_ok=True)

    image_paths = glob(os.path.join(images_dir, '*'))

    for img_path in image_paths:
        image = Image.open(img_path)
        image = image.convert('RGB')

        resize_image = letterbox_image(image, (416, 416))
        save_path = os.path.join(image_save_dir, os.path.basename(img_path))
        resize_image.save(save_path)

	
def _main():
    images_dir = 'C:\\Users\\xxx\\Pictures\\images\\'  # 需要修改
    image_save_dir = 'C:\\Users\\xxx\\Pictures\\resize_images\\'  # 需要修改
    image_size = 416 

    resize_images(images_dir=images_dir, image_save_dir=image_save_dir, image_size=image_size)


if __name__ == '__main__':
    _main()

运行就可以得到转换后的图片

python resize.py

  • 显卡内存不足的问题

我使用的gpu是gtx1050,只有2G内存,如果使用GPU来训练就会出现OOM(out of memory)错误,即使修改batch_size为1也不行。估计最低需要4G内存,如果有8G以上更好。

我们训练的时候需要禁止GPU,下面的代码加到train.py的头部就能禁止GPU

import os
os.environ['CUDA_VISIBLE_DEVICES'] = '-1'

在识别的时候占用内存不大,可以使用GPU来加速