windows10下实现endernewton版本Faster R-cnn+tensorflow+python3

前言

上一篇博文实现dBeker版本的代码,一天之内居然有三个人再看,开心得不得了!由于想用Resnet网路代替VGG16,但是dBeker版本的代码我没弄出来,问了几个小伙伴,还有看评论区里的也有同样想用renset替换VGG的。但是都没有成功,好像是这个版本的代码缺少Resnet的参数,由于本人也是刚入门,改代码对我还是比较困难的,(但是如果有大神做出来了请您私信给我,交流交流。)所以又找到了新的代码试一试。

本博文使用代码:https://github.com/endernewton/tf-faster-rcnn

目前都是用Linux系统跑这个代码的,由于自己的是windows,所以尝试跑了一下。顺便记录。

测试demo.py

准备

根据作者在github上给的Readme,一步一步进行下去:

1.下载github源码到电脑上。

2.编译Cython:在lib路径下,编译Cython模块(确保你已经安装了easydict,如果没有,pip install easydict):这部分我没有编译,不会,然后我就向下进行了,有会的朋友可以评论给大家看,谢谢

3.安装COCO API
给出github下载地址:https://github.com/cocodataset/cocoapi
把安装包下载下来,解压到data文件夹下,然后进入coco/PythonAPI下运行:

python setup.py build_ext --inplace
python setup.py build_ext install

4.下载PASCAL VOC数据集:这部分请详见我的上篇博文:https://blog.csdn.net/JJJKJJ/article/details/103141229

下载模型

1.本文使用的是的是resnet01模型,由于需要翻墙,这里给出百度云下载链接:https://blog.csdn.net/char_QwQ/article/details/80980505提取码:8ahl。
下载后解压到data文件夹下,并将文件夹重命名为 voc_2007_trainval ,文件结构如下:
在这里插入图片描述
其中imagenet_weights文件夹先不管。

2。在tf-faster-rcnn根目录创建一个\output\res101\voc_2007_trainval\default文件夹并且在其中存放预训练模型,也就是将刚才下载好的resnet模型复制到或者移动到default文件夹中。

测试

运行demo.py之前,首先修改几处代码

1.def parse_args():中的default='pascal_voc_0712’修改为pascal_voc

2.if name == ‘main’:中tfmodel = os.path.join(‘output’, demonet, DATASETS[dataset][0], ‘default’,NETS[demonet][0])的output,修改为绝对路径,我的是’D:/1Aqilei—npupt/tf-faster-rcnn-master/output’。

3.tf-faster-rcnn/lib/datasets/voc_eval.py的第121行的
with open(cachefile,‘w’) as f修改为:with open(cachefile,‘wb’) as f
同时还要把第105行的 cachefile = os.path.join(cachedir, ‘%s_annots.pkl’ % imagesetfile)
改成:cachefile = os.path.join(cachedir, ‘%s_annots.pkl’ % imagesetfile.split("/")[-1].split(".")[0])

4.修改lib.model.nms_wrapper.py全部修改:

# --------------------------------------------------------
# Fast R-CNN
# Copyright (c) 2015 Microsoft
# Licensed under The MIT License [see LICENSE for details]
# Written by Ross Girshick
# --------------------------------------------------------
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

from nms.py_cpu_nms import py_cpu_nms

def nms(dets, thresh, force_cpu=False):
    """Dispatch to either CPU or GPU NMS implementations."""

    if dets.shape[0] == 0:
        return []
    # if cfg.USE_GPU_NMS and not force_cpu:
    #  return gpu_nms(dets, thresh, device_id=cfg.GPU_ID)
    # else:
    # return cpu_nms(dets, thresh)
    return py_cpu_nms(dets=dets, thresh=thresh)

5.可能会出现No module named ‘lib.utils.Cython_bbox’的错误,这个错误的主要原因是,目前网上流行的Faster RCNN版本大多都是基于Py35的。当你使用Py36的环境去编译,那么就会出现这个问题。解决方法:https://pan.baidu.com/s/1-M2_Uic8n6Ac0M-DqH5-9Q
提取码:p1we.
将下载的文件放到lib\utils\文件夹下。问题解决

6.执行 demo.py,大功告成

7.有问题欢迎评论区评论,努力为大家解答

训练自己的数据集

注:此部分相关内容可参看https://blog.csdn.net/JJJKJJ/article/details/103141229
1.首先删除data/VOCdevkit2007/VOC2007/JPEGImages文件夹下的图片数据,换成自己的实验数据 --finish
这一步骤我将图片尺寸调整为900,600。同时rename。
2.删除data/VOCdevkit2007/VOC2007/Annotations文件夹下的xml文件,等待放入自己数据对应的xml文件 --finish
3.打开labelImg,对自己实验数据进行标注,点击change save dir改变xml文件的保存路径,一般保存在data\VOCdevkit2007\VOC2007\Annotations文件夹下 --finish
4.由于数据集数据有限,所以进行数据增强,通过上下镜像与左右镜像,增加自己的数据集。
附上代码:

上下镜像


'''
上下镜像
'''
import cv2
from PIL import Image
import xml.etree.ElementTree as ET
from tqdm import tqdm
import os
from PIL import Image



def flip_horizontal(jpg_file,new_jpg):
    im = Image.open(jpg_file)
    # out = im.transpose(Image.ROTATE_180)
    out = im.transpose(Image.FLIP_TOP_BOTTOM)
    out.save(new_jpg)

def flip_xml(xml_file,new_xml,height):
    tree = ET.parse(xml_file)
    objs = tree.findall('object')
    for ix, obj in enumerate(objs):
        name = obj.find('name').text
        #if name == 'mouse':
        #print(xml_file)
        obj_new = obj.find('bndbox')
        ymin = str( height - int(obj_new.find('ymax').text))#此2行保证翻转后ymin<ymax
        ymax = str( height - int(obj_new.find('ymin').text))
        obj_new.find('ymin').text = ymin
        obj_new.find('ymax').text = ymax
        tree.write(new_xml)


if __name__ == '__main__':
    # path = r'E:\VOC2007\Annotations'
    path = r'D:\1Aqilei---npupt\tf-faster-rcnn-master\data\VOCdevkit2007\VOC2007\Annotations'
    xml_files = [os.path.join(rootdir, file) for rootdir, _, files in os.walk(path) for file in files if
                 (file.endswith('.xml'))]
    print(xml_files)
    jpg_files = [xmlfile.replace('Annotations', 'JPEGImages').replace('xml', 'jpg') for xmlfile in xml_files]
    #jpg_files =[xmlfile.replace('xml','jpg') for xmlfile in xml_files]
    #print(jpg_files)
    # jpg_old_files = jpg_files
    files = zip(jpg_files,xml_files)
    #print(files)
    for jpg_file,xml_file in tqdm(files):
        #print(jpg_file)
        im = Image.open(jpg_file)
        height = im.size[1]
        # print(width)
        new_jpg = jpg_file.replace(jpg_file.split('\\')[-1].split('.')[0],jpg_file.split('\\')[-1].split('.')[0] + '_buttom')
        #print(new_jpg)
        # break
        new_xml = new_jpg.replace('JPEGImages', 'Annotations').replace('jpg', 'xml')
        # print(new_xml)
        flip_xml(xml_file,new_xml,height)
        flip_horizontal(jpg_file, new_jpg)

左右镜像

'''
左右镜像
'''
import cv2
from PIL import Image
import xml.etree.ElementTree as ET
from tqdm import tqdm
import os
from PIL import Image


def flip_horizontal(jpg_file,new_jpg):
    im = Image.open(jpg_file)
    # out = im.transpose(Image.ROTATE_180)
    out = im.transpose(Image.FLIP_LEFT_RIGHT)
    out.save(new_jpg)

def flip_xml(xml_file,new_xml,width):
    tree = ET.parse(xml_file)
    objs = tree.findall('object')
    for ix, obj in enumerate(objs):
        name = obj.find('name').text
        #if name == 'mouse':
        #print(xml_file)
        obj_new = obj.find('bndbox')
        xmin = str( width - int(obj_new.find('xmax').text))#此2行保证翻转后xmin<xmax
        xmax = str( width - int(obj_new.find('xmin').text))
        obj_new.find('xmin').text = xmin
        obj_new.find('xmax').text = xmax
        tree.write(new_xml)


if __name__ == '__main__':
    # path = r'E:\数据集\VOC2007\Annotations'
    path = r'D:\1Aqilei---npupt\tf-faster-rcnn-master\data\VOCdevkit2007\VOC2007\Annotations'
    xml_files = [os.path.join(rootdir, file) for rootdir, _, files in os.walk(path) for file in files if
                 (file.endswith('.xml'))]
    print(xml_files)
    jpg_files = [xmlfile.replace('Annotations', 'JPEGImages').replace('xml', 'jpg') for xmlfile in xml_files]
    #jpg_files =[xmlfile.replace('xml','jpg') for xmlfile in xml_files]
    #print(jpg_files)
    # jpg_old_files = jpg_files
    files = zip(jpg_files,xml_files)
    #print(files)
    for jpg_file,xml_file in tqdm(files):
        #print(jpg_file)
        im = Image.open(jpg_file)
        width = im.size[0]
        # print(width)
        new_jpg = jpg_file.replace(jpg_file.split('\\')[-1].split('.')[0],jpg_file.split('\\')[-1].split('.')[0] + '_filp')
        #print(new_jpg)
        # break
        new_xml = new_jpg.replace('JPEGImages', 'Annotations').replace('jpg', 'xml')
        # print(new_xml)
        flip_xml(xml_file,new_xml,width)
        flip_horizontal(jpg_file, new_jpg)

以上两个代码只需要改变路径就可以用了,数据增强完毕,翻了四倍。

5.生成4个txt文件

6.修改代码

6.1修改trainval_net.py

def parse_args():
  """
  Parse input arguments
  """
  parser = argparse.ArgumentParser(description='Train a Fast R-CNN network')
  parser.add_argument('--cfg', dest='cfg_file',
                      help='optional config file',
                      default="../experiments/cfgs/res101.yml",type=str)
  parser.add_argument('--weight', dest='weight',
                      help='initialize with pretrained model weights',
                      type=str,default="../data/imagenet_weights/res101.ckpt")
  parser.add_argument('--imdb', dest='imdb_name',
                      help='dataset to train on',
                      default='voc_2007_trainval', type=str)
  parser.add_argument('--imdbval', dest='imdbval_name',
                      help='dataset to validate on',
                      default='voc_2007_test', type=str)
  parser.add_argument('--iters', dest='max_iters',
                      help='number of iterations to train',
                      default=70000, type=int)
  parser.add_argument('--tag', dest='tag',
                      help='tag of the model',
                      default=None, type=str)
  parser.add_argument('--net', dest='net',
                      help='vgg16, res50, res101, res152, mobile',
                      default='res101', type=str)
  parser.add_argument('--set', dest='set_cfgs',
                      help='set config keys', default=None,
                      nargs=argparse.REMAINDER)

  # if len(sys.argv) == 1:
  #   parser.print_help()
  #   sys.exit(1)

  args = parser.parse_args()
  return args

6.2 修改lib/datasets/pascal_voc.py
第36行的classe修改成自己的类别,background不可以删除

6.3修改lib/datasets/imdb.py
第25行_num_classes=? ,?换成你自己的类+1,比如香蕉,橘子,苹果三类,这里_num_classes就要等于3+1=4

7.执行trainval_net.py
训练的模型保存在out文件夹下

训练过程中遇到的问题(及针对自己的数据集的解决方法)

RuntimeWarning: invalid value encountered in log targets_dw = np.log(gt_widths / ex_widths) total loss=Nan

1.减小学习率 亲测不好用
2.这种报错说明数据集的数据有一些问题,多出现在没有控制好边界的情况,首先,打开lib/database/pascal_voc.py文件,找到208行,将208行至211行每一行后面的-1删除,如下所示:
x1 = float(bbox.find(‘xmin’).text)
y1 = float(bbox.find(‘ymin’).text)
x2 = float(bbox.find(‘xmax’).text)
y2 = float(bbox.find(‘ymax’).text)
原因是因为我们制作的xml文件中有些框的坐标是从左上角开始的,也就是(0,0)如果再减一就会出现log(-1)的情况
如果这样之后还是出现类似的报错,那么说明依然有-1或者其他负数的情况出现。解决方法是打开./lib/model/config.py文件,找到flipp选项,将其置为False
__C.TRAIN.USE_FLIPPED = False
如果这样以后还是报类似的错误,就一定检查一下自己制作数据集的过程,看看是否哪里没有考虑清楚。
亲测不好用!
3.打开

  • 8
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 31
    评论
评论 31
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值