TensorFlow 和 OpenCV 实时分类

Posted

技术标签:

【中文标题】TensorFlow 和 OpenCV 实时分类【英文标题】:Tensorflow and OpenCV real-time classification 【发布时间】:2017-11-24 22:26:10 【问题描述】:

我正在测试机器学习水域并使用TS inception 模型重新训练网络以对我想要的对象进行分类。

最初,我的预测是在本地存储的图像上运行的,我意识到从文件中取消持久化图形需要 2-5 秒,而运行实际预测需要大约同一时间。

此后,我调整了我的代码以合并来自 OpenCV 的摄像头馈送,但由于上述时间,视频延迟是不可避免的。

在初始图形加载期间预计会出现时间命中;这就是为什么 initialSetup() 事先运行,但 2-5 秒是荒谬的。 我觉得我目前的申请;实时分类,这不是最好的加载方式。还有另一种方法吗?我知道移动版本 TS 建议缩小图表。瘦下来会是这里的路吗?万一这很重要,我的图表目前是 87.4MB

除此之外,有没有办法加快预测过程?

import os
import cv2
import timeit
import numpy as np
import tensorflow as tf

camera = cv2.VideoCapture(0)

# Loads label file, strips off carriage return
label_lines = [line.rstrip() for line
               in tf.gfile.GFile('retrained_labels.txt')]

def grabVideoFeed():
    grabbed, frame = camera.read()
    return frame if grabbed else None

def initialSetup():
    os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'
    start_time = timeit.default_timer()

    # This takes 2-5 seconds to run
    # Unpersists graph from file
    with tf.gfile.FastGFile('retrained_graph.pb', 'rb') as f:
        graph_def = tf.GraphDef()
        graph_def.ParseFromString(f.read())
        tf.import_graph_def(graph_def, name='')

    print 'Took  seconds to unpersist the graph'.format(timeit.default_timer() - start_time)

def classify(image_data):
    print '********* Session Start *********'

    with tf.Session() as sess:
        start_time = timeit.default_timer()

        # Feed the image_data as input to the graph and get first prediction
        softmax_tensor = sess.graph.get_tensor_by_name('final_result:0')

        print 'Tensor', softmax_tensor

        print 'Took  seconds to feed data to graph'.format(timeit.default_timer() - start_time)

        start_time = timeit.default_timer()

        # This takes 2-5 seconds as well
        predictions = sess.run(softmax_tensor, 'Mul:0': image_data)

        print 'Took  seconds to perform prediction'.format(timeit.default_timer() - start_time)

        start_time = timeit.default_timer()

        # Sort to show labels of first prediction in order of confidence
        top_k = predictions[0].argsort()[-len(predictions[0]):][::-1]

        print 'Took  seconds to sort the predictions'.format(timeit.default_timer() - start_time)

        for node_id in top_k:
            human_string = label_lines[node_id]
            score = predictions[0][node_id]
            print('%s (score = %.5f)' % (human_string, score))

        print '********* Session Ended *********'

initialSetup()

while True:
    frame = grabVideoFeed()

    if frame is None:
        raise SystemError('Issue grabbing the frame')

    frame = cv2.resize(frame, (299, 299), interpolation=cv2.INTER_CUBIC)

    # adhere to TS graph input structure
    numpy_frame = np.asarray(frame)
    numpy_frame = cv2.normalize(numpy_frame.astype('float'), None, -0.5, .5, cv2.NORM_MINMAX)
    numpy_final = np.expand_dims(numpy_frame, axis=0)

    classify(numpy_final)

    cv2.imshow('Main', frame)

    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

camera.release()
cv2.destroyAllWindows()

编辑 1

在调试完我的代码后,我意识到创建会话是一项既耗费资源又耗费时间的操作。

在之前的代码中,在运行预测的基础上,为每个 OpenCV 提要创建了一个新会话。 将 OpenCV 操作封装在单个会话中提供了巨大的时间改进,但这仍然会在初始运行时增加大量开销;预测需要 2-3 秒。之后,预测大约需要 0.5 秒,这使得摄像头馈送仍然滞后。

import os
import cv2
import timeit
import numpy as np
import tensorflow as tf

camera = cv2.VideoCapture(0)

# Loads label file, strips off carriage return
label_lines = [line.rstrip() for line
               in tf.gfile.GFile('retrained_labels.txt')]

def grabVideoFeed():
    grabbed, frame = camera.read()
    return frame if grabbed else None

def initialSetup():
    os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'
    start_time = timeit.default_timer()

    # This takes 2-5 seconds to run
    # Unpersists graph from file
    with tf.gfile.FastGFile('retrained_graph.pb', 'rb') as f:
        graph_def = tf.GraphDef()
        graph_def.ParseFromString(f.read())
        tf.import_graph_def(graph_def, name='')

    print 'Took  seconds to unpersist the graph'.format(timeit.default_timer() - start_time)

initialSetup()

with tf.Session() as sess:
    start_time = timeit.default_timer()

    # Feed the image_data as input to the graph and get first prediction
    softmax_tensor = sess.graph.get_tensor_by_name('final_result:0')

    print 'Took  seconds to feed data to graph'.format(timeit.default_timer() - start_time)

    while True:
        frame = grabVideoFeed()

        if frame is None:
            raise SystemError('Issue grabbing the frame')

        frame = cv2.resize(frame, (299, 299), interpolation=cv2.INTER_CUBIC)

        cv2.imshow('Main', frame)

        # adhere to TS graph input structure
        numpy_frame = np.asarray(frame)
        numpy_frame = cv2.normalize(numpy_frame.astype('float'), None, -0.5, .5, cv2.NORM_MINMAX)
        numpy_final = np.expand_dims(numpy_frame, axis=0)

        start_time = timeit.default_timer()

        # This takes 2-5 seconds as well
        predictions = sess.run(softmax_tensor, 'Mul:0': numpy_final)

        print 'Took  seconds to perform prediction'.format(timeit.default_timer() - start_time)

        start_time = timeit.default_timer()

        # Sort to show labels of first prediction in order of confidence
        top_k = predictions[0].argsort()[-len(predictions[0]):][::-1]

        print 'Took  seconds to sort the predictions'.format(timeit.default_timer() - start_time)

        for node_id in top_k:
            human_string = label_lines[node_id]
            score = predictions[0][node_id]
            print('%s (score = %.5f)' % (human_string, score))

        print '********* Session Ended *********'

        if cv2.waitKey(1) & 0xFF == ord('q'):
            sess.close()
            break

camera.release()
cv2.destroyAllWindows()

编辑 2

在摆弄之后,我偶然发现了graph quantization 和graph transformation,这就是获得的结果。

原始图表:87.4MB

量化图:87.5MB

转换后的图:87.1MB

八位计算:22MB,但在使用时遇到this。

【问题讨论】:

见:medium.com/towards-data-science/… @Ruut 我在 6 月 23 日读过这篇文章;实际上,第二天就出来了。他使用多线程来加速 I/O 操作。我一直想在我的项目中尝试这个,但实际预测仍然需要 0.4-0.8 秒,我认为这是因为我的模型很大。我仍在寻找缩小尺寸的方法 您好,我正在尝试实现与您几乎相同的目标:通过 OpenCV Videocapture 进行实时 Tensorflow 分类。预测持续 0.4 秒。我安装了支持 GPU 的 Tensorflow。请问(1)你是否在CPU/GPU构建? (2)你有没有办法实现更快的速度?感谢您的建议。谢谢。 @KeithOYS 我没有使用 GPU。其背后的原因是因为我要把我的模型移植到手机上。 2:尝试运行我的量化图时,我仍然收到上面提到的错误。 I/O 当前在主线程上运行,因此请考虑将其移至单独的线程。 Example。这将有助于加快速度。 @KeithOYS 关于加速实际模型,请考虑为mobilenet 重新训练它 【参考方案1】:

我最近添加了使用 TensorFlow for Poets 训练较小 Mobilenet 模型的选项: https://github.com/tensorflow/tensorflow/blob/master/tensorflow/docs_src/tutorials/image_retraining.md#other-model-architectures

这可能有助于加快分类速度,但会牺牲一些准确性。

【讨论】:

谢谢你..我会试一试,让你知道..还有一件事,我在搞乱对象检测 api 并设法在我自己的数据集上本地训练它。既然您是 Google 工程师,我希望您能接受我的 approach 以及下次我可以做些什么来改进它。非常感谢您的帮助! 你做到了实时吗?即使在桌面上我也面临同样的问题 @HaraHaraMahadevaki 我已经有一段时间没有解决这个问题了。我建议在移动网络上重新训练它。 你能给我链接吗? 顺便说一下,尝试使用这种方法。它提供了相当大的性能提升pyimagesearch.com/2015/12/21/…

以上是关于TensorFlow 和 OpenCV 实时分类的主要内容,如果未能解决你的问题,请参考以下文章

OpenCV+OpenVINO实现人脸Landmarks实时检测

玩转谷歌物体识别API,用TensorFlow和OpenCV打造实时识别应用

基于Tensorflow + Opencv 实现CNN自定义图像分类

基于Tensorflow + Opencv 实现CNN自定义图像分类

MTCNN实时人脸检测网络详解与opencv+tensorflow代码演示

Qt+OpenCV联合开发(二十九)--实时人脸检测案例