R-CNN,图片识别
目标检测(Object Detection)是图像分类的延伸,除了分类任务,还要给定多个检测目标的坐标位置。R-CNN是最早基于CNN的目标检测方法,然后基于这条路线依次演进出了SPPnet,Fast R-CNN和Faster R-CNN,然后到2017年的Mask R-CNN。
R-CNN 模型由候选区域(Region Proposal)、特征提取(Feature Extractor)和分类器(Classifier)三个模块组成。候选区域生成并提取独立类别的候选区域。特征提取从每个候选区域中提取特征,通常使用深度卷积神经网络。分类器使用线性 SVM 分类器模型将提取出的特征目标分类为已知类别之一。R-CNN 结构如下图所示。
1.候选区域
R-CNN 生成候选区域时使用了选择性搜索(Selective Search)算法,用来提出候选区域或图像中潜在对象的边界框。选择性搜索算法把图像分割成 1000-2000 个小区域,遍历分割的小区域并合并可能性最高的相邻区域,知道整张图像合并成一个区域位置,合并后输出所有存在过的区域,即候选区域。
通过选择性搜索算法选出的候选边框为矩形,不同物体矩形边框大小不同。但CNN模型的输入层图片必须固定分辨率,如果选择性搜索算法选出的矩形边框不进行预处理,则不能作为CNN的输入提取图像特征。因此每个输入图像的矩形候选框均要进行大小格式化处理。
2.特征提取
对特定目标的识别检测的难点之一是已标记物体分类标签的训练数据不多,CNN通常进行随机初始化神经网络参数,对训练数据量的要求非常高,因此 R-CNN 采用有监督的预训练,网络优化求解时采用随机梯度下降法,学习率大小为 0.001。
特征提取网络预训练后,采用选择性搜索算法搜索出来的候选框继续对经过了预训练 CNN模型进行训练。其原理是,假设模型需要检测的目标类别有N个,则要对前述经预训练的CNN模型最后一层进行替换,输出成N+1个神经元,其中多出一个背景神经元。该层的训练过程使用随机初始化参数的方法,其它网络层则参数不变。输入一张图片,可以得到 2000个左右候选框(Bounding Box)。数据集中的图片是提前进行人工标注的数据,每张图片都标注了涵盖目标物体的正确边框,因此在CNN阶段需要用重叠度(Intersection over Union,Io U)为 2000 个 Bounding Box 打分。若通过选择性搜索算法选出的 Bounding Box 与人工标注目标物体框的 Io U 大于 0.5,则将被 Bounding Box选中的物体标注成目标物体类别,该类物体成为正样本,若 Io U 小于 0.5 则该 Bounding Box 所框为背景类别,也成为负样本。
3.分类器
CNN的输出是一个4096个元素向量,用于描述图像的内容,并将其输入线性SVM进行分类,对每个已知类别的目标物体都训练一个支持向量机(Support Vector Machine,SVM),因此这是一个二分类问题。在特征提取过程中 R-CNN 模型通过选择性搜索算法选取了 2000 个左右 Bounding Box,即一个 2000×4096 特征向量矩阵,之后将矩阵与 SVM 权值矩阵 4096×N 点乘,可得到 2000×N 的结果矩阵,该矩阵表示了 2000个 Bounding Box 的分类结果。
R-CNN有如下缺点:
(1)需固定每一张子图片的大小,改变了原有图片的尺寸,影响CNN分类器的效果。
(2)将每一候选图片放入分类器训练,速度很慢并且有重复计算。
(3)其训练是分阶段的,对于目标检测而言,R-CNN首先需要对预训练模型进行特定类别物体的微调训练,然后再训练SVM对提取到的特征进行分类,最后还需要训练候选框回归器(Bounding-box Regressor)对候选子图中的目标进行精确的提取。
主程序:
import time
start = time.time()
import numpy as np
import os
import six.moves.urllib as urllib
import sys
import tarfile
import tensorflow.compat.v1 as tf
tf.disable_v2_behavior()
import zipfile
import cv2
from collections import defaultdict
from io import StringIO
from matplotlib import pyplot as plt
from PIL import Image
os.chdir('C://Users//fxlir//Desktop//my_detect')#文件夹路径
#Env setup
# This is needed to display the images.
#%matplotlib inline
# This is needed since the notebook is stored in the object_detection folder.
sys.path.append("..")
#Object detection imports
from object_detection.utils import label_map_util
from object_detection.utils import visualization_utils as vis_util
#Model preparation
# What model to download.
#这是我们刚才训练的模型
MODEL_NAME = 'C://Users//fxlir//Desktop//my_detect//models'#训练好的模型文件夹
#对应的Frozen model位置
# Path to frozen detection graph. This is the actual model that is used for the object detection.
PATH_TO_CKPT = MODEL_NAME + '//frozen_inference_graph.pb'#训练好的模型
# List of the strings that is used to add correct label for each box.
PATH_TO_LABELS = os.path.join('training', 'object-detection.pbtxt') #类别标签
#改成自己例子中的类别数,4
NUM_CLASSES = 1
#Load a (frozen) Tensorflow model into memory.
detection_graph = tf.Graph()
with detection_graph.as_default():
od_graph_def = tf.GraphDef()
with tf.gfile.GFile(PATH_TO_CKPT, 'rb') as fid:
serialized_graph = fid.read()
od_graph_def.ParseFromString(serialized_graph)
tf.import_graph_def(od_graph_def, name='')
#Loading label map
label_map = label_map_util.load_labelmap(PATH_TO_LABELS)
categories = label_map_util.convert_label_map_to_categories(label_map, max_num_classes=NUM_CLASSES, use_display_name=True)
category_index = label_map_util.create_category_index(categories)
#Helper code
def load_image_into_numpy_array(image):
(im_width, im_height) = image.size
return np.array(image.getdata()).reshape(
(im_height, im_width, 3)).astype(np.uint8)
#Detection
# If you want to test the code with your images, just add path to the images to the TEST_IMAGE_PATHS.
#测试图片位置
PATH_TO_TEST_IMAGES_DIR = 'C://Users//fxlir//Desktop//my_detect//raccoon'
os.chdir(PATH_TO_TEST_IMAGES_DIR)
TEST_IMAGE_PATHS = os.listdir(PATH_TO_TEST_IMAGES_DIR)
# Size, in inches, of the output images.
IMAGE_SIZE = (12, 8)
output_path = ('C://Users//fxlir//Desktop//my_detect//test_out//')
with detection_graph.as_default():
with tf.Session(graph=detection_graph) as sess:
# Definite input and output Tensors for detection_graph
image_tensor = detection_graph.get_tensor_by_name('image_tensor:0')
# Each box represents a part of the image where a particular object was detected.
detection_boxes = detection_graph.get_tensor_by_name('detection_boxes:0')
# Each score represent how level of confidence for each of the objects.
# Score is shown on the result image, together with the class label.
detection_scores = detection_graph.get_tensor_by_name('detection_scores:0')
detection_classes = detection_graph.get_tensor_by_name('detection_classes:0')
num_detections = detection_graph.get_tensor_by_name('num_detections:0')
for image_path in TEST_IMAGE_PATHS:
image = cv2.imread(image_path, 0)
image_BGR = cv2.cvtColor(image, cv2.COLOR_GRAY2BGR)#
#image_RGB = cv2.cvtColor(image_BGR, cv2.COLOR_BGR2RGB)#
image_np = image_BGR
image_np_expanded = np.expand_dims(image_np, axis=0)
(boxes, scores, classes, num) = sess.run(
[detection_boxes, detection_scores, detection_classes, num_detections],
feed_dict={image_tensor: image_np_expanded})
vis_util.visualize_boxes_and_labels_on_image_array(
image_np,
np.squeeze(boxes),
np.squeeze(classes).astype(np.int32),
np.squeeze(scores),
category_index,
use_normalized_coordinates=True,
line_thickness=8)
cv2.imwrite(output_path+image_path.split('\\')[-1],image_np)
cv2.imshow('object detection', image_np)
cv2.waitKey(0)
cv2.destroyAllWindows()
end = time.time()
print("Execution Time: ", end - start)
#欢迎订阅,一起学习,一起交流