Export Custom Vision model to Raspberry Pi 3: Issue and fix
Tags: customvision, raspberrypi3, docker
Published: 2020-04-24 17:19:52

---
title: Export Custom Vision model to Raspberry Pi 3: Issue and fix
published: true
description: Export Custom Vision model to Raspberry Pi 3
tags: customvision,raspberrypi3,docker
---

I play with [Custom Vision Service](https://www.customvision.ai/) export capability to docker file for RP3 today. There are several things I need to do to make it work, at least as of today.

I believe the issue will be addressed soon, so please refer to this information only when you have issue.

I don't explain what is Custom Vision or how to export model. Please refer to official document.

[Perform image classification at the edge with Custom Vision Service](https://docs.microsoft.com/en-us/azure/iot-edge/tutorial-deploy-custom-vision)

# Error 

When I build the image, I encounter following error at step 5/9.

```shell
Step 5/9 : RUN pip install flask pillow --index-url 'https://www.piwheels.org/simple'
 ---> Running in 686a1e4aa7bc
Looking in indexes: https://www.piwheels.org/simple
Collecting flask
  Downloading https://www.piwheels.org/simple/flask/Flask-1.1.2-py2.py3-none-any.whl (94 kB)
ERROR: Could not find a version that satisfies the requirement pillow (from versions: none)
ERROR: No matching distribution found for pillow
```

# Dockerfile

Generated Dockerfile is below. If this is different from yours, then your issue maybe different. Key points are:

- It's from python:3.7-slim
- It misses libgl1-mesa-glx module on the first apt install.

```dockerfile
FROM python:3.7-slim

RUN apt update && apt install -y libjpeg62-turbo libopenjp2-7 libtiff5 libatlas-base-dev
RUN pip install absl-py six protobuf wrapt gast astor termcolor keras_applications keras_preprocessing --no-deps
RUN pip install numpy==1.16 tensorflow==1.13.1 --extra-index-url 'https://www.piwheels.org/simple' --no-deps
RUN pip install flask pillow --index-url 'https://www.piwheels.org/simple'

# By default, we run manual image resizing to maintain parity with CVS webservice prediction results.
# If parity is not required, you can enable faster image resizing by uncommenting the following lines.
# RUN echo "deb http://security.debian.org/debian-security jessie/updates main" >> /etc/apt/sources.list & apt update -y
# RUN apt install -y  zlib1g-dev libjpeg-dev gcc libglib2.0-bin libsm6 libxext6 libxrender1 libjasper-dev libpng16-16 libopenexr23 libgstreamer1.0-0 libavcodec58 libavformat58 libswscale5 libqtgui4 libqt4-test libqtcore4
# RUN pip install opencv-python --extra-index-url 'https://www.piwheels.org/simple'

COPY app /app

# Expose the port
EXPOSE 80

# Set the working directory
WORKDIR /app

# Run the flask server for the endpoints
CMD python -u app.py
```

# Fix

I updated the Dockerfile as below.

```dockerfile
FROM balenalib/raspberrypi3-debian-python:3.7

RUN apt update && apt install -y libjpeg62-turbo libopenjp2-7 libtiff5 libatlas-base-dev libgl1-mesa-glx
RUN pip install absl-py six protobuf wrapt gast astor termcolor keras_applications keras_preprocessing --no-deps
RUN pip install numpy==1.16 tensorflow==1.13.1 --extra-index-url 'https://www.piwheels.org/simple' --no-deps
RUN pip install flask pillow --index-url 'https://www.piwheels.org/simple'

# By default, we run manual image resizing to maintain parity with CVS webservice prediction results.
# If parity is not required, you can enable faster image resizing by uncommenting the following lines.
# RUN echo "deb http://security.debian.org/debian-security jessie/updates main" >> /etc/apt/sources.list & apt update -y
# RUN apt install -y  zlib1g-dev libjpeg-dev gcc libglib2.0-bin libsm6 libxext6 libxrender1 libjasper-dev libpng16-16 libopenexr23 libgstreamer1.0-0 libavcodec58 libavformat58 libswscale5 libqtgui4 libqt4-test libqtcore4
# RUN pip install opencv-python --extra-index-url 'https://www.piwheels.org/simple'

COPY app /app

# Expose the port
EXPOSE 80

# Set the working directory
WORKDIR /app

# Run the flask server for the endpoints
CMD python -u app.py
```
# Reference

I use the same base image from [Custom Vision + Azure IoT Edge on a Raspberry Pi 3](https://github.com/Azure-Samples/Custom-vision-service-iot-edge-raspberry-pi/blob/master/modules/ImageClassifierService/arm32v7.Dockerfile).

I also added "libgl1-mesa-glx" module as there is [issue](https://github.com/Azure-Samples/Custom-vision-service-iot-edge-raspberry-pi/issues/65)

# Additional Info
README has section **Build ARM container on x64 machine** which says:

>Export "ARM" Dockerfile from customvision.ai. Then build it using docker buildx command.
```bash
docker buildx build --platform linux/arm/v7 -t <your image name> --load .
```
I am using Windows 10 Docker Desktop v19.03.8.

I tested by running the command by enabling experimental feature which works fine, but I also try **without** enable experimental feature and simply run **docker build** which works just fine. So I am not 100% sure if we need **buildx** right now.