前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >算法集锦(11)| 自动驾驶 | 基于HOG和SVM的车辆识别算法

算法集锦(11)| 自动驾驶 | 基于HOG和SVM的车辆识别算法

作者头像
用户7623498
发布2020-08-04 16:01:13
1.2K0
发布2020-08-04 16:01:13
举报

本文旨在介绍一种基于方向梯度直方图(HOG)和支持向量机(SVM,Support Vector Machines)的车辆检测和跟踪算法。该算法在OpenCV和Sklearn环境下开发,经不断优化后在实际路况下得到了成功的应用。

为实现该算法,需要完成以下几步:

  • 在标注的训练集中提取HOG特征
  • 在图像数据集(图片中有车辆或无车辆)中训练分类器
  • 在每一帧视频图像下进行窗口滑移(sliding window),以获得图像的子区域
  • 在各个子区域(subregion)中应用训练好的分类器
  • 创建热点图(heat map),并逐帧的进行车辆检测和跟踪

方向梯度直方图

注意到,不同车辆的颜色千变万化,而它们的形状则基本一致,因此用车辆的形状参数来代表车辆具有更高的鲁棒性。通常,通过分析不同方向的梯度值可以获得 物体的形状特征,为了弱化车辆在形状上的细微差异,采用方向梯度直方图(Histogram of Oriented Gradient,HOG)进行形状检测具有更好的效果。

HOG是一种在计算机视觉和图像处理中用来进行物体检测的特征描述子,通过计算和统计图像局部区域的梯度方向直方图来构成特征。首先,把样本图像分割为若干个像素的单元,把梯度方向平均划分为多个区间,在每个单元里面对所有像素的梯度方向在各个方向区间进行直方图统计,得到一个多维的特征向量。每相邻的单元构成一个区间,把一个区间内的特征向量联起来得到多维的特征向量,用区间对样本图像进行扫描,扫描步长为一个单元。最后,将所有块的特征串联起来,就得到了车辆的特征。

特征提取

我们需要设置number_of_rientations, pixels_per_cellcells_per_block等参数来计算图像各个通道的HOG值。其中number_of_rientations 参数决定每个单元的像素梯度在直方图中用几个线段表示;pixels_per_cell 代表每个单元(cell)中包含的像素的行数和列数;cells_per_block 指定直方图进行归一化的局部区域。通过设置这些参数,可以提取出更可靠的特征集。此外,还可以应用transfor_sqrt 来消除阴影和光照变化的影响。

下面,我们来看看不同参数下提取的车辆特征情况。

代码语言:javascript
复制
feature_params = {
  'color_model': 'yuv',                # hls, hsv, yuv, ycrcb
  'bounding_box_size': 64,             # 64 pixels x 64 pixel image
  'number_of_orientations': 11,        # 6 - 12
  'pixels_per_cell': 8,                # 8, 16
  'cells_per_block': 2,                # 1, 2
  'do_transform_sqrt': True
}
# [3 x 3 block positions] x [2 x 2 cells per block] x [11 orientations] x [3 channels] = 1,188 features
source = FeatureSourcer(feature_params, vehicle_image)
vehicle_features = source.features(vehicle_image)
rgb_img, y_img, u_img, v_img = source.visualize()
代码语言:javascript
复制
feature_params = {
  'color_model': 'hls',                # hls, hsv, yuv, ycrcb
  'bounding_box_size': 64,             # 64 pixels x 64 pixel image
  'number_of_orientations': 12,        # 6 - 12
  'pixels_per_cell': 16,                # 8, 16
  'cells_per_block': 2,                # 1, 2
  'do_transform_sqrt': True
}
# [7 x 7 block positions] x [2 x 2 cells per block] x [12 orientations] x [3 channels] = 7,056 features
代码语言:javascript
复制
YUV Feature Extraction Time Taken: 471.28
HLS Feature Extraction Time Taken: 1781.44

分类器训练

我们采用支持向量机(SVM)作为分类器策略。图像数据集共包括8792个含车辆的图片和8968个不含车辆的图片。为了减小训练误差,在将原始特征输入分类器前,我们用scaler 函数对其进行转换处理。

代码语言:javascript
复制
# Feature Extraction...
for img in vehicle_imgs:
  vehicles_features.append(source.features(img))
for img in nonvehicle_imgs:
  nonvehicles_features.append(source.features(img))
# Scaling Features...
unscaled_x = np.vstack((vehicles_features, nonvehicles_features)).astype(np.float64)
scaler = StandardScaler().fit(unscaled_x)
x = scaler.transform(unscaled_x)
y = np.hstack((np.ones(total_vehicles), np.zeros(total_nonvehicles)))
# Training Features...
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size = 0.2, random_state = rand.randint(1, 100))
svc = LinearSVC()
svc.fit(x_train, y_train)
accuracy = svc.score(x_test, y_test)
代码语言:javascript
复制
HLS Features Classifier Accuracy: 0.9878
YUV Features Classifier Accuracy: 0.9834
代码语言:javascript
复制
class BinaryClassifier:
  def __init__(self, svc, scaler):
    self.svc, self.scaler = svc, scaler
  def predict(self, f):
    f = self.scaler.transform([f])
    r = self.svc.predict(f)
    return np.int(r[0])

滑动窗口

我们通过滑动窗口来获得视频图像的不同子区域(subregion),然后在其上应用分类器来判断该区域是否包含车辆。考虑到计算HOG特征非常耗时,因此我们仅在开始时计算整个图片的HOG特征值,然后再在需要时才计算子区域的HOG特征,这样可以有效的提高计算效率。

通常我们仅对地平线以下的区域进行搜索,因此车辆不可能“开”到天上去。

代码语言:javascript
复制
cls = BinaryClassifier(svc, scaler)
src = FeatureSourcer(feature_params, temp_frame)
slider = Slider(sourcer = src, classifier = cls, increment = 8)
window_sizes = 80, 120, 150, 180
strip_positions = 410, 390, 380, 380
boxed_images, strips = [], []
for ws, wp in zip(window_sizes, strip_positions):
  bounding_boxes = slider.locate(frame = this_frame, window_size = ws, window_position = wp)
  boxed_image = put_boxes(this_frame, bounding_boxes)
  boxed_images.append(boxed_image)
  strips.append(slider.strip())
show_images(strips)
show_images(boxed_images)

热点图

在连续的视频中,可能会出现交叉识别(overlapping detection)或者假阳性识别(false positive detection)问题。我们可以采用热点图(hot map)方法来解决该问题。

首先,先设置一个空白的“白板”,当分类器检测到车辆时,就在增加相应区域的“热度值”,并随着视频的变化循环往复的进行检测。最终,有车辆存在的区域就会变得越来越“热”,从而识别出车辆的准确位置。应用时,通常会设置一个阙值来剔除假阳性出现的区域,有车辆存在的区域一直会保持“热态”,而偶尔出现的假阳性检测结果随着时间的变化迅速变为“冷态”。

代码语言:javascript
复制
this_heatmap = HeatMap(frame = temp_frame, thresh = 20, memory = 30) 
this_heatmap.reset()
for sz, pos in zip(ws, wp):
  bounding_boxes = slider.locate(frame = this_frame, window_size = sz, window_position = pos)
  this_heatmap.update(bounding_boxes)
heatmap, thresholded_map, labeled_map = this_heatmap.get()
labeled_frame = this_heatmap.draw(this_frame)

总 结

本文介绍的算法的流程为:首先通过HOG提取图像的特征,然后将其输入到SVM分类器中进行车辆识别。通过滑动窗口技术来检测图像的不同区域,获得车辆的准确位置。此外为了解决交叉识别和假阳性检测问题,应用了热点图技术。

实际应用发现,HLS和YUV色彩编码模式下的图像更适用于HOG特征提取,并且YUV模式的运算效率较HLS高,因此建议采用YUV色彩编码进行车辆检测。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2018-05-23,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 决策智能与机器学习 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档