机器学习实战:车辆检测( 二 )


def color_histogram(img, nbins=32, bins_range=(0, 256)):"""Returns the histograms of the color image across all channels, as a concatenanted feature vector"""# Compute the histogram of the color channels separatelychannel1_hist = np.histogram(img[:,:,0], bins=nbins, range=bins_range)channel2_hist = np.histogram(img[:,:,1], bins=nbins, range=bins_range)channel3_hist = np.histogram(img[:,:,2], bins=nbins, range=bins_range)# Concatenate the histograms into a single feature vector and return itreturn np.concatenate((channel1_hist[0], channel2_hist[0], channel3_hist[0]))
分类器
分类器负责将指定的图像分类为车辆/非车辆 。为此目的,我们按以下步骤进行实现:
正如上一节所讨论的,我们决定只保留一个特征:YCrCb图像Y通道上计算的HOG特征向量 。
我们随机地分割数据集,留下20%用于测试 。然后使用.. 来归一化样本数据 。
由于没有足够的时间来测试众多的分类器,我们主观选择了支持向量机 (SVM),因为在物体检测的相关文献中,SVM与HOG是常见的组合 。而且,我们使用了rbf核函数的SVC,因为它精度最高,虽然要比慢一些,但是在一系列图像上的测试表明,使用rbf核的SVC,其物体检测能力要强得多 。
我们使用函数获得了以下参数的理想值:核类型( 或rbf ),C ( 1,100,1000,1000 )和gamma ( auto,0.01,0.1,1 )之间。最佳的配置可以实现99%以上的准确度,参数如下:
滑动窗口检测
我们创建多个尺寸的滑动窗口,大小从64x64到像素,然后使用分类器来识别这些窗口,并且只保留正向的预测 。我们在屏幕底部使用较大的滑动窗户,因为这一区域的车辆通常较大,而在屏幕上方则使用较小的滑动窗口 。在y方向小于350像素的区域(即图像上部)不进行车辆检测 。下图显示了单元的重叠设置为4时的滑动窗口检测示例:

机器学习实战:车辆检测

文章插图
热图和阈值化
我们的分类器有时(不可避免地)会将非车辆区域错误地识别为车辆 。为了避免在视频上突出显示这些误报区域,我们可以利用滑动窗口中的冗余信息,计算某一区域被检测为车辆的次数 。首先使用scipy..的label函数来标记具有重叠窗口的对象 。然后通过物体最小边界框来提取每个标签的位置 。我们只保留识别为车辆的次数超过特定阈值的区域 。根据实验,我们发现阈值4就可以取得不错的结果 。下面的照片展示了热图和阈值的工作原理:
机器学习实战:车辆检测

文章插图
第一个小热图表示分类器的原始检测结果,而第二个小热图表示阈值区域,红色强度随着重叠窗口数量的增加而增加 。右侧的最后一张小图显示了分类器预测为车辆的所有窗口 。在这个例子中,我们实际上使用的是,它比rbf核的SVC更容易得到错误的预测 。
帧聚合
为了进一步强化我们的处理流水线,我们决定每隔n帧平滑所有的检测窗口 。为此,我们缓存在( n-1)* f + 1到n* f之间所有检测到的窗口,其中n是正标量,表示当前所在的帧分组 。下面的类封装了检测到的物体:
class DetectedObject:"""The DetectedObject class encapsulates information about an object identified by our detector"""def __init__(self, bounding_box, img_patch, frame_nb):self.bounding_box = bounding_boxself.img_patch = img_patch self.frame_nb = frame_nbself.centroid = (int((bounding_box[0][0] + bounding_box[1][0]) / 2), int((bounding_box[0][1] + bounding_box[1][1]) / 2))self.similar_objects = []...
每当组中的当前帧或下一帧中检测到一个新目标时,检查过去是否检测到类似的对象,如果是的话,我们追加那个类似的对象,从而增加这个对象在多个帧中的计数 。在帧n * f处,我们只保留那些检测超过m次的物体(及其边界框),从而在流水线中实现某种双重滤波 。