目录

神经网络

准备用于对象检测的数据集

使用Keras实现R-CNN

添加Keras回调

测试我们的模型

R-CNN的局限性

下一步是什么?


  • 下载源4.2 KB

使用对象检测算法时,基本方法是尝试通过在目标对象周围绘制边界框来定位目标对象。由于可能存在多个感兴趣的对象,并且事先不知道它们的出现次数,因此会产生可变长度的输出层,这意味着无法通过构建由完全连接的层组成的标准深度神经网络来解决对象检测问题。解决此问题的一种方法是从图像中获取不同的感兴趣区域,并使用神经网络检测每个特定区域内是否存在所需对象。由于所需对象在图像中可能具有不同的纵横比和位置,从而导致大量区域并最终在计算上爆炸,因此该方法似乎也失败了。

为了解决该问题,已经开发了诸如R-CNN,Fast R-CNN和YOLO之类的算法。在本文中,我们将实现R-CNN以检测给定图像中的人。

查看上一篇

神经网络

带有CNN的区域(R-CNN)由Ross,Jeff和Jitendra于2014年提出。我们的想法是,我们无需对大量区域进行检测,而是通过选择性搜索传递图像,从而从图像中仅提取2000个区域地区提案。现在,我们可以与这2000个提议的区域合作,而不必尝试对大量区域进行分类。接下来,我们在提议的区域上计算联合交叉点(IOU),并使用地面真实数据添加标签。为了理解所有内容,我们将在这里使用Keras从零开始实现R-CNN,但是在本系列的后面部分,我们一定会更详细地介绍R-CNN。

准备用于对象检测的数据集

我们将使用可在kaggle上轻松获得的INRIAPerson数据集。提到的数据集有2个包含“测试”和“训练”数据的子目录,并且两个子目录都具有图像及其关联的注释。图像注释基本上标记了图像上的数据,并使对象可以被AI和ML模型感知。这些图像可能包含人类、车辆或任何其他类型的物体,以使其可被机器识别。但是,专门创建了INRIAPerson数据集以检测图像文件中的人,因此仅包含人注释。看下面的文件可以使思路清晰。

<?xml version="1.0" ?>
<annotation><folder>VOC2007</folder><filename>crop_000010.png</filename><source><database>PASperson Database</database><annotation>PASperson</annotation></source><size><width>594</width><height>720</height><depth>3</depth></size><segmented>0</segmented><object><name>person</name><pose>Unspecified</pose><truncated>0</truncated><difficult>0</difficult><bndbox><xmin>194</xmin><ymin>127</ymin><xmax>413</xmax><ymax>647</ymax></bndbox></object>
</annotation>

我们将使用这些注释使模型可识别对象。但是,在继续前进之前,我们首先需要将这些批注解析为csv文件并提取所需的数据。Python提供了用于解析xml文件的ElementTree API。下面是一个函数,可用于轻松加载和解析xml批注文件。

def parse_xml_to_csv(path):xml_list = []#iterate over all files to extract the bounding box for person present in the corresponding imagefor xml_annot in glob.glob(path + '/*.xml'):#load and parse filetree = ET.parse(xml_annot)doc = etree.parse(xml_annot)count = doc.xpath("count(//object)")#getting root of the documentroot = tree.getroot()with open(str(xml_annot)[0:-4]+".csv","w+") as file:file.write(str(int(count)))for person in root.findall('object'):value = (person[4][0].text,person[4][1].text,person[4][2].text,person[4][3].text)coors = " ".join(value)with open(str(xml_annot)[0:-4]+".csv","a") as file:file.write("\n")file.write(coors)

调用上面的函数,将路径传递到注释文件作为参数:

annot_path ="./Annotations"
xml_df = parse_xml_to_csv(annot_path)

功能完成后,您可以查看所有转换后的csv文件。

使用Keras实现R-CNN

有了数据,我们就可以继续实现R-CNN。首先,让我们导入将要使用的所有库。

import os                        # to interact with OS
import cv2                       # to perform selective search on images
import keras                     # to implement neural net
import numpy as np               # to work with arrays
import pandas as pd              # for data manipulation
import tensorflow as tf          # for deep learning models
import matplotlib.pyplot as plt  # for plotting

正如我们之前提到的,搜索感兴趣的区域在计算上已耗费大量力气,因此我们将在此处尝试实现有效的解决方案。选择性搜索根据颜色、纹理、大小或形状计算相似度,并按层次将最相似的区域分组。继续该过程,直到整个图像变为单个区域。OpenCV提供使用该createSelectiveSearchSegmentation函数来实现选择性搜索。将优化和选择性搜索添加到您的解决方案中,如下所示:

# OpenCV optimization
cv2.setUseOptimized(True);
# selective search
selective_search = cv2.ximgproc.segmentation.createSelectiveSearchSegmentation()

现在,如果我们在测试图像上应用选择性搜索,则会导致所需对象周围的边界框。

在这一点上,我们对当前边界框的精确度感兴趣。为此,我们可以简单地使用“联合交叉点”(IOU),这是一种评估指标,用于测量对象检测器的准确性。可以通过计算预测边界框和地面真相边界框之间的重叠面积(相交面积)除以两者所限定的总面积(并集面积)来计算:

def compute_iou(box1, box2):x_left = max(box1['x1'], box2['x1'])y_top = max(box1['y1'], box2['y1'])x_right = min(box1['x2'], box2['x2'])y_bottom = min(box1['y2'], box2['y2'])intersection_area = (x_right - x_left) * (y_bottom - y_top)box1_area = (box1['x2'] - box1['x1']) * (box1['y2'] - box1['y1'])box2_area = (box2['x2'] - box2['x1']) * (box2['y2'] - box2['y1'])union_area = box1_area + box2_area - intersection_areaiou = intersection_area / union_areareturn iou

现在,我们需要对数据进行预处理,以创建可以传递给我们的模型的数据集。我们将遍历所有图像并将它们设置为选择性搜索的基础。然后,我们将对通过选择性搜索得出的前2000个建议区域进行迭代,并计算IOU,以便可以注释所需对象(人类)的区域。这些图像将根据对象的存在进行标记,并将附加到我们的training_images数组中。

training_images=[]
training_labels=[]
for e,i in enumerate(os.listdir(annot)):try:filename = i.split(".")[0]+".png"img = cv2.imread(os.path.join(path,filename))dataframe = pd.read_csv(os.path.join(annot,i))ground_truth_values=[]for row in dataframe.iterrows():x1 = int(row[1][0].split(" ")[0])y1 = int(row[1][0].split(" ")[1])x2 = int(row[1][0].split(" ")[2])y2 = int(row[1][0].split(" ")[3])ground_truth_values.append({"x1":x1,"x2":x2,"y1":y1,"y2":y2})# setting the image as base image for selective searchselective_search.setBaseImage(img)# initializing fast selective searchselective_search.switchToSelectiveSearchFast()# getting proposed regionsssresults = selective_search.process()imout = img.copy()counter = 0f_counter = 0flag = 0fflag = 0bflag = 0for e,result in enumerate(ssresults):# iterating over the first 2000 results from selective search to colculate IOUif e < 2000 and flag == 0:for val in ground_truth_values:x,y,w,h = resultiou = compute_iou(val,{"x1":x,"x2":x+w,"y1":y,"y2":y+h})# limiting the maximum positive samples to 20if counter < 20:# setting IOU > 0.70 as goodness measure for positive i.e. person detectedif iou > 0.70:image = imout[y:y+h,x:x+w]resized = cv2.resize(image, (224,224), interpolation = cv2.INTER_AREA)training_images.append(resized)training_labels.append(1)counter += 1else :fflag =1# limiting the maximum negative samples to 20if f_counter <20:if iou < 0.3:image = imout[y:y+h,x:x+w]resized = cv2.resizetimage, (224,224), interpolation = cv2.INTER_AREA)training_images.append(resized)training_labels.append(0)f_counter += 1else :bflag = 1if fflag == 1 and bflag == 1:flag = 1except Exception as e:print(e)continue

现在,training_images和training_labels包含我们模型的新x和y坐标。让我们从模型的导入开始。

from keras.layers import Dense
from keras import Model
from keras import optimizers
from keras.optimizers import Adam
from keras.applications.vgg16 import VGG16
from keras.preprocessing.image import ImageDataGenerator
from keras.callbacks import ModelCheckpoint, EarlyStopping

从技术上讲,R-CNN模型可以从头开始拟合,但是它花费了太多时间,并且导致性能不佳。在这里,我们将使用迁移学习来节省时间并获得更好的性能。您可以根据自己的喜好使用imagenet或coco权重进行转移学习。

vggmodel = VGG16(weights='imagenet', include_top=True)
vggmodel.summary()

上面的代码片段导致以下输出:

接下来,我们将设置trainable为false冻结模型的前十层。

for layers in (vggmodel.layers)[:10]:
layers.trainable = False

我们只对人类的存在与否感兴趣,这意味着我们只有两个类别可以预测,因此我们将添加两个具有softmax激活的单位密集层。使用softmax激活的原因是它确保输出的总和为1(即,输出是概率)。

X= vggmodel.layers[-2].output
predictions = Dense(2, activation="softmax")(X)

最后,我们将使用Adam优化器来编译模型。

model_final = Model(vggmodel.input, predictions)
model_final.compile(loss = keras.losses.categorical_crossentropy, optimizer = Adam(lr=0.001), metrics=["accuracy"])

我们已经创建了模型。在继续之前,我们需要对数据集进行编码。我们可以使用LabelBinarizer编码。

class Label_Binarizer(LabelBinarizer):def transform(self, y_old):Y = super().transform(y_old)if self.y_type_ == 'binary':return np.hstack((Y, 1-Y))else:return Ydef inverse(self, Y):if self.y_type_ == 'binary':return super().inverse(Y[:, 0])else:return super().inverse(Y)
encoded = Label_Binarizer()
Y =  encoded.fit_transform(y_new)

我们还需要将数据集分为训练集和测试集,可以使用来自sklearn的train_test_split来完成。在这里,我们将数据分为80%的训练和20%的测试比率。

X_train, X_test , y_train, y_test = train_test_split(X_new,Y,test_size=0.20)

Keras提供ImageDataGenerator来将数据集传递给模型。您还可以应用水平或垂直翻转来增加数据集。

train_data_prep = ImageDataGenerator(horizontal_flip=True, vertical_flip=True, rotation_range=90)
trainingdata = train_data_prep.flow(x=X_train, y=y_train)
test_data_prep = ImageDataGenerator(horizontal_flip=True, vertical_flip=True, rotation_range=90)
testingdata = test_data_prep.flow(x=X_test, y=y_test)

添加Keras回调

训练深度神经网络需要花费大量时间,而且我们总是有浪费计算资源的风险。为避免此问题,Keras提供了两个回调:EarlyStopping和ModelCheckPoint。EarlyStopping在一个时代结束时被调用。一旦不再改善训练流程,它将终止训练过程,从而使您可以配置任意数量的时代。ModelCheckpoint在每个时代之后也会调用,并自动保存效果最佳的模型。在使用fit_generator训练模型时,我们可以同时使用两个回调:

checkpoint = ModelCheckpoint("rcnn.h5", monitor='val_loss', verbose=1, save_best_only=True, save_weights_only=False, mode='auto', save_freq=1)
early = EarlyStopping(monitor='val_loss', min_delta=0, patience=100, verbose=1, mode='auto')
hist = model_final.fit_generator(generator= traindata, steps_per_epoch= 10, epochs= 500, validation_data= testdata, validation_steps=2, callbacks=[checkpoint,early])

测试我们的模型

现在将创建我们的模型并将其保存为rcnn.h5,我们处于良好的位置对模型进行预测。我们将按照与之前相同的步骤进行操作:遍历所有图像并将它们设置为基本图像以进行选择性搜索。稍后,我们会将选择性搜索结果传递给我们的模型进行预测,并且模型在图像中遇到人类时会创建边界框。

count=0
for e,i in enumerate(os.listdir(path)):count += 1image = cv2.imread(os.path.join(path,i))selective_search.setBaseImage(image)selective_search.switchToSelectiveSearchFast()ssresults = selective_search.process()imout = image.copy()for e, res in enumerate(ssresults):if e < 2000:x,y,w,h = restest_image = imout[y:y+h,x:x+w]resized = cv2.resize(test_image, (224,224), interpolation = cv2.INTER_AREA)image = np.expand_dims(resized, axis=0)out= model_final.predict(image)if out[0][0] > 0.65:cv2.rectangle(imout, (x, y), (x+w, y+h), (0, 255, 0), 1, cv2.LINE_AA)plt.figure()plt.imshow(imout)

注意:结果来自提前终止

R-CNN的局限性

R-CNN具有一些缺点。它仍然在其根部实现滑动窗口。唯一的区别是,它实际上是作为卷积实现的,这使其比传统的滑动窗口技术更有效。但是,对于2000个区域提案中的每一个提案,它仍然需要对CNN进行全面的前瞻,并且具有复杂的多阶段培训流程,从而导致性能问题。同样,由于测试时间长,R-CNN在实时或拥挤的区域变得不可行。

下一步是什么?

在本文中,我们学习了在Keras中使用深度神经网络实现第一个自定义对象检测器。我们还讨论了该方法的一些局限性。在该系列的下一篇文章中,我们将尝试克服R-CNN带来的限制,并获得对该区域中存在的人数的估计。

AI队列长度检测:R-CNN用于使用Keras进行自定义对象检测相关推荐

  1. jetson nano opencv 打开 CSI摄像头_Nvidia Jetson Nano:使用Tensorflow和OpenCV从头开始自定义对象检测...

    本文作者: 转载自: https://medium.com/swlh/nvidia-jetson-nano-custom-object-detection-from-scratch-using-ten ...

  2. 使用 Tensorflow 2 进行自定义对象检测的一般方法

    在本文中,将向你介绍如何使用 Tensorflow 2 训练你自己的自定义对象检测器.这不是进行特定类型检测的教程,而是我们可以用来检测任何东西的常用方法. 要使用 Tensorflow 对象检测 A ...

  3. AI队列长度检测:使用YOLO进行图像中的对象检测

    目录 YOLO简介 创建和加载模型 预处理输入 获取边界框 下一步是什么? 下载源219 MB 在本系列的前几篇文章中,我们从头开始实现了对象检测.我们观察到从头训练模型需要大量的计算资源和时间.这些 ...

  4. AI队列长度检测:使用YOLO进行视频中的对象检测

    下载源219 MB 到目前为止,在本系列中,我们一直在处理静止图像数据.在本文中,我们将使用YOLO的基本实现来检测和计数视频序列中的人物. 让我们再次从导入所需的库开始. import cv2 im ...

  5. 如何使用 Yolo v5 对象检测算法进行自定义对象检测

    介绍 在本文中,将向你解释如何使用 Yolo v5 算法检测和分类60+个不同类型的道路交通标志. 我们将从非常基础的开始,涵盖每个步骤,如准备数据集.训练和测试等.在本文中,我们将使用 Window ...

  6. GluonCV-物体检测教程-09.在网络摄像头上运行对象检测模型

    本文将展示如何通过直接在您的网络摄像头视频流上运行预先训练的对象检测模型. NOTE: 本教程仅在MacOS环境中测试过 需要的Python包:cv2,matplotlib 你需要一个摄像头:) 与m ...

  7. AI队列长度检测:使用Keras进行对象检测

    目录 介绍 AI队列长度检测:使用Keras进行对象检测 卷积神经网络 训练CNN以检测物体 测试我们的模型 下一步是什么? 下载源1.4 KB 介绍 看到人们排队进入您的咖啡店或商店是一件很棒的事, ...

  8. 开源代码MatrixNets:用于对象检测的新的比例和长宽比感知体系结构

    今天我们介绍MatrixNets(xNets),这是一种用于对象检测的新的深层体系结构.xNets将具有相似大小和高宽比的对象映射到许多专门的层中,从而使xNets可以提供可感知比例和高宽比的体系结构 ...

  9. 检测和语义分割_分割和对象检测-第5部分

    检测和语义分割 有关深层学习的FAU讲义 (FAU LECTURE NOTES ON DEEP LEARNING) These are the lecture notes for FAU's YouT ...

最新文章

  1. Spark-core(核心)的基本介绍
  2. 轻松搞定个人虚拟桌面部署之1-远程桌面服务概述
  3. MSSQL优化之————探索MSSQL执行计划
  4. servlet中用out.print输出中文为“乱码”如何解决
  5. 中国新时代贡献人物_关于如何鼓励新贡献者的8个新博客文章
  6. Mybatis 处理日期格式自动转换
  7. Freeswitch配置:一台Freeswitch向另外一台Freeswitch转发视频会议命令
  8. 选择最佳的DC/DC转换器的五大秘诀
  9. css音乐播放器插件,jQuery MPlayer音乐播放器插件
  10. 思科服务器a设置dns信息,思科怎么配置dns服务器
  11. 资产初探:信贷资产流转业务及其与资产证券化的区别
  12. matlab统计学分析函数
  13. 如果觉得上面太正式,请看小红书风格的“从数字化转型到智能化转型”
  14. 3dmark压力测试 linux,压榨你的电脑潜能:3DMark压力测试正式发布
  15. 码农故事2——岁前落脚得安定 年后求职寻转机
  16. 58——FFA-Net: Feature Fusion Attention Network for Single Image Dehazing
  17. css动画让文字一行一行逐渐显示
  18. ZigBee的无线通信与网络组建
  19. bcd 初始化库系统卷失败_U盘多系统启动制作教程 教你做多U盘系统启动盘
  20. Python正则表达式——数量词

热门文章

  1. 运行gulp_Gulp的基本使用
  2. 计算机不属于发明保护客体,如何判断两种类型的计算机程序发明能否成为专利保护客体?...
  3. android自定义队列,Android 消息机制(一)消息队列的创建与循环的开始 Looper与MessageQueue...
  4. UI设计素材模板|音乐社交娱乐教育APP Makeapp Wireframe Kit
  5. 淘宝美工设计初学必会技能之PSD分层模板
  6. python分词统计词频_python jieba分词并统计词频后输出结果到Excel和txt文档方法
  7. C++引用和指针区别
  8. MyBatis的概述及使用
  9. Linux内存管理:转换后备缓冲区(TLB)原理
  10. 【网站推荐】Solaris 平台编写设备驱动程序