# 本专栏内容基于清华大学出版社出版的《Python计算机视觉实战》学习笔记。

随着大数据及深度神经网络的不断发展,人们通过图像大数据和深度网络联合训练的方法使得目标检测算法不断优化,实现了多个场景下的落地与应用。目前主流的目标检测算法主要包括以RCNN为代表的Two-Stage算法及以YOLO为代表的One-Stage算法,通过对目标区域的回归计算进行目标定位。

1 RCNN

1.1算法概述

CNN算法是基于区域滑动+分类识别的流程,采用两步法进行目标定位。首先,对图像建立子区域搜索策略;其次,采用深度神经网络提取子区域的特征向量;然后,利用分类器判断目标类别,将所处区域的信息存储到该类别所对应的候选框列表中;最后,对得到的候选框列表进行非极大抑制分析,通过回归计算进行位置修正,输出目标位置。

1.区域搜索
对输人图像采用子区域搜索策略生成数千个候选框,将这些置,得到一系列子图

2.特征提取
遍历得到的子图列表,利用深度神经网络分别计算其特征向量,得到统一维度量集合。

3.分类判别
对应到目标类别建立多个SVM分类器,将特征向量集合分别调用SVM分类器进行分类判断,确定对应的子区域是否存在目标,进而得到候选框列表

4.位置修正
对候选框列表进行非极大抑制分析,并通过回归分析进行位置修正,输出目标位置。

RCNN系列融合了深度神经网络优秀的特征提取能力和分类器的判别能力,实现了端到端的目标检测框架,但整体上依然采用了“区域+检测”的二阶段过程,属于Two-Stage算法,难以达到对自标进行实时检测的要求。另外,以YOLO为代表的One-Stage算法不需要设置侯选区域,可直接输出定位结果。

1.2 RCNN的数据集实现

下面利用Python实现大数据集的训练。

①大训练集预训练

# 建立'AlexNet'网络
def create_alexnet(num_classes):
    network=input_data(shape=[None,config.IMAGE_SIZE,config.IMAGE_SIZE,3])
    # 四维输出张量,卷积核个数,卷积核尺寸,步长
    network=conv_2d(network,96,11,strides=4,activation='relu')
    network=max_pool_2d(network,3,strides=2)
    # 数据归一化
    network=local_response_normalization(network)
    network=conv_2d(network,256,5,activation='relu')
    network=max_pool_2d(network,3,strides=2)
    network=local_response_normalization(network)
    network=conv_2d(network,384,3,activation='relu')
    network=conv_2d(network,384,3,activation='relu')
    network=conv_2d(network,256,3,activation='relu')
    network=max_pool_2d(network,3,strides=2)
    network=local_response_normalization(network)
    network=fully_connected(network,4096,activation='tanh')
    network=dropout(network,0.5)
    network=fully_connected(network,4096,activation='tanh')
    network=dropout(network,0.5)
    network=fully_connected(network,num_classes,activation='softmax')
    nomentum=tflearn.Momentum(learning_rate=0.001,lr_decay=0.95,decay_step=200)
    network=regression(network,optimizer=momentum,loss='categorical_crossentropy')
    return network

"""定义alexnet网络,这里num_classes是大训练集对应的分类数量"""
def load_data(datafile,num_class,save=False,save_path='dataset.pkl'):
    fr=codece.open(datafile,'r','utf-9')
    train_list=fr.readlines()
    labels=[]
    images=[]
    # 对每一个训练样本
for line in train_list:
    tmp=line.strip().spilt('')
    fpath=tmp[0]
    img=cv2.imread(fpath)
    # 样本resize到227×227,转为矩阵保存
    img=prep.resize_image(img,config.IMAGE_SIZE,config.IMAGE_SIZE)
    np_img=np.asarray(img,dtype='float32')
    images.append(np_image)
    
    index=int(tmp[1])
    label=np.zeros(num_class)
    
    label[index]=1
    labels.append(label)
if save:
    # 序列化保存
    pickle.dump((images,labels),open(save_path,'wb'))
    fr.close()
    return images,labels

"""样本预处理,所有样本resize后转矩阵保存"""
def train(network,X,Y,save_model_path):
    # 训练
    model=tflearn.DNN(network,checkpoint_path='model_alexnet',max_checkpoints=1,tensorboard_verbose=2,tensorboard_dir='output')
    if os.path.isfile(save_model_path+'.index'):
        model.load(save_model_path)
        print('load model...')
        
        model.fit(X,Y,n_epoch=200,validation_set=0.1,shuffle=True,show_metric=True,batch_size=64,snapshot_step=200,snapshot_epoch=False,run_id='alexnet_oxflowers17')  # epoch=1000
        # 保存模型
        model.save(save_model_path)
        print('save model...')

 训练模型,X,Y为样本,迭代次数为200次,训练集中取出10%作为验证集(用来计算模型预测正确率),每次迭代训练64个样本。

②小数据集微调

#使用一个已经训练过的alexnet与最后一层重新设计
def create_alexnet(num_classes,restore=Falge):
    #创建'AlexNet'
    network=input_data(shape=[None,config.IMAGE.SIZE,config.IMAGE_SIZE,3])
    network=conv_2d(network,96,11,strides=4,activation='relu')
    network=max_pool_2d(network,3,strides=2)
    network=local_response_normalization(network)
    network=conv_2d(network,256,5,activation='relu')
    network=max_pool_2_d(network,3,strides=2)
    network==local_response_normalization(network)
    network=conv_2d(network,384,3,activation='relu')
    network=conv_2d(network,384,3,activation='relu')
    network=conv_2d(network,256,3,activation='relu')
    network=max_pool_2_d(network,3,strides=2)
    network==local_response_normalization(network)
    network=fully_connected(network,4096,activation='tanh')
    network=dropout(network,0.5)
    network=fully_connected(network,4096,activation='tanh')
    network=dropout(network,0.5)
    #不还原此层
    network=fully_connected(network,num_classes,activation='softmax',restore=restore)
    network=regression(network,optimizer='momentum',loss='categorical_crossentropy',learning_rate=0.001)
return network

"""定义新的alexnet,这里的num_classes改为小训练集的分类数量"""
def fine_tune_Alexnet(network,X,Y,save_model_path,fine_tune_model_path):
    # 训练
    model=tflearn.DNN(network,checkpoint_path='rcnn_model_alexnet',max_checkpoints=1,tensorboard_verbose=2,tensorboard_dir='output_RCNN')
    if os.path.isfile(fine_tune_model_path+'.index'):
        print("加载微调模型")
        model.load(fine_tune_model_path)
        # 加载预训练好的模型参数
    elif os.path.isfile(save_model_path+'.index'):
        print("加载alexnet")
        model.lload(save_model_path)
    else:
        print("没有文件加载,错误")
        return False 
    
    model.fit(X,Y,n_epoch=3,validation_set=0.1,shuffle=True,show_metric=True,batch_size=64,snapshot_step=200,snapshot_epoch=Fa1se,run_id='alexnet_rcnnflowers2')
    # 保存模型
    model.save(fine_tune_model_path)

先加载大数据集中预训练好的网络参数,再用小训练集的样本训练新的alexnet,进行数据微调。

③训练svm分类器和boundingbox回归

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐