物体检测-Faster R-CNN(1)
物体检测-Faster R-CNN
物体检测是计算机视觉中的一个重要的研究领域,在人流检测,行人跟踪,自动驾驶,医学影像等领域有着广泛的应用。不同于简单的图像分类,物体检测旨在对图像中的目标进行精确识别,包括物体的位置和分类,因此能够应用于更多高层视觉处理的场景。例如在自动驾驶领域,需要辨识摄像头拍摄的图像中的车辆、行人、交通指示牌及其位置,以便进一步根据这些数据决定驾驶策略。上一期学习案例中,我们聚焦于YOLO算法,YOLO(You Only Look Once)是一种one-stage物体检测算法,在本期案例中,我们介绍一种two-stage算法——Faster R-CNN,将目标区域检测和类别识别分为两个任务进行物体检测。
进入环境
进入ModelArts
点击如下链接:https://www.huaweicloud.com/product/modelarts.html , 进入ModelArts主页。点击“立即使用”按钮,输入用户名和密码登录,进入ModelArts使用页面
创建ModelArts notebook
下面,我们在ModelArts中创建一个notebook开发环境,ModelArts notebook提供网页版的Python开发环境,可以方便的编写、运行代码,并查看运行结果。
第一步:在ModelArts服务主界面依次点击“开发环境”、“创建”
第二步:填写notebook所需的参数:
项目 | 建议填写方式 |
---|---|
名称 | 自定义环境名称 |
工作环境 | Python3 |
资源池 | 选择\"公共资源池\"即可 |
类型 | GPU |
规格 | [限时免费]体验规格GPU版 |
存储配置 | EVS |
磁盘规格 | 5GB |
第三步:配置好notebook参数后,点击下一步,进入notebook信息预览。确认无误后,点击“立即创建“
第四步:创建完成后,返回开发环境主界面,等待Notebook创建完毕后,打开Notebook,进行下一步操作
在ModelArts中创建开发环境
接下来,我们创建一个实际的开发环境,用于后续的实验步骤。
第一步:点击下图所示的“打开”按钮,进入刚刚创建的Notebook,
第二步:创建一个Python3环境的的Notebook。点击右上角的\"New\",然后选择Pytorch-1.0.0开发环境。
第三步:点击左上方的文件名\"Untitled\",并输入一个与本实验相关的名称,
在Notebook中编写并执行代码
在Notebook中,我们输入一个简单的打印语句,然后点击上方的运行按钮,可以查看语句执行的结果:",
开发环境准备好啦,接下来可以愉快地写代码啦!"
import os
from modelarts.session import Session
sess = Session()
if sess.region_name == 'cn-north-1':
bucket_path="modelarts-labs/notebook/DL_object_detection_faster/fasterrcnn.tar.gz"
elif sess.region_name == 'cn-north-4':
bucket_path="modelarts-labs-bj4/notebook/DL_object_detection_faster/fasterrcnn.tar.gz"
else:
print("请更换地区到北京一或北京四")
if not os.path.exists('./experiments'):
sess.download_data(bucket_path=bucket_path, path="./fasterrcnn.tar.gz")
if os.path.exists('./fasterrcnn.tar.gz'):
# 解压压缩包
os.system("tar -xf ./fasterrcnn.tar.gz")
# 清理压缩包
os.system("rm -r ./fasterrcnn.tar.gz")
!pip install pycocotools==2.0.0
!pip install torchvision==0.4.0
!pip install protobuf==3.9.0
import tools._init_paths
%matplotlib inline
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
import tensorboardX as tb
from datasets.factory import get_imdb
from model.train_val import get_training_roidb, train_net
from model.config import cfg, cfg_from_file, cfg_from_list, get_output_dir, get_output_tb_dir
import roi_data_layer.roidb as rdl_roidb
from roi_data_layer.layer import RoIDataLayer
import utils.timer
import pickle
import torch
import torch.optim as optim
from nets.vgg16 import vgg16
import numpy as np
import os
import sys
import glob
import time
imdb_name = "voc_2007_trainval"
imdbval_name = "voc_2007_test"
# 使用的预训练模型位置
weight = "./data/imagenet_weights/vgg16.pth"
# 训练迭代次数
max_iters = 100
# cfg模型文件位置
cfg_file = './experiments/cfgs/vgg16.yml'
set_cfgs = None
if cfg_file is not None:
cfg_from_file(cfg_file)
if set_cfgs is not None:
cfg_from_list(set_cfgs)
print('Using config:')
print(cfg)
def combined_roidb(imdb_names):
def get_roidb(imdb_name):
# 加载数据集
imdb = get_imdb(imdb_name)
print('Loaded dataset `{:s}` for training'.format(imdb.name))
# 使用ground truth作为数据集策略
imdb.set_proposal_method(cfg.TRAIN.PROPOSAL_METHOD)
print('Set proposal method: {:s}'.format(cfg.TRAIN.PROPOSAL_METHOD))
roidb = get_training_roidb(imdb)
return roidb
roidbs = [get_roidb(s) for s in imdb_names.split('+')]
roidb = roidbs[0]
if len(roidbs) > 1:
for r in roidbs[1:]:
roidb.extend(r)
tmp = get_imdb(imdb_names.split('+')[1])
imdb = datasets.imdb.imdb(imdb_names, tmp.classes)
else:
imdb = get_imdb(imdb_names)
return imdb, roidb
np.random.seed(cfg.RNG_SEED)
# 加载训练数据集
imdb, roidb = combined_roidb(imdb_name)
print('{:d} roidb entries'.format(len(roidb)))
# 设置输出路径
output_dir = get_output_dir(imdb,None)
print('Output will be saved to `{:s}`'.format(output_dir))
# 设置日志保存路径
tb_dir = get_output_tb_dir(imdb, None)
print('TensorFlow summaries will be saved to `{:s}`'.format(tb_dir))
# 加载验证数据集
orgflip = cfg.TRAIN.USE_FLIPPED
cfg.TRAIN.USE_FLIPPED = False
_, valroidb = combined_roidb(imdbval_name)
print('{:d} validation roidb entries'.format(len(valroidb)))
cfg.TRAIN.USE_FLIPPED = orgflip
# 创建backbone网络
# 在案例中使用的是VGG16模型,可以尝试其他不同的模型结构,例如Resnet等
net = vgg16()
from model.train_val import filter_roidb, SolverWrapper
# 对ROI进行筛选,将无效的ROI数据筛选掉
roidb = filter_roidb(roidb)
valroidb = filter_roidb(valroidb)
sw = SolverWrapper(
net,
imdb,
roidb,
valroidb,
output_dir,
tb_dir,
pretrained_model=weight)
print('Solving...')
# 显示所有模型属性
sw.__dict__.keys()
# sw.net为主干网络
print(sw.net)
# 构建网络结构,模型加入ROI数据层
sw.data_layer = RoIDataLayer(sw.roidb, sw.imdb.num_classes)
sw.data_layer_val = RoIDataLayer(sw.valroidb, sw.imdb.num_classes, random=True)
# 构建网络结构,在VGG16基础上加入ROI和Classifier部分
lr, train_op = sw.construct_graph()
# 加载之前的snapshot
lsf, nfiles, sfiles = sw.find_previous()
# snapshot 为训练提供了断点训练,如果有snapshot将加载进来,继续训练
if lsf == 0:
lr, last_snapshot_iter, stepsizes, np_paths, ss_paths = sw.initialize()
else:
lr, last_snapshot_iter, stepsizes, np_paths, ss_paths = sw.restore(str(sfiles[-1]), str(nfiles[-1]))
iter = last_snapshot_iter + 1
last_summary_time = time.time()
# 在之前的训练基础上继续进行训练
stepsizes.append(max_iters)
stepsizes.reverse()
next_stepsize = stepsizes.pop()
# 将net切换成训练模式
print("网络结构:")
sw.net.train()
sw.net.to(sw.net._device)
while iter < max_iters + 1:
if iter == next_stepsize + 1:
# 加入snapshot节点
sw.snapshot(iter)
lr *= cfg.TRAIN.GAMMA
scale_lr(sw.optimizer, cfg.TRAIN.GAMMA)
next_stepsize = stepsizes.pop()
utils.timer.timer.tic()
# 数据通过ROI数据层,进行前向计算
blobs = sw.data_layer.forward()
now = time.time()
if iter == 1 or now - last_summary_time > cfg.TRAIN.SUMMARY_INTERVAL:
# 计算loss函数
# 根据loss函数对模型进行训练
rpn_loss_cls, rpn_loss_box, loss_cls, loss_box, total_loss, summary = \
sw.net.train_step_with_summary(blobs, sw.optimizer)
for _sum in summary:
sw.writer.add_summary(_sum, float(iter))
# 进行数据层验证计算
blobs_val = sw.data_layer_val.forward()
summary_val = sw.net.get_summary(blobs_val)
for _sum in summary_val:
sw.valwriter.add_summary(_sum, float(iter))
last_summary_time = now
else:
rpn_loss_cls, rpn_loss_box, loss_cls, loss_box, total_loss = \
sw.net.train_step(blobs, sw.optimizer)
utils.timer.timer.toc()
if iter % (cfg.TRAIN.DISPLAY) == 0:
print('iter: %d / %d, total loss: %.6f\n >>> rpn_loss_cls: %.6f\n '
'>>> rpn_loss_box: %.6f\n >>> loss_cls: %.6f\n >>> loss_box: %.6f\n >>> lr: %f' % \
(iter, max_iters, total_loss, rpn_loss_cls, rpn_loss_box, loss_cls, loss_box, lr))
print('speed: {:.3f}s / iter'.format(
utils.timer.timer.average_time()))
# 进行snapshot存储
if iter % cfg.TRAIN.SNAPSHOT_ITERS == 0:
last_snapshot_iter = iter
ss_path, np_path = sw.snapshot(iter)
np_paths.append(np_path)
ss_paths.append(ss_path)
# 删掉多余的snapshot
if len(np_paths) > cfg.TRAIN.SNAPSHOT_KEPT:
sw.remove_snapshot(np_paths, ss_paths)
iter += 1
if last_snapshot_iter != iter - 1:
sw.snapshot(iter - 1)
sw.writer.close()
sw.valwriter.close()
- 点赞
- 收藏
- 关注作者
评论(0)