предисловие
В прошлый раз мы установили среду разработки tensorflow, в которой удобнее запускать тестовую модель, но она все равно слишком велика для Raspberry Pi. Только 0,3 кадра в секунду не может удовлетворить потребности производственной среды в реальном времени.В этой статье мы развертываем TensorFlow Lite, специально разработанный для мобильных и встроенных устройств, и запускаем несколько моделей для проверки предельной частоты кадров на чистом Raspberry Pi.
TensorFlow Lite — это набор инструментов, которые помогают разработчикам запускать модели TensorFlow на мобильных, встроенных устройствах и устройствах IoT. Он поддерживает вывод машинного обучения на устройстве с малой задержкой и небольшим размером двоичного файла.
TensorFlow Lite включает в себя два основных компонента:
- Интерпретатор TensorFlow Lite, который запускает специально оптимизированные модели на различных типах оборудования, включая мобильные телефоны, встроенные устройства Linux и микроконтроллеры.
- Преобразователь TensorFlow Lite, который преобразует модели TensorFlow в эффективную форму для использования интерпретатором и вносит оптимизации для уменьшения размера двоичного файла и повышения производительности.
Преобразователь, как правило, выполняется на главном компьютере, в основном для статического преобразования графика расчета и создания файла .tflite после преобразования типа веса. Интерпретатор в основном работает на встроенных устройствах.Давайте сначала установим tensorflow lite на Raspberry Pi.
Установите TensorFlow Lite
1. Создайте виртуальную среду
python3 -m venv --system-site-packages ~/my_envs/tf_lite
source ~/my_envs/tf_lite/bin/activate
2. Установите версию 2.1.0
# 可以在官网里下载各个版本
# https://www.tensorflow.org/lite/guide/python
wget https://dl.google.com/coral/python/tflite_runtime-2.1.0.post1-cp37-cp37m-linux_armv7l.whl
pip install tflite_runtime-2.1.0.post1-cp37-cp37m-linux_armv7l.whl
3. Включить opencv
cd ~/my_envs/tf_lite/lib/python3.7/site-packages
ln -s /usr/local/lib/python3.7/site-packages/cv2 cv2
4. Установка завершена
import tflite_runtime.interpreter as tflite
tflite.Interpreter
Настройка камеры Raspberry Pi
1. Проверьте камеру
Сначала убедитесь, что кабель камеры подключен к интерфейсу CSI Raspberry Pi, и включите камеру в параметрах интерфейса -> опция камеры в raspi-config.
# 拍摄照片
raspistill -o demo.jpg
# 录制视频
raspivid -o vid.h264
Проверьте, нет ли снятых в директории фотографий demo.jpg и видеофайлов vid.h264, и убедитесь в отсутствии проблем с железом.
2. Используйте пикамеру для управления камерой
pip install picamera
Сфотографировать
import picamera
from time import sleep
camera = picamera.PiCamera()
try:
# 设置分辨率
camera.resolution = (1024, 768)
camera.brightness = 60
camera.start_preview()
# 增加文本
camera.annotate_text = 'Raspberry Pi'
sleep(3)
# 捕捉一张照片
camera.capture('image1.jpeg')
finally:
camera.stop_preview()
camera.close()
Tip:
Не забудьте закрыть камеру с помощью camera.close(), когда закончите ее использовать, или используйте предложение With для автоматического освобождения ресурсов. В противном случае вы получите сообщение об ошибке picamera.exc.PiCameraMMALError: Не удалось включить соединение: не хватает ресурсов, и вы можете только убить процесс python, чтобы принудительно освободить его.
записать видео
with picamera.PiCamera() as camera:
camera.resolution = (640, 480)
camera.start_preview()
camera.start_recording('video.h264')
camera.wait_recording(10)
camera.stop_recording()
3. Используйте opencv для управления камерой
import cv2
cap = cv2.VideoCapture(0)
cap.set(cv2.cv.CV_CAP_PROP_FRAME_WIDTH, 640)
cap.set(cv2.cv.CV_CAP_PROP_FRAME_HEIGHT, 480)
while True:
# 获取一帧图像
ret, frame = cap.read()
# 显示窗口
cv2.imshow("capture", frame)
# 按 q 退出
if(cv2.waitKey(1) == ord('q')):
cv2.destroyAllWindows()
break
Tip:
Если вызвать камеру CSI в OpenCV, данных не будет.Это потому, что модуль камеры в Raspberry Pi загружается в директорию /boot/ в виде прошивки, а не стандартного драйвера камеры V4L2, поэтому загружается После этого узел устройства /dev/video0 не будет найден. Мы можем решить проблему, добавив строку bcm2835-v4l2 в /etc/modules.
$sudo nano /etc/modules
Добавьте: bcm2835-v4l2, сохраните и закройте.
4. Запросить другие USB-видеоустройства
ls -ltrh /dev/video*
Используйте блокнот Jupyter
Jupyter Notebook — это веб-приложение с открытым исходным кодом, которое позволяет пользователям создавать и обмениваться документами, содержащими код, уравнения, визуализации и текст. Он широко используется на различных облачных платформах, поэтому для переносимости последующего кода мы сначала установим его здесь.
1. Установите юпитер
sudo apt install jupyter
2. Создайте файл конфигурации
Создайте файл конфигурации ноутбука Jupyter jupyter_notebook_config.py и введите в терминале:
jupyter notebook --generate-config
sudo nano ~/.jupyter/jupyter_notebook_config.py
Отредактируйте файл конфигурации jupyter_notebook_config.py.
c.NotebookApp.ip = '127.0.0.1'
c.NotebookApp.open_browser = True
Удалите эти два комментария и прослушайте локальный адрес порта 127.0.0.1.
3. Настройте виртуальную среду в jupyter.
pip install ipykernel
Используйте python -m ipykernel install --user --name имя виртуальной среды --display-name Имя, которое будет отображаться в Jupyter для привязки существующей виртуальной среды.
# 配置 pytorch 环境
python -m ipykernel install --user --name pytorch --display-name pytorch
# 配置 opencv 环境
python -m ipykernel install --user --name opencv --display-name opencv
# 配置 tensorflow 环境
python -m ipykernel install --user --name tensorflow --display-name tensorflow
# 配置 tensorflow 2.x 环境
python -m ipykernel install --user --name tf2 --display-name tf2
# 配置 tf_lite 环境
python -m ipykernel install --user --name tf_lite --display-name tf_lite
4. Запустите ноутбук и переключайтесь между различными средами.
jupyter notebook
В меню Сервис -> Изменить сервис -> перечислены все виртуальные среды.
Приложение Tensorflow Lite
1. Клонировать официальный пример
git clone https://github.com/tensorflow/examples --depth 1
2. Приложение для классификации изображений
Сначала установите пакет зависимостей, а затем загрузите файл модели MobileNet и файл классификационной метки в каталог tmp.
cd examples/lite/examples/image_classification/raspberry_pi
bash download.sh /tmp
3. Запустите вывод в блокноте
jupyter notebook
Мы создаем новый файл classify_picamera.ipynb и читаем в модели tflite,
labels = load_labels('/tmp/labels_mobilenet_quant_v1_224.txt')
interpreter = Interpreter('/tmp/mobilenet_v1_1.0_224_quant.tflite')
interpreter.allocate_tensors()
_, height, width, _ = interpreter.get_input_details()[0]['shape']
вызовитеterpreter.invoke(), чтобы сделать вывод,
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]]
Наконец, результаты классификации отображаются в окне opencv.
with picamera.PiCamera(resolution=(640, 480), framerate=30) as camera:
camera.start_preview()
try:
stream = io.BytesIO()
for _ in camera.capture_continuous(
stream, format='jpeg', use_video_port=True):
stream.seek(0)
image = Image.open(stream).convert('RGB').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]
camera.annotate_text = '%s %.2f\n%.1fms' % (labels[label_id], prob,
elapsed_ms)
# print(camera.annotate_text)
data = np.frombuffer(stream.getvalue(), dtype=np.uint8)
dst = cv2.imdecode(data, cv2.IMREAD_UNCHANGED)
cv2.imshow("img", dst)
stream.seek(0)
stream.truncate(0)
if(cv2.waitKey(1) == ord('q')):
cv2.destroyAllWindows()
break
finally:
camera.stop_preview()
print('end')
Скорость по-прежнему относительно высока, кадр в 130 мс может достигать 7-8 кадров в секунду, а точность также очень высока.Видно, что улучшение все еще очевидно. Это связано не только с компактностью MobileNet, но и с ускорением обтекаемой модели tflite, которая может достигать результатов в квазиреальном времени.
4. Приложение для обнаружения объектов
cd examples/lite/examples/object_detection/raspberry_pi
bash download.sh /tmp
Загрузите файл модели MobileNet ssd v2 и файл метки coco в каталог tmp.
5. Запустите вывод в блокноте
jupyter notebook
Мы создаем новый файл detect_picamera.ipynb и читаем в модели tflite,
labels = load_labels('/tmp/coco_labels.txt')
interpreter = Interpreter('/tmp/detect.tflite')
interpreter.allocate_tensors()
_, input_height, input_width, _ = interpreter.get_input_details()[0]['shape']
вызовитеterpreter.invoke(), чтобы сделать вывод,
def detect_objects(interpreter, image, threshold):
"""Returns a list of detection results, each a dictionary of object info."""
set_input_tensor(interpreter, image)
interpreter.invoke()
# Get all output details
boxes = get_output_tensor(interpreter, 0)
classes = get_output_tensor(interpreter, 1)
scores = get_output_tensor(interpreter, 2)
count = int(get_output_tensor(interpreter, 3))
results = []
for i in range(count):
if scores[i] >= threshold:
result = {
'bounding_box': boxes[i],
'class_id': classes[i],
'score': scores[i]
}
results.append(result)
return results
Получите цели аннотаций, преобразуйте поля аннотаций и метки классов
def annotate_objects(annotator, results, labels):
"""Draws the bounding box and label for each object in the results."""
for obj in results:
# Convert the bounding box figures from relative coordinates
# to absolute coordinates based on the original resolution
ymin, xmin, ymax, xmax = obj['bounding_box']
xmin = int(xmin * CAMERA_WIDTH)
xmax = int(xmax * CAMERA_WIDTH)
ymin = int(ymin * CAMERA_HEIGHT)
ymax = int(ymax * CAMERA_HEIGHT)
# Overlay the box, label, and score on the camera preview
annotator.bounding_box([xmin, ymin, xmax, ymax])
annotator.text([xmin, ymin],
'%s\n%.2f' % (labels[obj['class_id']], obj['score']))
Наконец, используйте opencv, чтобы объединить видеопоток и слой аннотаций и отобразить их в окне cv2.
with picamera.PiCamera(
resolution=(CAMERA_WIDTH, CAMERA_HEIGHT), framerate=30) as camera:
camera.start_preview()
try:
stream = io.BytesIO()
annotator = Annotator(camera)
for _ in camera.capture_continuous(
stream, format='jpeg', use_video_port=True):
stream.seek(0)
image = Image.open(stream).convert('RGB').resize(
(input_width, input_height), Image.ANTIALIAS)
start_time = time.monotonic()
results = detect_objects(interpreter, image, 0.4)
elapsed_ms = (time.monotonic() - start_time) * 1000
annotator.clear()
annotate_objects(annotator, results, labels)
annotator.text([5, 0], '%.1fms' % (elapsed_ms))
annotator.update()
data = np.frombuffer(stream.getvalue(), dtype=np.uint8)
dst = cv2.imdecode(data, cv2.IMREAD_UNCHANGED)
dst2 = cv2.cvtColor(np.asarray(annotator._buffer),cv2.COLOR_RGB2BGR)
dst = cv2.add(dst, dst2)
cv2.imshow("img", dst)
stream.seek(0)
stream.truncate(0)
if(cv2.waitKey(1) == ord('q')):
cv2.destroyAllWindows()
break
finally:
camera.stop_preview()
180-200 мс на кадр, около 5 кадров в секунду, нагрузка немного увеличилась, поэтому немного медленнее, чем задача классификации, которая должна была достичь предела 4-го поколения Raspberry Pi. Если вы хотите повысить производительность, вам необходимо использовать ресурсы расширения USB, такие как Intel Nerve Stick или Google Coral.
Установочный пакет и загрузка исходного кода
Для получения соответствующих документов и материалов в этом выпуске вы можете ответить на фоне официального аккаунта: «rpi06», чтобы получить ссылку для скачивания.
Следующее уведомление
Мы будем на tersorflow lite, сделать несколько интересных приложений, Быть в курсе...