Skip to content

Commit e5fe323

Browse files
authored
Add OpenVino Detector (blakeblackshear#3768)
* Initial work for adding OpenVino detector. Not functional * Load model and submit for inference. Sucessfully load model and initialize OpenVino engine with either CPU or GPU as device. Does not parse results for objects. * Detection working with ssdlite_mobilenetv2 FP16 model * Add OpenVIno support and model to docker image * Add documentation for OpenVino detector configuration * Adds support for ARM32/ARM64 and the Myriad X hardware - Use custom-built openvino wheel for all platforms - Add libusb build without udev for NCS2 support * Add documentation around Intel CPU requirements and NCS2 setup * Print all available output tensors * Update documentation for config parameters
1 parent 4523c9b commit e5fe323

File tree

9 files changed

+187
-3
lines changed

9 files changed

+187
-3
lines changed

Dockerfile

+54
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ ARG DEBIAN_FRONTEND=noninteractive
55

66
FROM debian:11 AS base
77

8+
FROM --platform=linux/amd64 debian:11 AS base_amd64
9+
810
FROM debian:11-slim AS slim-base
911

1012
FROM blakeblackshear/frigate-nginx:1.0.2 AS nginx
@@ -24,13 +26,62 @@ WORKDIR /rootfs/usr/local/go2rtc/bin
2426
RUN wget -qO go2rtc "https://github.com/AlexxIT/go2rtc/releases/download/v0.1-rc.3/go2rtc_linux_${TARGETARCH}" \
2527
&& chmod +x go2rtc
2628

29+
# Download and Convert OpenVino model
30+
FROM base_amd64 AS ov-converter
31+
ARG DEBIAN_FRONTEND
32+
33+
# Install OpenVino Runtime and Dev library
34+
COPY requirements-ov.txt /requirements-ov.txt
35+
RUN apt-get -qq update \
36+
&& apt-get -qq install -y wget python3 python3-distutils \
37+
&& wget -q https://bootstrap.pypa.io/get-pip.py -O get-pip.py \
38+
&& python3 get-pip.py "pip" \
39+
&& pip install -r /requirements-ov.txt
40+
41+
# Get OpenVino Model
42+
RUN mkdir /models \
43+
&& cd /models && omz_downloader --name ssdlite_mobilenet_v2 \
44+
&& cd /models && omz_converter --name ssdlite_mobilenet_v2 --precision FP16
45+
46+
47+
# libUSB - No Udev
48+
FROM wget as libusb-build
49+
ARG TARGETARCH
50+
ARG DEBIAN_FRONTEND
51+
52+
# Build libUSB without udev. Needed for Openvino NCS2 support
53+
WORKDIR /opt
54+
RUN apt-get update && apt-get install -y unzip build-essential automake libtool
55+
RUN wget -q https://github.com/libusb/libusb/archive/v1.0.25.zip -O v1.0.25.zip && \
56+
unzip v1.0.25.zip && cd libusb-1.0.25 && \
57+
./bootstrap.sh && \
58+
./configure --disable-udev --enable-shared && \
59+
make -j $(nproc --all)
60+
RUN apt-get update && \
61+
apt-get install -y --no-install-recommends libusb-1.0-0-dev && \
62+
rm -rf /var/lib/apt/lists/*
63+
WORKDIR /opt/libusb-1.0.25/libusb
64+
RUN /bin/mkdir -p '/usr/local/lib' && \
65+
/bin/bash ../libtool --mode=install /usr/bin/install -c libusb-1.0.la '/usr/local/lib' && \
66+
/bin/mkdir -p '/usr/local/include/libusb-1.0' && \
67+
/usr/bin/install -c -m 644 libusb.h '/usr/local/include/libusb-1.0' && \
68+
/bin/mkdir -p '/usr/local/lib/pkgconfig' && \
69+
cd /opt/libusb-1.0.25/ && \
70+
/usr/bin/install -c -m 644 libusb-1.0.pc '/usr/local/lib/pkgconfig' && \
71+
ldconfig
72+
73+
2774

2875
FROM wget AS models
2976

3077
# Get model and labels
3178
RUN wget -qO edgetpu_model.tflite https://github.com/google-coral/test_data/raw/release-frogfish/ssdlite_mobiledet_coco_qat_postprocess_edgetpu.tflite
3279
RUN wget -qO cpu_model.tflite https://github.com/google-coral/test_data/raw/release-frogfish/ssdlite_mobiledet_coco_qat_postprocess.tflite
3380
COPY labelmap.txt .
81+
# Copy OpenVino model
82+
COPY --from=ov-converter /models/public/ssdlite_mobilenet_v2/FP16 openvino-model
83+
RUN wget -q https://github.com/openvinotoolkit/open_model_zoo/raw/master/data/dataset_classes/coco_91cl_bkgr.txt -O openvino-model/coco_91cl_bkgr.txt
84+
3485

3586

3687
FROM wget AS s6-overlay
@@ -85,6 +136,7 @@ RUN pip3 wheel --wheel-dir=/wheels -r requirements-wheels.txt
85136
FROM scratch AS deps-rootfs
86137
COPY --from=nginx /usr/local/nginx/ /usr/local/nginx/
87138
COPY --from=go2rtc /rootfs/ /
139+
COPY --from=libusb-build /usr/local/lib /usr/local/lib
88140
COPY --from=s6-overlay /rootfs/ /
89141
COPY --from=models /rootfs/ /
90142
COPY docker/rootfs/ /
@@ -112,6 +164,8 @@ RUN --mount=type=bind,from=wheels,source=/wheels,target=/deps/wheels \
112164

113165
COPY --from=deps-rootfs / /
114166

167+
RUN ldconfig
168+
115169
EXPOSE 5000
116170
EXPOSE 1935
117171
EXPOSE 8554

docker/install_deps.sh

+2
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,9 @@ if [[ "${TARGETARCH}" == "amd64" ]]; then
5252
# Use debian testing repo only for hwaccel packages
5353
echo 'deb http://deb.debian.org/debian testing main non-free' >/etc/apt/sources.list.d/debian-testing.list
5454
apt-get -qq update
55+
# intel-opencl-icd specifically for GPU support in OpenVino
5556
apt-get -qq install --no-install-recommends --no-install-suggests -y \
57+
intel-opencl-icd \
5658
mesa-va-drivers libva-drm2 intel-media-va-driver-non-free i965-va-driver libmfx1 radeontop intel-gpu-tools
5759
rm -f /etc/apt/sources.list.d/debian-testing.list
5860
fi

docs/docs/configuration/detectors.md

+61
Original file line numberDiff line numberDiff line change
@@ -77,3 +77,64 @@ detectors:
7777
```
7878

7979
When using CPU detectors, you can add a CPU detector per camera. Adding more detectors than the number of cameras should not improve performance.
80+
81+
## OpenVINO
82+
83+
The OpenVINO detector allows Frigate to run an OpenVINO IR model on Intel CPU, GPU and VPU hardware.
84+
85+
### OpenVINO Devices
86+
87+
The OpenVINO detector supports the Intel-supplied device plugins and can specify one or more devices in the configuration. See OpenVINO's device naming conventions in the [Device Documentation](https://docs.openvino.ai/latest/openvino_docs_OV_UG_Working_with_devices.html) for more detail. Other supported devices could be `AUTO`, `CPU`, `GPU`, `MYRIAD`, etc.
88+
89+
```yaml
90+
detectors:
91+
ov_detector:
92+
type: openvino
93+
device: GPU
94+
```
95+
96+
OpenVINO is supported on 6th Gen Intel platforms (Skylake) and newer. A supported Intel platform is required to use the GPU device with OpenVINO. The `MYRIAD` device may be run on any platform, including Arm devices. For detailed system requirements, see [OpenVINO System Requirements](https://www.intel.com/content/www/us/en/developer/tools/openvino-toolkit/system-requirements.html)
97+
98+
#### Intel NCS2 VPU and Myriad X Setup
99+
100+
Intel produces a neural net inference accelleration chip called Myriad X. This chip was sold in their Neural Compute Stick 2 (NCS2) which has been discontinued. If intending to use the MYRIAD device for accelleration, additional setup is required to pass through the USB device. The host needs a udev rule installed to handle the NCS2 device.
101+
102+
```bash
103+
sudo usermod -a -G users "$(whoami)"
104+
cat <<EOF > 97-myriad-usbboot.rules
105+
SUBSYSTEM=="usb", ATTRS{idProduct}=="2485", ATTRS{idVendor}=="03e7", GROUP="users", MODE="0666", ENV{ID_MM_DEVICE_IGNORE}="1"
106+
SUBSYSTEM=="usb", ATTRS{idProduct}=="f63b", ATTRS{idVendor}=="03e7", GROUP="users", MODE="0666", ENV{ID_MM_DEVICE_IGNORE}="1"
107+
EOF
108+
sudo cp 97-myriad-usbboot.rules /etc/udev/rules.d/
109+
sudo udevadm control --reload-rules
110+
sudo udevadm trigger
111+
```
112+
113+
Additionally, the Frigate docker container needs to run with the following configuration:
114+
115+
```bash
116+
--device-cgroup-rule='c 189:\* rmw' -v /dev/bus/usb:/dev/bus/usb
117+
```
118+
or in your compose file:
119+
120+
```yml
121+
device_cgroup_rules:
122+
- 'c 189:* rmw'
123+
volumes:
124+
- /dev/bus/usb:/dev/bus/usb
125+
```
126+
127+
### OpenVINO Models
128+
129+
The included model for an OpenVINO detector comes from Intel's Open Model Zoo [SSDLite MobileNet V2](https://github.com/openvinotoolkit/open_model_zoo/tree/master/models/public/ssdlite_mobilenet_v2) and is converted to an FP16 precision IR model. Use the model configuration shown below when using the OpenVINO detector.
130+
131+
```yaml
132+
model:
133+
path: /openvino-model/ssdlite_mobilenet_v2.xml
134+
width: 300
135+
height: 300
136+
input_tensor: nhwc
137+
input_pixel_format: bgr
138+
labelmap_path: /openvino-model/coco_91cl_bkgr.txt
139+
140+
```

docs/docs/configuration/index.md

+3-3
Original file line numberDiff line numberDiff line change
@@ -76,9 +76,9 @@ detectors:
7676
# Required: name of the detector
7777
coral:
7878
# Required: type of the detector
79-
# Valid values are 'edgetpu' (requires device property below) and 'cpu'.
79+
# Valid values are 'edgetpu' (requires device property below) `openvino` (see Detectors documentation), and 'cpu'.
8080
type: edgetpu
81-
# Optional: device name as defined here: https://coral.ai/docs/edgetpu/multiple-edgetpu/#using-the-tensorflow-lite-python-api
81+
# Optional: Edgetpu or OpenVino device name
8282
device: usb
8383
# Optional: num_threads value passed to the tflite.Interpreter (default: shown below)
8484
# This value is only used for CPU types
@@ -104,7 +104,7 @@ model:
104104
input_pixel_format: rgb
105105
# Optional: Object detection model input tensor format
106106
# Valid values are nhwc or nchw (default: shown below)
107-
input_tensor: "nhwc"
107+
input_tensor: nhwc
108108
# Optional: Label name modifications. These are merged into the standard labelmap.
109109
labelmap:
110110
2: vehicle

frigate/config.py

+1
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ class Config:
5454

5555
class DetectorTypeEnum(str, Enum):
5656
edgetpu = "edgetpu"
57+
openvino = "openvino"
5758
cpu = "cpu"
5859

5960

frigate/detectors/openvino.py

+54
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
import logging
2+
import numpy as np
3+
import openvino.runtime as ov
4+
5+
from frigate.detectors.detection_api import DetectionApi
6+
7+
8+
logger = logging.getLogger(__name__)
9+
10+
11+
class OvDetector(DetectionApi):
12+
def __init__(self, det_device=None, model_config=None, num_threads=1):
13+
self.ov_core = ov.Core()
14+
self.ov_model = self.ov_core.read_model(model_config.path)
15+
16+
self.interpreter = self.ov_core.compile_model(
17+
model=self.ov_model, device_name=det_device
18+
)
19+
logger.info(f"Model Input Shape: {self.interpreter.input(0).shape}")
20+
self.output_indexes = 0
21+
while True:
22+
try:
23+
tensor_shape = self.interpreter.output(self.output_indexes).shape
24+
logger.info(f"Model Output-{self.output_indexes} Shape: {tensor_shape}")
25+
self.output_indexes += 1
26+
except:
27+
logger.info(f"Model has {self.output_indexes} Output Tensors")
28+
break
29+
30+
def detect_raw(self, tensor_input):
31+
32+
infer_request = self.interpreter.create_infer_request()
33+
infer_request.infer([tensor_input])
34+
35+
results = infer_request.get_output_tensor()
36+
37+
detections = np.zeros((20, 6), np.float32)
38+
i = 0
39+
for object_detected in results.data[0, 0, :]:
40+
if object_detected[0] != -1:
41+
logger.debug(object_detected)
42+
if object_detected[2] < 0.1 or i == 20:
43+
break
44+
detections[i] = [
45+
object_detected[1], # Label ID
46+
float(object_detected[2]), # Confidence
47+
object_detected[4], # y_min
48+
object_detected[3], # x_min
49+
object_detected[6], # y_max
50+
object_detected[5], # x_max
51+
]
52+
i += 1
53+
54+
return detections

frigate/object_detection.py

+5
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
from frigate.config import DetectorTypeEnum, InputTensorEnum
1414
from frigate.detectors.edgetpu_tfl import EdgeTpuTfl
15+
from frigate.detectors.openvino import OvDetector
1516
from frigate.detectors.cpu_tfl import CpuTfl
1617

1718
from frigate.util import EventsPerSecond, SharedMemoryFrameManager, listen, load_labels
@@ -57,6 +58,10 @@ def __init__(
5758
self.detect_api = EdgeTpuTfl(
5859
det_device=det_device, model_config=model_config
5960
)
61+
elif det_type == DetectorTypeEnum.openvino:
62+
self.detect_api = OvDetector(
63+
det_device=det_device, model_config=model_config
64+
)
6065
else:
6166
logger.warning(
6267
"CPU detectors are not recommended and should only be used for testing or for trial purposes."

requirements-ov.txt

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
numpy == 1.19.*
2+
openvino == 2022.*
3+
openvino-dev[tensorflow2] == 2022.*

requirements-wheels.txt

+4
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,7 @@ scipy == 1.8.*
1818
setproctitle == 1.2.*
1919
ws4py == 0.5.*
2020
zeroconf == 0.39.4
21+
# Openvino Library - Custom built with MYRIAD support
22+
openvino @ https://github.com/NateMeyer/openvino-wheels/releases/download/multi-arch_2022.2.0/openvino-2022.2.0-000-cp39-cp39-manylinux_2_31_x86_64.whl; platform_machine == 'x86_64'
23+
openvino @ https://github.com/NateMeyer/openvino-wheels/releases/download/multi-arch_2022.2.0/openvino-2022.2.0-000-cp39-cp39-linux_aarch64.whl; platform_machine == 'aarch64'
24+
openvino @ https://github.com/NateMeyer/openvino-wheels/releases/download/multi-arch_2022.2.0/openvino-2022.2.0-000-cp39-cp39-linux_armv7l.whl; platform_machine == 'armv7l'

0 commit comments

Comments
 (0)