相关资源汇总:

TensorFlow Lite 官网

TensorFlow Lite 官方指南

一、摄像头数据读取

直接采用OPENCV读取摄像头数据,参考NanoPI T3官方文档,由于这里我是先装的TensorFlowLite,其中需要升级numpy,这里遇到了一点问题,提前说明下:

该板子python中的包通过pip进行安装或卸载后,需要手动卸载掉当前的包才能升级或卸载:

1
2
3
4
5
6
#升级到最新
pip install packname
#卸载
pip uninstall packname
#查看当前包
pip list
  • 有时候可能需要利用sudo,或者是sudo -H
  • pip的,默认源是官方源,可以使用-i https://pypi.tuna.tsinghua.edu.cn/simple some-package命令来临时采用清华源(由于NanoPi T3中ubuntu16.04所使用的python最新版本较低,所以这里不推荐升级pip)

这里给出一个调用摄像头的demo:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import numpy as np
import cv2 as cv
cap = cv.VideoCapture(0)
if not cap.isOpened():
print("Cannot open camera")
exit()

cap.set(cv.CAP_PROP_FRAME_HEIGHT,240)
cap.set(cv.CAP_PROP_FRAME_WIDTH,320)

'''使用cv.VideoCapture.set设置摄像头分辨率是出现错误'''
while True:
# Capture frame-by-frame
ret, frame = cap.read()
# if frame is read correctly ret is True
if not ret:
print("Can't receive frame (stream end?). Exiting ...")
break
cv.imshow('frame', frame)
if cv.waitKey(1) == ord('q'):
break
# When everything done, release the capture
cap.release()
cv.destroyAllWindows()
  • 注意:调用set函数时,如果摄像头不支持此类参数会报类似于以下的错误:

    1
    2
    3
    4
    5
    6
    [ WARN:0] global /root/opencv/modules/videoio/src/cap_gstreamer.cpp (933) open OpenCV | GStreamer warning: Cannot query video position: status=0, value=-1, duration=-1
    [ WARN:0] global /root/opencv/modules/videoio/src/cap_gstreamer.cpp (1757) handleMessage OpenCV | GStreamer warning: Embedded video playback halted; module v4l2src0 reported: Internal data flow error.
    [ WARN:0] global /root/opencv/modules/videoio/src/cap_gstreamer.cpp (515) startPipeline OpenCV | GStreamer warning: unable to start pipeline
    [ WARN:0] global /root/opencv/modules/videoio/src/cap_gstreamer.cpp (1055) setProperty OpenCV | GStreamer warning: no pipeline
    Can't receive frame (stream end?). Exiting ...
    [ WARN:0] global /root/opencv/modules/videoio/src/cap_gstreamer.cpp (480) isPipelinePlaying OpenCV | GStreamer warning: GStreamer: pipeline have not been created

二、TensorFlowLite安装

参考官方,这里采用python来操作,官方给出了python入门,这里可以直接参考:

如果需要C/C++操作,可以参考在ARM64上构建TensorFlowLite,需要自己通过交叉编译工具链进行编译

通过下面的命令确定python版本和机器位数:

1
2
3
4
#python版本
python3 --version
#机器位数
uname -a

对于NanoPi T3来说是ARM64,python3.5,故采用以下命令直接安装:

1
sudo pip3 install https://dl.google.com/coral/python/tflite_runtime-2.1.0.post1-cp35-cp35m-linux_aarch64.whl
  • 期间可以能需要numpy版本更新,详见上文
  • 安装的是tflite_runtime,仅用于解释TensorFlow中的网络
  • 可以通过转化器将其他TensorFlow模型转换为TensorFlow Lite模型
  • 关于Interpreter的更多API可以参考在Python中加载并运行模型

安装好后可以通过官方针对树莓派的demo来进行:

但是树莓派上采用picamera调用摄像头,需要将上述代码中的picamera换为opencv部分,下述代码为修改后可行的图像分类demo:

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
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

import argparse
import io
import time
import numpy as np
import cv2 as cv

from PIL import Image
from tflite_runtime.interpreter import Interpreter

cap = cv.VideoCapture(0)
if not cap.isOpened():
print("Cannot open camera")
exit()

cap.set(cv.CAP_PROP_FRAME_HEIGHT,480)
cap.set(cv.CAP_PROP_FRAME_WIDTH,640)

cv.namedWindow("Video")
font = cv.FONT_HERSHEY_SIMPLEX
color = (0, 255, 0)#BGR

def load_labels(path):
with open(path, 'r') as f:
return {i: line.strip() for i, line in enumerate(f.readlines())}

def set_input_tensor(interpreter, image):
tensor_index = interpreter.get_input_details()[0]['index']
input_tensor = interpreter.tensor(tensor_index)()[0]
input_tensor[:, :] = image

def classify_image(interpreter, image, top_k=1):
"""Returns a sorted array of classification results."""
set_input_tensor(interpreter, image)
interpreter.invoke()
output_details = interpreter.get_output_details()[0]
output = np.squeeze(interpreter.get_tensor(output_details['index']))

# If the model is quantized (uint8 data), then dequantize the results
if output_details['dtype'] == np.uint8:
scale, zero_point = output_details['quantization']
output = scale * (output - zero_point)

ordered = np.argpartition(-output, top_k)
return [(i, output[i]) for i in ordered[:top_k]]

def main():
parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter)
parser.add_argument('--model', help='File path of .tflite file.', required=True)
parser.add_argument('--labels', help='File path of labels file.', required=True)
args = parser.parse_args()

labels = load_labels(args.labels)

interpreter = Interpreter(args.model)
interpreter.allocate_tensors()
_, height, width, _ = interpreter.get_input_details()[0]['shape']

while True:
# Capture frame-by-frame
ret, frame = cap.read()
# if frame is read correctly ret is True
if not ret:
print("Can't receive frame (stream end?). Exiting ...")
break

image = Image.fromarray(cv.cvtColor(frame,cv.COLOR_BGR2RGB))
image = image.resize((width, height),Image.ANTIALIAS)

start_time = time.time()
results = classify_image(interpreter, image)
elapsed_ms = (time.time() - start_time) * 1000
label_id, prob = results[0]

image = cv.cvtColor(np.array(image),cv.COLOR_RGB2BGR)
cv.putText(image, 'labels=%s'%(labels[label_id]), (0, 40), font, 0.8, color)
if prob >= 0.5:
cv.putText(image, 'prob=%.2f'%(prob), (0, 80), font, 0.8, (0, 0, 255)) #BGR
else:
cv.putText(image, 'prob=%.2f'%(prob), (0, 80), font, 0.8, color)
cv.putText(image, 'ms=%.1f'%(elapsed_ms), (0, 120), font, 0.8, color)
cv.imshow('frame', image)
if cv.waitKey(1) == ord('q'):
cap.release()
break

if __name__ == '__main__':
main()
cv.destroyAllWindows()