『Caffe』图像检测程序(待续)

和图像分类不同,图像检测涉及更多的技术基础,本程序是基于传统的滑窗模式完成检测,当下已经有了最新的基于caffe的RCNN、Fast-RCNN、Faster-RCNN以及SSD框架 ,个中思路不同,不得叹惋前路漫漫。由于接触本部时走了很多弯路,所以给出几个关键词用于学习滑窗检测理论基础学习:overfeat;全卷积网络;图像金字塔;非极大值抑制,当然了,传统的卷积分类网络也要了解。

程序调用逻辑图如下:

库导入以及参数设置部分:

 1 # coding=utf-8
 2 import numpy as np
 3 import sys
 4 import os
 5 import math
 6 sys.path.append(‘/usr/local/lib/python2.7/dist-packages‘)    # 实验室服务器包安装紊乱,cv2库的位置
 7 sys.path.append(‘/home/caf/zm/caffe/python‘)                 # caffe库的位置
 8 import cv2
 9 import caffe
10 caffe.set_device(0)
11 caffe.set_mode_gpu()
12
13
14 box_stride      = 32        # 感受野大小
15 threshold_value = 0.95      # 初始化框阈值
16 input_size      = 227       # 训练图片尺寸
17 mean_file       = ‘/home/caf/zm/caffe/python/caffe/imagenet/ilsvrc_2012_mean.npy‘   # 均值文件(这里是caffe自带的)
18 image_path      = ‘./120.1 +1.4.jpg‘                                                # 待检测图片                                                              # 训练图片尺寸
19 # 注意,训练网络、分类网络、检测网络是三个不同的网络,详情自行查阅文献
20 model_def       = ‘./deploy_full_conv.prototxt‘                                     # 检测用全卷积网络
21 model_weights   = ‘./_iter_20000.caffemodel‘                                        # 训练好的模型

注:没什么好说的,input_size和之前不同不分长宽,没什么原因纯粹因为改起来好麻烦,所以训练的时候要统一宽高尺寸,或者愿意来改这个程序

程序入口和face_detection()函数(程序主干):

 1 def face_detection(imgFile):
 2
 3     # 加载网络和参数
 4     net_full_conv = caffe.Net(model_def,
 5                               model_weights,
 6                               caffe.TEST)              # 全卷积网络(导入训练好的模型和deploy配置文件)
 7                                                        # 用caffe的测试模式,即只是提取特征,不训练
 8
 9     img = cv2.imread(imgFile)                          # 读入测试图像
10     print img.shape                                    # 测试图像尺寸
11
12     # 生成图像金字塔
13     scales = []                                        # 存储scale的容器,组成图像金字塔
14     factor = 0.793700526                               # 图像放大或者缩小的一个因子(经验值)
15     largest = min(2, 4000/max(img.shape[0:2]))
16     scale = largest                                    # 初始化scale(最大放缩比)
17     minD = largest*min(img.shape[0:2])
18     while minD >= input_size:                          # 保证输入尺寸不小于训练尺寸
19         scales.append(scale)
20         scale *= factor
21         minD *= factor
22
23     total_boxes = []                                   # 存储候选框的容器
24
25     for scale in scales:
26         # 使用cv2库整形为金字塔的尺寸并存储
27         scale_img = cv2.resize(img,((int(img.shape[0] * scale), int(img.shape[1] * scale))))
28         cv2.imwrite(‘./scale_img.jpg‘,scale_img)
29
30         # caffe载入整形好的图片
31         im = caffe.io.load_image(‘./scale_img.jpg‘)
32         # 将data接收数据格式改为适应图片(全卷积网络不限制输入图片尺寸)
33         net_full_conv.blobs[‘data‘].reshape(1,3,scale_img.shape[1],scale_img.shape[0])
34
35         # 预处理部分,同分类网络
36         # 用转换函数Transformer函数使transformer得到data层的数据格式
37         transformer = caffe.io.Transformer({‘data‘: net_full_conv.blobs[‘data‘].data.shape})
38         transformer.set_mean(‘data‘, np.load(mean_file).mean(1).mean(1))
39         transformer.set_transpose(‘data‘, (2,0,1))
40         transformer.set_channel_swap(‘data‘, (2,1,0))
41         transformer.set_raw_scale(‘data‘, 255.0)
42
43         # 进行一次前向传播
44         out = net_full_conv.forward_all(data=np.asarray([transformer.preprocess(‘data‘, im)]))
45             # 这里介绍一下forward_all的输出,打印print out[‘prob‘].shape会反回[1,2,n,n],
46             # 表示一个含有两张featuremap的n*n输出,而2的原因是因为这是个二分类网络,是对应概率的.
47             # out[‘prob‘].[0,1]表示取第二张featuremap.
48             # [0,1]表示是的featuremap,[0,0]表示非的featuremap
49             # 以2*2(n=2)为例,featuremap上的每个数字表示原图相应位置的概率
50
51         # 将featuremap的box还原为图片上的box
52         boxes = generateBoundingBox(out[‘prob‘][0,1], scale)
53
54         # 存储图片上的box
55         if(boxes):
56             total_boxes.extend(boxes)
57
58     print total_boxes
59     boxes_nms = np.array(total_boxes)
60
61     # 合并图片上的box
62     # 利用非极大值算法过滤出人脸概率最大的框,并对结果进行合并处理
63     true_boxes = nms_average(boxes_nms, 2, 0.2)
64
65     if not true_boxes == []:
66         # 提取坐标剔除得分
67         (x1, y1, x2, y2) = true_boxes[0][:-1]
68         # 画框
69         cv2.rectangle(img, (int(x1),int(y1)), (int(x2),int(y2)), (0,255,0),thickness=2)
70         # 展示
71         cv2.imshow(‘test win‘, img)
72         # 存储
73         cv2.imwrite(‘./result.jpg‘,img)
74         # 等待键盘指令(没啥大用)
75         cv2.waitKey(1)
76
77 if __name__ == "__main__":
78
79     face_detection(image_path)

注:本部分通过对各个分部的调用实现了程序的主要功能,直接涉及到的模块是图像金字塔的生成和使用。值得一提的是net_full_conv.forward_all()的输出,直接把(1,2,n,n)的featuremaps输出了,正好和之前在论文里看到的全卷积神经网络原理对应上了,这里提取了代表label’是‘的那一层featuremap进行后续处理。

接受主函数中的featuremap并还原生成候选框的程序:

 1 def generateBoundingBox(featureMap, scale):
 2     ‘‘‘
 3     还原候选框
 4     :param featureMap:    m*n的矩阵
 5     :param scale:         放缩参数,前面转换时乘了上来,这里要除回去
 6     :return:              {y1,x1,y2,x2,prob}
 7     ‘‘‘
 8     boundingBox = []                                          # 用于存储候选框
 9     stride = box_stride                                       # 感受野大小
10     cellSize = input_size                                     # 框的尺寸
11     for (x,y), prob in np.ndenumerate(featureMap):            # np的(index,value)迭代器
12         if(prob >= threshold_value):                                     # 判断概率阙值
13             # print prob
14             boundingBox.append([float(stride * y)/scale,                   # 还原对角线上点坐标
15                                 float(stride * x)/scale,
16                                 float(stride * y + cellSize - 1)/scale,    # 还原对角线下点坐标
17                                 float(stride * x + cellSize - 1)/scale,
18                                 prob])                                     # 存储概率值
19     #sort by prob, from max to min.
20     #boxes = np.array(boundingBox)
21     return boundingBox

注:本部分把featuremap像素还原为原图上的候选框,原图指的是非金字塔放缩的原图。

其中np.ndenumerate()是类比原生python中enumerate()的函数,用法如下(pycharm下ipython拷贝代码真方便,推荐):

 1 import numpy as np
 2 feature = np.arange(4).reshape(2,2)
 3 feature
 4 # Out[4]:
 5 # array([[0, 1],
 6 #        [2, 3]])
 7 for (x,y), prob in np.ndenumerate(feature):
 8     print(x,y,prob)
 9 # (0, 0, 0)
10 # (0, 1, 1)
11 # (1, 0, 2)
12 # (1, 1, 3)

接受上部分还原出的大量候选框进行合并策略的程序:

 1 def nms_average(boxes, groupThresh=2, overlapThresh=0.2):
 2     ‘‘‘
 3
 4     :param boxes:          多个矩形框组成的向量 [left, bottom, right, top, prob]
 5     :param groupThresh:    合并阙值,n张以上才能合并,否则放弃
 6     :param overlapThresh:  相关性阙值
 7     :return:               [left, bottom, right, top, 1]
 8     ‘‘‘
 9     # boxes{x1,y1,x2,y2,prob}
10     # rects{x,y,w,h}
11     rects = []
12     for i in range(len(boxes)):
13         # if boxes[i][4] > 0.2:     # 概率大于20%才录入,由于前面已经处理过了,所以没用
14         rects.append([boxes[i,0], boxes[i,1], boxes[i,2]-boxes[i,0], boxes[i,3]-boxes[i,1]])
15     # 合并矩形框,非极大值一致
16     # 重叠率过大的框只保留最大概率的那张
17     # cv2的合并框函数,返回的rects和输入的名称相同,最少有groupThresh个框才合并,overlapThresh是是否合并的计算参数(相关关系参数)
18     rects, weights = cv2.groupRectangles(rects, groupThresh, overlapThresh)
19     rectangles = []
20     for i in range(len(rects)):
21         testRect = Rect( Point(rects[i,0], rects[i,1]), Point(rects[i,0]+rects[i,2], rects[i,1]+rects[i,3]))
22         rectangles.append(testRect)
23     # clusters{x1,y1,x2,y2}  集合
24     # cluster{x1,y1,x2,y2}   属于Reck类
25     # rect{x1,y1,x2,y2}      属于Reck类
26     clusters = []
27     for rect in rectangles:
28         matched = 0
29         for cluster in clusters:
30             # 重叠率达到20%就进行合并
31             if (rect_merge( rect, cluster , 0.2) ):
32                 matched=1
33                 cluster.left   =  (cluster.left + rect.left   )/2
34                 cluster.right  = ( cluster.right+  rect.right  )/2
35                 cluster.top    = ( cluster.top+    rect.top    )/2
36                 cluster.bottom = ( cluster.bottom+ rect.bottom )/2
37         # 新框和所有cluster重叠率都不到20%就直接添加为新的cluster
38         if ( not matched ):
39             clusters.append( rect )
40     result_boxes = []
41     for i in range(len(clusters)):
42         result_boxes.append([clusters[i].left, clusters[i].bottom, clusters[i].right, clusters[i].top, 1])
43     return result_boxes
时间: 2024-10-11 17:51:27

『Caffe』图像检测程序(待续)的相关文章

『cs231n』图像定位与检测(下,待续)

图像检测原理 定义: 给出一张图片和几个类别,定位出图片中这些类所有的实例. 思路分析:回归vs分类 由于输出数目不定,所以不能简单的把检测任务像定位任务一样归化为回归任务(检测任务会导致回归层神经元数目是不确定的) 在机器学习中,分类和回归是解决所有问题的两种基本思路,所以我们尝试用分类的思想分析问题. 思路是将所有可能分类的区域送入网络 问题是图片数量太多 直观的解决思路是换个速度快的电脑... ... 实际上新电脑还是不够快... ... 那就只查看一些可能的区域(预处理) Region

『cs231n』图像定位与检测

图像处理任务 分类,定位,检测,图像分割辨析: 定位: 每张图片只有单个对象(可以有多个类),后面有提到,一般只要是固定个对象即可,不一定是一个(人体姿势判断部分)由于实现相对简单,所以能划分为定位任务时尽量划分为定位任务 检测: 每张图片可以有多个对象和多个类 分割: 不是简单的画框,而是围出轮廓,本节不予讨论 图像分类&定位 定位任务引入 和分类任务输出一个代表类标签的向量不同,定位任务输出的是描述框的四个数字,而网络评估不使用准确率而使用IOU.[注]IOU定义如下: 矩形框A.B的一个重

『TensorFlow』图像预处理_

部分代码单独测试: 这里实践了图像大小调整的代码,值得注意的是格式问题: 输入输出图像时一定要使用uint8编码, 但是数据处理过程中TF会自动把编码方式调整为float32,所以输入时没问题,输出时要手动转换回来!使用numpy.asarray(dtype)或者tf.image.convert_image_dtype(dtype)都行 都行 1 import numpy as np 2 import tensorflow as tf 3 import matplotlib.pyplot as

『计算机视觉』物体检测之RefineDet

Two Stage 的精度优势 二阶段的分类:二步法的第一步在分类时,正负样本是极不平衡的,导致分类器训练比较困难,这也是一步法效果不如二步法的原因之一,也是focal loss的motivation.而第二步在分类时,由于第一步滤掉了绝大部分的负样本,送给第二步分类的proposal中,正负样本比例已经比较平衡了,所以第二步分类中不存在正负样本极度不平衡的问题.即二步法可以在很大程度上,缓和正负样本极度不平衡的分类问题二阶段的回归:二步法中,第一步会先对初始候选框进行校正,然后把校正过的候选框

『计算机视觉』Mask-RCNN_关键点检测分支(待续)

Github地址:Mask_RCNN 『计算机视觉』Mask-RCNN_论文学习 『计算机视觉』Mask-RCNN_项目文档翻译 『计算机视觉』Mask-RCNN_推断网络其一:总览 『计算机视觉』Mask-RCNN_推断网络其二:基于ReNet101的FPN共享网络 『计算机视觉』Mask-RCNN_推断网络其三:RPN锚框处理和Proposal生成 『计算机视觉』Mask-RCNN_推断网络其四:FPN和ROIAlign的耦合 『计算机视觉』Mask-RCNN_推断网络其五:目标检测结果精炼

使用Caffe完成图像目标检测 和 caffe 全卷积网络

一.[用Python学习Caffe]2. 使用Caffe完成图像目标检测 标签: pythoncaffe深度学习目标检测ssd 2017-06-22 22:08 207人阅读 评论(0) 收藏 举报  分类: 机器学习(22)  深度学习(12)  版权声明:本文为博主原创文章,未经博主允许不得转载. 目录(?)[+] 2. 使用Caffe完成图像目标检测 本节将以一个快速的图像目标检测网络SSD作为例子,通过Python Caffe来进行图像目标检测. 必须安装windows-ssd版本的Ca

『TensorFlow』分布式训练_其二_多GPU并行demo分析(待续)

建议比对『MXNet』第七弹_多GPU并行程序设计 models/tutorials/image/cifar10/cifer10_multi_gpu-train.py # Copyright 2015 The TensorFlow Authors. All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file exc

『ENGLISH』

以A字母开头的词汇 英文 中文 abstract module 抽象模组 access 访问.存取 access control 存取控制 access control information 存取控制资讯 access mechanism 存取机制 access rights 存取权限 accessibility 无障碍性 accessibility information 无障碍网页资讯 accessibility problem 无障碍网页问题 accessible 无障碍的 access

『TensorFlow』迁移学习_他山之石,可以攻玉

目的: 使用google已经训练好的模型,将最后的全连接层修改为我们自己的全连接层,将原有的1000分类分类器修改为我们自己的5分类分类器,利用原有模型的特征提取能力实现我们自己数据对应模型的快速训练.实际中对于一个陌生的数据集,原有模型经过不高的迭代次数即可获得很好的准确率. 实战: 实机文件夹如下,两个压缩文件可以忽略: 花朵图片数据下载: 1 curl -O http://download.tensorflow.org/example_images/flower_photos.tgz 已经