基于卷积神经网络的城市交通拥堵预警系统

接到一个非常古怪的大创项目,辣鸡学校竟然还有deep learning的东西,大吃一鲸……

感觉开启了新世界的大门……虽然用到的东西都很浅显,但是还是不得不一边做一边各处找博客学习……

所以写点东西来记录一下做这个东西的过程吧~

前言

项目的需求是基于深度学习,建立一个CNN网络,读取交通监控视频,当堵车现象发生时发出警示。

我的想法是首先把视频切成帧,然后做一个图像分类器对当前帧进行处理,如果判断为畅通那么不做处理,如果判断为拥堵那么进一步与下一帧图片做相似度检测,超过阈值即判断拥堵现象出现。

感觉项目挺有意思的,想吐槽的一点就是数据集太少了……只有两三条街的监控录像让我怎么好好玩嘛……

流程

TensorFlow是Google基于DistBelief进行研发的第二代人工智能学习系统,被广泛用于语音识别或图像识别等多项机器深度学习领域。其命名来源于本身的运行原理。Tensor(张量)意味着N维数组,Flow(流)意味着基于数据流图的计算,TensorFlow代表着张量从图象的一端流动到另一端计算过程,是将复杂的数据结构传输至人工智能神经网中进行分析和处理的过程。

Tensorflow的安装

1
2
3
4
5
$ sudo easy_install --upgrade pip
$ sudo easy_install --upgrade six
# Mac OS X, CPU only, Python 2.7:
$ export TF_BINARY_URL=https://storage.googleapis.com/tensorflow/mac/cpu/tensorflow-0.12.1-py2-none-any.whl
$ sudo pip install --upgrade $TF_BINARY_URL

测试一下是否安装成功:

1
2
3
4
import tensorflow as tf
hello = tf.constant('Hello, TensorFlow!')
sess = tf.Session()
print sess.run(hello)


Inception模型安装

1
2
$ git clone https://github.com/tensorflow/tensorflow.git
$ git clone https://github.com/tensorflow/models.git

测试一下:

1
2
$ cd models/tutorials/image/imagenet
$ python classify_image.py


数据集处理

数据集处理主要使用OpenCV对图片进行压缩处理,加快训练速度。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import os
import cv2
import numpy as np
image_dir = '02'
new_dir = 'Cars_02'
if not os.path.exists(new_dir):
os.makedirs(new_dir)
for img_file in os.listdir(image_dir):
img_file_path = os.path.join(image_dir, img_file)
img = cv2.imread(img_file_path)
img = cv2.resize(img, (480, 270))
new_file = os.path.join(new_dir, img_file)
cv2.imwrite(new_file, img)
print(new_file)

最后我们把处理好的图片整理一下,分类丢到不同的文件夹就好了。


图像分类模型的训练

因为从零开始训练一个新的模型代价太大了,不管是网络结构还是调参数都是很麻烦的事情…

所以我们基于Inception模型来retrain一个图像分类模型,Inception模型是Google用两个星期,使用上百万张带分类的图片训练出的模型(http://arxiv.org/abs/1512.00567), 在做图像识别时,为了节省时间通常使用预训练的Inception模型做为训练基础。

在这里我们采用迁移学习的方法,利用已有的model,在前面的网络层中提取feature,去掉最后一个分类的全连接层,在分类器层之前提取多维度的特征。即前面各层的参数都不变,调整网络的最后的一层,变为所需要的输出节点数量,然后训练最后一层softmax分类器。

在Tensorflow里是这样实现的:将自己的训练集中的图像输入网络,最后在倒数第二层bottleneck层中会生成2048维的特征向量,再用这个特征来训练softmax分类器。

具体的方法如下:

把训练集分好类放到一个文件夹下,然后运行retrain.py脚本。

1
$ python tensorflow/tensorflow/examples/image_retraining/retrain.py --output_graph output_graph.pb --output_labels output_labels.txt --image_dir ~/desktop/tmp

训练过程中会下载大约100M左右的模型文件,模型下载完成后就可以看到训练已经开始了,首先是提取图片的bottleneck特征并生成特征文件:

整个过程大约20分钟,最后训练结果如下:

最终生成的模型和标签文件:

然后我们使用训练好的模型来做图像分类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import tensorflow as tf
import sys
image_file = sys.argv[1]
image = tf.gfile.FastGFile(image_file, 'rb').read()
labels = []
for label in tf.gfile.GFile("output_labels.txt"):
labels.append(label.rstrip())
with tf.gfile.FastGFile("output_graph.pb", 'rb') as f:
graph_def = tf.GraphDef()
graph_def.ParseFromString(f.read())
tf.import_graph_def(graph_def, name='')
with tf.Session() as sess:
softmax_tensor = sess.graph.get_tensor_by_name('final_result:0')
predict = sess.run(softmax_tensor, {'DecodeJpeg/contents:0': image})
print 'Result: '
top = predict[0].argsort()[-len(predict[0]):][::-1]
f = predict[0][top[0]] * 100
print labels[top[0]] + ' Accuracy: %.2f%%' %f
for index in top:
human_string = labels[index]
score = predict[0][index]
print(human_string, score)

最后找几张图片来测试一下效果:

似乎 效果还不错?


视频序列的处理

最后,我们加上opencv有关视频处理的代码,读取视频并保存成图片交给我们的分类模型进行处理,然后拥堵的时候使用感知哈希来检测相邻图片的相似性。

哈希就是将图像按照一定的哈希算法,经过运算后得出的一组二进制数字。而我们利用汉明距离就可以通过这串二进制数字来算出图片之间的差异,这里的感知哈希采用的是离散余弦变换来降低频率的方法。

这样,一个大概的框架就差不多搞定了。随便找了一段视频测试了一下,大约一张图片需要跑2到3秒左右。那么要想达到实时处理的效果中间这段时间就只能舍弃了……(毕竟垃圾电脑,感觉升级一下配置可能会更快一点?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
#coding=utf-8
import tensorflow as tf
import sys
import cv2
import time
import numpy as np
vc = cv2.VideoCapture('/Users/user/Desktop/t.mp4') #读入视频文件
total = vc.get(cv2.cv.CV_CAP_PROP_FRAME_COUNT)
fps = vc.get(cv2.cv.CV_CAP_PROP_FPS)
c = 1
labels = []
for label in tf.gfile.GFile("output_labels.txt"):
labels.append(label.rstrip())
with tf.gfile.FastGFile("output_graph.pb", 'rb') as f:
graph_def = tf.GraphDef()
graph_def.ParseFromString(f.read())
tf.import_graph_def(graph_def, name='')
def getHash(image):
avreage = np.mean(image)
hash = []
for i in range(image.shape[0]):
for j in range(image.shape[1]):
if image[i,j] > avreage:
hash.append(1)
else:
hash.append(0)
return hash
def Hamming_distance(hash1,hash2):
num = 0
for index in range(len(hash1)):
if hash1[index] != hash2[index]:
num += 1
return num
def classify_pHash(image1, image2):
image1 = cv2.resize(image1, (80, 60))
image2 = cv2.resize(image2, (80, 60))
gray1 = cv2.cvtColor(image1, cv2.COLOR_BGR2GRAY)
gray2 = cv2.cvtColor(image2, cv2.COLOR_BGR2GRAY)
# 将灰度图转为浮点型,再进行dct变换
dct1 = cv2.dct(np.float32(gray1))
dct2 = cv2.dct(np.float32(gray2))
dct1_roi = dct1[0:8, 0:8]
dct2_roi = dct2[0:8, 0:8]
hash1 = getHash(dct1_roi)
hash2 = getHash(dct2_roi)
return Hamming_distance(hash1, hash2)
def f():
cv2.imwrite('/Users/user/Desktop/test/' + str(c) + '.jpg', frame)
image_file = '/Users/user/Desktop/test/' + str(c) + '.jpg'
cv2.imshow('image', frame)
image = tf.gfile.FastGFile(image_file, 'rb').read()
with tf.Session() as sess:
softmax_tensor = sess.graph.get_tensor_by_name('final_result:0')
predict = sess.run(softmax_tensor, {'DecodeJpeg/contents:0': image})
top = predict[0].argsort()[-len(predict[0]):][::-1]
f = predict[0][top[0]] * 100
if c == 1: return
if top[0] == 1 :
img1 = cv2.imread('/Users/user/Desktop/test/' + str(c) + '.jpg')
cv2.imshow('img1', img1)
img2 = cv2.imread('/Users/user/Desktop/test/' + str(c - 1) + '.jpg')
cv2.imshow('img2', img2)
degree = classify_pHash(img1, img2)
print '__Result: '
if(degree < 10) :
print labels[top[0]] + ' accuracy: %.2f%%' % f
else :
print labels[top[1]] + ' accuracy: %.2f%% ' % (100 - f) \
+ 'similarity: '+ str(degree)
t = 0
while vc.isOpened():
for i in range(0, (int)(t + 0.5)):
rval, frame = vc.read()
rval, frame = vc.read()
t1 = time.time()
f()
t2 = time.time()
t = (t2 - t1) * fps
print '%.2f ' %(t2 - t1) + ' %.2f' %(t)
c = c + 1
vc.release()

未完待续…?

参考:

[1]: https://www.tensorflow.org/tutorials/image_retraining
[2]: http://blog.csdn.net/daydayup_668819/article/details/68060483
[3]: http://blog.topspeedsnail.com/archives/10685
[4]: http://blog.csdn.net/qq_25231283/article/details/52700394
[5]: http://blog.csdn.net/feimengjuan/article/details/51279629


文章目录
  1. 1. 前言
  2. 2. 流程
    1. 2.1. Tensorflow的安装
    2. 2.2. Inception模型安装
    3. 2.3. 数据集处理
    4. 2.4. 图像分类模型的训练
    5. 2.5. 视频序列的处理
  3. 3. 参考: