AK391 commited on
Commit
7734d5b
1 Parent(s): 924319f
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. Dockerfile +53 -0
  2. datasets/data_path/citypersons.train +0 -0
  3. datasets/data_path/eth.train +2056 -0
  4. deploy/ONNXRuntime/README.md +19 -0
  5. deploy/ONNXRuntime/onnx_inference.py +160 -0
  6. deploy/TensorRT/cpp/CMakeLists.txt +39 -0
  7. deploy/TensorRT/cpp/README.md +58 -0
  8. deploy/TensorRT/cpp/include/BYTETracker.h +49 -0
  9. deploy/TensorRT/cpp/include/STrack.h +50 -0
  10. deploy/TensorRT/cpp/include/dataType.h +36 -0
  11. deploy/TensorRT/cpp/include/kalmanFilter.h +31 -0
  12. deploy/TensorRT/cpp/include/lapjv.h +63 -0
  13. deploy/TensorRT/cpp/include/logging.h +503 -0
  14. deploy/TensorRT/cpp/src/BYTETracker.cpp +241 -0
  15. deploy/TensorRT/cpp/src/STrack.cpp +192 -0
  16. deploy/TensorRT/cpp/src/bytetrack.cpp +506 -0
  17. deploy/TensorRT/cpp/src/kalmanFilter.cpp +152 -0
  18. deploy/TensorRT/cpp/src/lapjv.cpp +343 -0
  19. deploy/TensorRT/cpp/src/utils.cpp +429 -0
  20. deploy/TensorRT/python/README.md +22 -0
  21. deploy/ncnn/cpp/CMakeLists.txt +84 -0
  22. deploy/ncnn/cpp/README.md +103 -0
  23. deploy/ncnn/cpp/include/BYTETracker.h +49 -0
  24. deploy/ncnn/cpp/include/STrack.h +50 -0
  25. deploy/ncnn/cpp/include/dataType.h +36 -0
  26. deploy/ncnn/cpp/include/kalmanFilter.h +31 -0
  27. deploy/ncnn/cpp/include/lapjv.h +63 -0
  28. deploy/ncnn/cpp/src/BYTETracker.cpp +241 -0
  29. deploy/ncnn/cpp/src/STrack.cpp +192 -0
  30. deploy/ncnn/cpp/src/bytetrack.cpp +396 -0
  31. deploy/ncnn/cpp/src/kalmanFilter.cpp +152 -0
  32. deploy/ncnn/cpp/src/lapjv.cpp +343 -0
  33. deploy/ncnn/cpp/src/utils.cpp +429 -0
  34. exps/default/nano.py +39 -0
  35. exps/default/yolov3.py +89 -0
  36. exps/default/yolox_l.py +15 -0
  37. exps/default/yolox_m.py +15 -0
  38. exps/default/yolox_s.py +15 -0
  39. exps/default/yolox_tiny.py +19 -0
  40. exps/default/yolox_x.py +15 -0
  41. exps/example/mot/yolox_l_mix_det.py +138 -0
  42. exps/example/mot/yolox_m_mix_det.py +138 -0
  43. exps/example/mot/yolox_s_mix_det.py +138 -0
  44. exps/example/mot/yolox_x_ablation.py +138 -0
  45. exps/example/mot/yolox_x_ch.py +138 -0
  46. exps/example/mot/yolox_x_mix_det.py +138 -0
  47. exps/example/mot/yolox_x_mix_mot20_ch.py +139 -0
  48. exps/example/mot/yolox_x_mot17_half.py +138 -0
  49. requirements.txt +22 -0
  50. setup.cfg +18 -0
Dockerfile ADDED
@@ -0,0 +1,53 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ FROM nvcr.io/nvidia/tensorrt:21.09-py3
2
+
3
+ ENV DEBIAN_FRONTEND=noninteractive
4
+ ARG USERNAME=user
5
+ ARG WORKDIR=/workspace/ByteTrack
6
+
7
+ RUN apt-get update && apt-get install -y \
8
+ automake autoconf libpng-dev nano python3-pip \
9
+ curl zip unzip libtool swig zlib1g-dev pkg-config \
10
+ python3-mock libpython3-dev libpython3-all-dev \
11
+ g++ gcc cmake make pciutils cpio gosu wget \
12
+ libgtk-3-dev libxtst-dev sudo apt-transport-https \
13
+ build-essential gnupg git xz-utils vim \
14
+ libva-drm2 libva-x11-2 vainfo libva-wayland2 libva-glx2 \
15
+ libva-dev libdrm-dev xorg xorg-dev protobuf-compiler \
16
+ openbox libx11-dev libgl1-mesa-glx libgl1-mesa-dev \
17
+ libtbb2 libtbb-dev libopenblas-dev libopenmpi-dev \
18
+ && sed -i 's/# set linenumbers/set linenumbers/g' /etc/nanorc \
19
+ && apt clean \
20
+ && rm -rf /var/lib/apt/lists/*
21
+
22
+ RUN git clone https://github.com/ifzhang/ByteTrack \
23
+ && cd ByteTrack \
24
+ && git checkout 3434c5e8bc6a5ae8ad530528ba8d9a431967f237 \
25
+ && mkdir -p YOLOX_outputs/yolox_x_mix_det/track_vis \
26
+ && sed -i 's/torch>=1.7/torch==1.9.1+cu111/g' requirements.txt \
27
+ && sed -i 's/torchvision==0.10.0/torchvision==0.10.1+cu111/g' requirements.txt \
28
+ && sed -i "s/'cuda'/0/g" tools/demo_track.py \
29
+ && pip3 install pip --upgrade \
30
+ && pip3 install -r requirements.txt -f https://download.pytorch.org/whl/torch_stable.html \
31
+ && python3 setup.py develop \
32
+ && pip3 install cython \
33
+ && pip3 install 'git+https://github.com/cocodataset/cocoapi.git#subdirectory=PythonAPI' \
34
+ && pip3 install cython_bbox gdown \
35
+ && ldconfig \
36
+ && pip cache purge
37
+
38
+ RUN git clone https://github.com/NVIDIA-AI-IOT/torch2trt \
39
+ && cd torch2trt \
40
+ && git checkout 0400b38123d01cc845364870bdf0a0044ea2b3b2 \
41
+ # https://github.com/NVIDIA-AI-IOT/torch2trt/issues/619
42
+ && wget https://github.com/NVIDIA-AI-IOT/torch2trt/commit/8b9fb46ddbe99c2ddf3f1ed148c97435cbeb8fd3.patch \
43
+ && git apply 8b9fb46ddbe99c2ddf3f1ed148c97435cbeb8fd3.patch \
44
+ && python3 setup.py install
45
+
46
+ RUN echo "root:root" | chpasswd \
47
+ && adduser --disabled-password --gecos "" "${USERNAME}" \
48
+ && echo "${USERNAME}:${USERNAME}" | chpasswd \
49
+ && echo "%${USERNAME} ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers.d/${USERNAME} \
50
+ && chmod 0440 /etc/sudoers.d/${USERNAME}
51
+ USER ${USERNAME}
52
+ RUN sudo chown -R ${USERNAME}:${USERNAME} ${WORKDIR}
53
+ WORKDIR ${WORKDIR}
datasets/data_path/citypersons.train ADDED
The diff for this file is too large to render. See raw diff
 
datasets/data_path/eth.train ADDED
@@ -0,0 +1,2056 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ETHZ/eth01/images/image_00000001_0.png
2
+ ETHZ/eth01/images/image_00000002_0.png
3
+ ETHZ/eth01/images/image_00000003_0.png
4
+ ETHZ/eth01/images/image_00000004_0.png
5
+ ETHZ/eth01/images/image_00000005_0.png
6
+ ETHZ/eth01/images/image_00000006_0.png
7
+ ETHZ/eth01/images/image_00000007_0.png
8
+ ETHZ/eth01/images/image_00000008_0.png
9
+ ETHZ/eth01/images/image_00000009_0.png
10
+ ETHZ/eth01/images/image_00000010_0.png
11
+ ETHZ/eth01/images/image_00000011_0.png
12
+ ETHZ/eth01/images/image_00000012_0.png
13
+ ETHZ/eth01/images/image_00000013_0.png
14
+ ETHZ/eth01/images/image_00000014_0.png
15
+ ETHZ/eth01/images/image_00000015_0.png
16
+ ETHZ/eth01/images/image_00000016_0.png
17
+ ETHZ/eth01/images/image_00000017_0.png
18
+ ETHZ/eth01/images/image_00000018_0.png
19
+ ETHZ/eth01/images/image_00000019_0.png
20
+ ETHZ/eth01/images/image_00000020_0.png
21
+ ETHZ/eth01/images/image_00000021_0.png
22
+ ETHZ/eth01/images/image_00000022_0.png
23
+ ETHZ/eth01/images/image_00000023_0.png
24
+ ETHZ/eth01/images/image_00000024_0.png
25
+ ETHZ/eth01/images/image_00000025_0.png
26
+ ETHZ/eth01/images/image_00000026_0.png
27
+ ETHZ/eth01/images/image_00000027_0.png
28
+ ETHZ/eth01/images/image_00000028_0.png
29
+ ETHZ/eth01/images/image_00000029_0.png
30
+ ETHZ/eth01/images/image_00000030_0.png
31
+ ETHZ/eth01/images/image_00000031_0.png
32
+ ETHZ/eth01/images/image_00000032_0.png
33
+ ETHZ/eth01/images/image_00000033_0.png
34
+ ETHZ/eth01/images/image_00000034_0.png
35
+ ETHZ/eth01/images/image_00000035_0.png
36
+ ETHZ/eth01/images/image_00000036_0.png
37
+ ETHZ/eth01/images/image_00000037_0.png
38
+ ETHZ/eth01/images/image_00000038_0.png
39
+ ETHZ/eth01/images/image_00000039_0.png
40
+ ETHZ/eth01/images/image_00000040_0.png
41
+ ETHZ/eth01/images/image_00000041_0.png
42
+ ETHZ/eth01/images/image_00000042_0.png
43
+ ETHZ/eth01/images/image_00000043_0.png
44
+ ETHZ/eth01/images/image_00000044_0.png
45
+ ETHZ/eth01/images/image_00000045_0.png
46
+ ETHZ/eth01/images/image_00000046_0.png
47
+ ETHZ/eth01/images/image_00000047_0.png
48
+ ETHZ/eth01/images/image_00000048_0.png
49
+ ETHZ/eth01/images/image_00000049_0.png
50
+ ETHZ/eth01/images/image_00000050_0.png
51
+ ETHZ/eth01/images/image_00000051_0.png
52
+ ETHZ/eth01/images/image_00000052_0.png
53
+ ETHZ/eth01/images/image_00000053_0.png
54
+ ETHZ/eth01/images/image_00000054_0.png
55
+ ETHZ/eth01/images/image_00000055_0.png
56
+ ETHZ/eth01/images/image_00000056_0.png
57
+ ETHZ/eth01/images/image_00000057_0.png
58
+ ETHZ/eth01/images/image_00000058_0.png
59
+ ETHZ/eth01/images/image_00000059_0.png
60
+ ETHZ/eth01/images/image_00000060_0.png
61
+ ETHZ/eth01/images/image_00000061_0.png
62
+ ETHZ/eth01/images/image_00000062_0.png
63
+ ETHZ/eth01/images/image_00000063_0.png
64
+ ETHZ/eth01/images/image_00000064_0.png
65
+ ETHZ/eth01/images/image_00000065_0.png
66
+ ETHZ/eth01/images/image_00000066_0.png
67
+ ETHZ/eth01/images/image_00000067_0.png
68
+ ETHZ/eth01/images/image_00000068_0.png
69
+ ETHZ/eth01/images/image_00000069_0.png
70
+ ETHZ/eth01/images/image_00000070_0.png
71
+ ETHZ/eth01/images/image_00000071_0.png
72
+ ETHZ/eth01/images/image_00000072_0.png
73
+ ETHZ/eth01/images/image_00000073_0.png
74
+ ETHZ/eth01/images/image_00000074_0.png
75
+ ETHZ/eth01/images/image_00000075_0.png
76
+ ETHZ/eth01/images/image_00000076_0.png
77
+ ETHZ/eth01/images/image_00000077_0.png
78
+ ETHZ/eth01/images/image_00000078_0.png
79
+ ETHZ/eth01/images/image_00000079_0.png
80
+ ETHZ/eth01/images/image_00000080_0.png
81
+ ETHZ/eth01/images/image_00000081_0.png
82
+ ETHZ/eth01/images/image_00000082_0.png
83
+ ETHZ/eth01/images/image_00000083_0.png
84
+ ETHZ/eth01/images/image_00000084_0.png
85
+ ETHZ/eth01/images/image_00000085_0.png
86
+ ETHZ/eth01/images/image_00000086_0.png
87
+ ETHZ/eth01/images/image_00000087_0.png
88
+ ETHZ/eth01/images/image_00000088_0.png
89
+ ETHZ/eth01/images/image_00000089_0.png
90
+ ETHZ/eth01/images/image_00000090_0.png
91
+ ETHZ/eth01/images/image_00000091_0.png
92
+ ETHZ/eth01/images/image_00000092_0.png
93
+ ETHZ/eth01/images/image_00000093_0.png
94
+ ETHZ/eth01/images/image_00000094_0.png
95
+ ETHZ/eth01/images/image_00000095_0.png
96
+ ETHZ/eth01/images/image_00000096_0.png
97
+ ETHZ/eth01/images/image_00000097_0.png
98
+ ETHZ/eth01/images/image_00000098_0.png
99
+ ETHZ/eth01/images/image_00000099_0.png
100
+ ETHZ/eth01/images/image_00000100_0.png
101
+ ETHZ/eth01/images/image_00000101_0.png
102
+ ETHZ/eth01/images/image_00000102_0.png
103
+ ETHZ/eth01/images/image_00000103_0.png
104
+ ETHZ/eth01/images/image_00000104_0.png
105
+ ETHZ/eth01/images/image_00000105_0.png
106
+ ETHZ/eth01/images/image_00000106_0.png
107
+ ETHZ/eth01/images/image_00000107_0.png
108
+ ETHZ/eth01/images/image_00000108_0.png
109
+ ETHZ/eth01/images/image_00000109_0.png
110
+ ETHZ/eth01/images/image_00000110_0.png
111
+ ETHZ/eth01/images/image_00000111_0.png
112
+ ETHZ/eth01/images/image_00000112_0.png
113
+ ETHZ/eth01/images/image_00000113_0.png
114
+ ETHZ/eth01/images/image_00000114_0.png
115
+ ETHZ/eth01/images/image_00000115_0.png
116
+ ETHZ/eth01/images/image_00000116_0.png
117
+ ETHZ/eth01/images/image_00000117_0.png
118
+ ETHZ/eth01/images/image_00000118_0.png
119
+ ETHZ/eth01/images/image_00000119_0.png
120
+ ETHZ/eth01/images/image_00000120_0.png
121
+ ETHZ/eth01/images/image_00000121_0.png
122
+ ETHZ/eth01/images/image_00000122_0.png
123
+ ETHZ/eth01/images/image_00000123_0.png
124
+ ETHZ/eth01/images/image_00000124_0.png
125
+ ETHZ/eth01/images/image_00000125_0.png
126
+ ETHZ/eth01/images/image_00000126_0.png
127
+ ETHZ/eth01/images/image_00000127_0.png
128
+ ETHZ/eth01/images/image_00000128_0.png
129
+ ETHZ/eth01/images/image_00000129_0.png
130
+ ETHZ/eth01/images/image_00000130_0.png
131
+ ETHZ/eth01/images/image_00000131_0.png
132
+ ETHZ/eth01/images/image_00000132_0.png
133
+ ETHZ/eth01/images/image_00000133_0.png
134
+ ETHZ/eth01/images/image_00000134_0.png
135
+ ETHZ/eth01/images/image_00000135_0.png
136
+ ETHZ/eth01/images/image_00000136_0.png
137
+ ETHZ/eth01/images/image_00000137_0.png
138
+ ETHZ/eth01/images/image_00000138_0.png
139
+ ETHZ/eth01/images/image_00000139_0.png
140
+ ETHZ/eth01/images/image_00000140_0.png
141
+ ETHZ/eth01/images/image_00000141_0.png
142
+ ETHZ/eth01/images/image_00000142_0.png
143
+ ETHZ/eth01/images/image_00000143_0.png
144
+ ETHZ/eth01/images/image_00000144_0.png
145
+ ETHZ/eth01/images/image_00000145_0.png
146
+ ETHZ/eth01/images/image_00000146_0.png
147
+ ETHZ/eth01/images/image_00000147_0.png
148
+ ETHZ/eth01/images/image_00000148_0.png
149
+ ETHZ/eth01/images/image_00000149_0.png
150
+ ETHZ/eth01/images/image_00000150_0.png
151
+ ETHZ/eth01/images/image_00000151_0.png
152
+ ETHZ/eth01/images/image_00000152_0.png
153
+ ETHZ/eth01/images/image_00000153_0.png
154
+ ETHZ/eth01/images/image_00000154_0.png
155
+ ETHZ/eth01/images/image_00000155_0.png
156
+ ETHZ/eth01/images/image_00000156_0.png
157
+ ETHZ/eth01/images/image_00000157_0.png
158
+ ETHZ/eth01/images/image_00000158_0.png
159
+ ETHZ/eth01/images/image_00000159_0.png
160
+ ETHZ/eth01/images/image_00000160_0.png
161
+ ETHZ/eth01/images/image_00000161_0.png
162
+ ETHZ/eth01/images/image_00000162_0.png
163
+ ETHZ/eth01/images/image_00000163_0.png
164
+ ETHZ/eth01/images/image_00000164_0.png
165
+ ETHZ/eth01/images/image_00000165_0.png
166
+ ETHZ/eth01/images/image_00000166_0.png
167
+ ETHZ/eth01/images/image_00000167_0.png
168
+ ETHZ/eth01/images/image_00000168_0.png
169
+ ETHZ/eth01/images/image_00000169_0.png
170
+ ETHZ/eth01/images/image_00000170_0.png
171
+ ETHZ/eth01/images/image_00000171_0.png
172
+ ETHZ/eth01/images/image_00000172_0.png
173
+ ETHZ/eth01/images/image_00000173_0.png
174
+ ETHZ/eth01/images/image_00000174_0.png
175
+ ETHZ/eth01/images/image_00000175_0.png
176
+ ETHZ/eth01/images/image_00000176_0.png
177
+ ETHZ/eth01/images/image_00000177_0.png
178
+ ETHZ/eth01/images/image_00000178_0.png
179
+ ETHZ/eth01/images/image_00000179_0.png
180
+ ETHZ/eth01/images/image_00000180_0.png
181
+ ETHZ/eth01/images/image_00000181_0.png
182
+ ETHZ/eth01/images/image_00000182_0.png
183
+ ETHZ/eth01/images/image_00000183_0.png
184
+ ETHZ/eth01/images/image_00000184_0.png
185
+ ETHZ/eth01/images/image_00000185_0.png
186
+ ETHZ/eth01/images/image_00000186_0.png
187
+ ETHZ/eth01/images/image_00000187_0.png
188
+ ETHZ/eth01/images/image_00000188_0.png
189
+ ETHZ/eth01/images/image_00000189_0.png
190
+ ETHZ/eth01/images/image_00000190_0.png
191
+ ETHZ/eth01/images/image_00000191_0.png
192
+ ETHZ/eth01/images/image_00000192_0.png
193
+ ETHZ/eth01/images/image_00000193_0.png
194
+ ETHZ/eth01/images/image_00000194_0.png
195
+ ETHZ/eth01/images/image_00000195_0.png
196
+ ETHZ/eth01/images/image_00000196_0.png
197
+ ETHZ/eth01/images/image_00000197_0.png
198
+ ETHZ/eth01/images/image_00000198_0.png
199
+ ETHZ/eth01/images/image_00000199_0.png
200
+ ETHZ/eth01/images/image_00000200_0.png
201
+ ETHZ/eth01/images/image_00000201_0.png
202
+ ETHZ/eth01/images/image_00000202_0.png
203
+ ETHZ/eth01/images/image_00000203_0.png
204
+ ETHZ/eth01/images/image_00000204_0.png
205
+ ETHZ/eth01/images/image_00000205_0.png
206
+ ETHZ/eth01/images/image_00000206_0.png
207
+ ETHZ/eth01/images/image_00000207_0.png
208
+ ETHZ/eth01/images/image_00000208_0.png
209
+ ETHZ/eth01/images/image_00000209_0.png
210
+ ETHZ/eth01/images/image_00000210_0.png
211
+ ETHZ/eth01/images/image_00000211_0.png
212
+ ETHZ/eth01/images/image_00000212_0.png
213
+ ETHZ/eth01/images/image_00000213_0.png
214
+ ETHZ/eth01/images/image_00000214_0.png
215
+ ETHZ/eth01/images/image_00000215_0.png
216
+ ETHZ/eth01/images/image_00000216_0.png
217
+ ETHZ/eth01/images/image_00000217_0.png
218
+ ETHZ/eth01/images/image_00000218_0.png
219
+ ETHZ/eth01/images/image_00000219_0.png
220
+ ETHZ/eth01/images/image_00000220_0.png
221
+ ETHZ/eth01/images/image_00000221_0.png
222
+ ETHZ/eth01/images/image_00000222_0.png
223
+ ETHZ/eth01/images/image_00000223_0.png
224
+ ETHZ/eth01/images/image_00000224_0.png
225
+ ETHZ/eth01/images/image_00000225_0.png
226
+ ETHZ/eth01/images/image_00000226_0.png
227
+ ETHZ/eth01/images/image_00000227_0.png
228
+ ETHZ/eth01/images/image_00000228_0.png
229
+ ETHZ/eth01/images/image_00000229_0.png
230
+ ETHZ/eth01/images/image_00000230_0.png
231
+ ETHZ/eth01/images/image_00000231_0.png
232
+ ETHZ/eth01/images/image_00000232_0.png
233
+ ETHZ/eth01/images/image_00000233_0.png
234
+ ETHZ/eth01/images/image_00000234_0.png
235
+ ETHZ/eth01/images/image_00000235_0.png
236
+ ETHZ/eth01/images/image_00000236_0.png
237
+ ETHZ/eth01/images/image_00000237_0.png
238
+ ETHZ/eth01/images/image_00000238_0.png
239
+ ETHZ/eth01/images/image_00000239_0.png
240
+ ETHZ/eth01/images/image_00000240_0.png
241
+ ETHZ/eth01/images/image_00000241_0.png
242
+ ETHZ/eth01/images/image_00000242_0.png
243
+ ETHZ/eth01/images/image_00000243_0.png
244
+ ETHZ/eth01/images/image_00000244_0.png
245
+ ETHZ/eth01/images/image_00000245_0.png
246
+ ETHZ/eth01/images/image_00000246_0.png
247
+ ETHZ/eth01/images/image_00000247_0.png
248
+ ETHZ/eth01/images/image_00000248_0.png
249
+ ETHZ/eth01/images/image_00000249_0.png
250
+ ETHZ/eth01/images/image_00000250_0.png
251
+ ETHZ/eth01/images/image_00000251_0.png
252
+ ETHZ/eth01/images/image_00000252_0.png
253
+ ETHZ/eth01/images/image_00000253_0.png
254
+ ETHZ/eth01/images/image_00000254_0.png
255
+ ETHZ/eth01/images/image_00000255_0.png
256
+ ETHZ/eth01/images/image_00000256_0.png
257
+ ETHZ/eth01/images/image_00000257_0.png
258
+ ETHZ/eth01/images/image_00000258_0.png
259
+ ETHZ/eth01/images/image_00000259_0.png
260
+ ETHZ/eth01/images/image_00000260_0.png
261
+ ETHZ/eth01/images/image_00000261_0.png
262
+ ETHZ/eth01/images/image_00000262_0.png
263
+ ETHZ/eth01/images/image_00000263_0.png
264
+ ETHZ/eth01/images/image_00000264_0.png
265
+ ETHZ/eth01/images/image_00000265_0.png
266
+ ETHZ/eth01/images/image_00000266_0.png
267
+ ETHZ/eth01/images/image_00000267_0.png
268
+ ETHZ/eth01/images/image_00000268_0.png
269
+ ETHZ/eth01/images/image_00000269_0.png
270
+ ETHZ/eth01/images/image_00000270_0.png
271
+ ETHZ/eth01/images/image_00000271_0.png
272
+ ETHZ/eth01/images/image_00000272_0.png
273
+ ETHZ/eth01/images/image_00000273_0.png
274
+ ETHZ/eth01/images/image_00000274_0.png
275
+ ETHZ/eth01/images/image_00000275_0.png
276
+ ETHZ/eth01/images/image_00000276_0.png
277
+ ETHZ/eth01/images/image_00000277_0.png
278
+ ETHZ/eth01/images/image_00000278_0.png
279
+ ETHZ/eth01/images/image_00000279_0.png
280
+ ETHZ/eth01/images/image_00000280_0.png
281
+ ETHZ/eth01/images/image_00000281_0.png
282
+ ETHZ/eth01/images/image_00000282_0.png
283
+ ETHZ/eth01/images/image_00000283_0.png
284
+ ETHZ/eth01/images/image_00000284_0.png
285
+ ETHZ/eth01/images/image_00000285_0.png
286
+ ETHZ/eth01/images/image_00000286_0.png
287
+ ETHZ/eth01/images/image_00000287_0.png
288
+ ETHZ/eth01/images/image_00000288_0.png
289
+ ETHZ/eth01/images/image_00000289_0.png
290
+ ETHZ/eth01/images/image_00000290_0.png
291
+ ETHZ/eth01/images/image_00000291_0.png
292
+ ETHZ/eth01/images/image_00000292_0.png
293
+ ETHZ/eth01/images/image_00000293_0.png
294
+ ETHZ/eth01/images/image_00000294_0.png
295
+ ETHZ/eth01/images/image_00000295_0.png
296
+ ETHZ/eth01/images/image_00000296_0.png
297
+ ETHZ/eth01/images/image_00000297_0.png
298
+ ETHZ/eth01/images/image_00000298_0.png
299
+ ETHZ/eth01/images/image_00000299_0.png
300
+ ETHZ/eth01/images/image_00000300_0.png
301
+ ETHZ/eth01/images/image_00000301_0.png
302
+ ETHZ/eth01/images/image_00000302_0.png
303
+ ETHZ/eth01/images/image_00000303_0.png
304
+ ETHZ/eth01/images/image_00000304_0.png
305
+ ETHZ/eth01/images/image_00000305_0.png
306
+ ETHZ/eth01/images/image_00000306_0.png
307
+ ETHZ/eth01/images/image_00000307_0.png
308
+ ETHZ/eth01/images/image_00000308_0.png
309
+ ETHZ/eth01/images/image_00000309_0.png
310
+ ETHZ/eth01/images/image_00000310_0.png
311
+ ETHZ/eth01/images/image_00000311_0.png
312
+ ETHZ/eth01/images/image_00000312_0.png
313
+ ETHZ/eth01/images/image_00000313_0.png
314
+ ETHZ/eth01/images/image_00000314_0.png
315
+ ETHZ/eth01/images/image_00000315_0.png
316
+ ETHZ/eth01/images/image_00000316_0.png
317
+ ETHZ/eth01/images/image_00000317_0.png
318
+ ETHZ/eth01/images/image_00000318_0.png
319
+ ETHZ/eth01/images/image_00000319_0.png
320
+ ETHZ/eth01/images/image_00000320_0.png
321
+ ETHZ/eth01/images/image_00000321_0.png
322
+ ETHZ/eth01/images/image_00000322_0.png
323
+ ETHZ/eth01/images/image_00000323_0.png
324
+ ETHZ/eth01/images/image_00000324_0.png
325
+ ETHZ/eth01/images/image_00000325_0.png
326
+ ETHZ/eth01/images/image_00000326_0.png
327
+ ETHZ/eth01/images/image_00000327_0.png
328
+ ETHZ/eth01/images/image_00000328_0.png
329
+ ETHZ/eth01/images/image_00000329_0.png
330
+ ETHZ/eth01/images/image_00000330_0.png
331
+ ETHZ/eth01/images/image_00000331_0.png
332
+ ETHZ/eth01/images/image_00000332_0.png
333
+ ETHZ/eth01/images/image_00000333_0.png
334
+ ETHZ/eth01/images/image_00000334_0.png
335
+ ETHZ/eth01/images/image_00000335_0.png
336
+ ETHZ/eth01/images/image_00000336_0.png
337
+ ETHZ/eth01/images/image_00000337_0.png
338
+ ETHZ/eth01/images/image_00000338_0.png
339
+ ETHZ/eth01/images/image_00000339_0.png
340
+ ETHZ/eth01/images/image_00000340_0.png
341
+ ETHZ/eth01/images/image_00000341_0.png
342
+ ETHZ/eth01/images/image_00000342_0.png
343
+ ETHZ/eth01/images/image_00000343_0.png
344
+ ETHZ/eth01/images/image_00000344_0.png
345
+ ETHZ/eth01/images/image_00000345_0.png
346
+ ETHZ/eth01/images/image_00000346_0.png
347
+ ETHZ/eth01/images/image_00000347_0.png
348
+ ETHZ/eth01/images/image_00000348_0.png
349
+ ETHZ/eth01/images/image_00000349_0.png
350
+ ETHZ/eth01/images/image_00000350_0.png
351
+ ETHZ/eth01/images/image_00000351_0.png
352
+ ETHZ/eth01/images/image_00000352_0.png
353
+ ETHZ/eth01/images/image_00000353_0.png
354
+ ETHZ/eth01/images/image_00000354_0.png
355
+ ETHZ/eth01/images/image_00000355_0.png
356
+ ETHZ/eth01/images/image_00000356_0.png
357
+ ETHZ/eth01/images/image_00000357_0.png
358
+ ETHZ/eth01/images/image_00000358_0.png
359
+ ETHZ/eth01/images/image_00000359_0.png
360
+ ETHZ/eth01/images/image_00000360_0.png
361
+ ETHZ/eth01/images/image_00000361_0.png
362
+ ETHZ/eth01/images/image_00000362_0.png
363
+ ETHZ/eth01/images/image_00000363_0.png
364
+ ETHZ/eth01/images/image_00000364_0.png
365
+ ETHZ/eth01/images/image_00000365_0.png
366
+ ETHZ/eth01/images/image_00000366_0.png
367
+ ETHZ/eth01/images/image_00000367_0.png
368
+ ETHZ/eth01/images/image_00000368_0.png
369
+ ETHZ/eth01/images/image_00000369_0.png
370
+ ETHZ/eth01/images/image_00000370_0.png
371
+ ETHZ/eth01/images/image_00000371_0.png
372
+ ETHZ/eth01/images/image_00000372_0.png
373
+ ETHZ/eth01/images/image_00000373_0.png
374
+ ETHZ/eth01/images/image_00000374_0.png
375
+ ETHZ/eth01/images/image_00000375_0.png
376
+ ETHZ/eth01/images/image_00000376_0.png
377
+ ETHZ/eth01/images/image_00000377_0.png
378
+ ETHZ/eth01/images/image_00000378_0.png
379
+ ETHZ/eth01/images/image_00000379_0.png
380
+ ETHZ/eth01/images/image_00000380_0.png
381
+ ETHZ/eth01/images/image_00000381_0.png
382
+ ETHZ/eth01/images/image_00000382_0.png
383
+ ETHZ/eth01/images/image_00000383_0.png
384
+ ETHZ/eth01/images/image_00000384_0.png
385
+ ETHZ/eth01/images/image_00000385_0.png
386
+ ETHZ/eth01/images/image_00000386_0.png
387
+ ETHZ/eth01/images/image_00000387_0.png
388
+ ETHZ/eth01/images/image_00000388_0.png
389
+ ETHZ/eth01/images/image_00000389_0.png
390
+ ETHZ/eth01/images/image_00000390_0.png
391
+ ETHZ/eth01/images/image_00000391_0.png
392
+ ETHZ/eth01/images/image_00000392_0.png
393
+ ETHZ/eth01/images/image_00000393_0.png
394
+ ETHZ/eth01/images/image_00000394_0.png
395
+ ETHZ/eth01/images/image_00000395_0.png
396
+ ETHZ/eth01/images/image_00000396_0.png
397
+ ETHZ/eth01/images/image_00000397_0.png
398
+ ETHZ/eth01/images/image_00000398_0.png
399
+ ETHZ/eth01/images/image_00000399_0.png
400
+ ETHZ/eth01/images/image_00000400_0.png
401
+ ETHZ/eth01/images/image_00000401_0.png
402
+ ETHZ/eth01/images/image_00000402_0.png
403
+ ETHZ/eth01/images/image_00000403_0.png
404
+ ETHZ/eth01/images/image_00000404_0.png
405
+ ETHZ/eth01/images/image_00000405_0.png
406
+ ETHZ/eth01/images/image_00000406_0.png
407
+ ETHZ/eth01/images/image_00000407_0.png
408
+ ETHZ/eth01/images/image_00000408_0.png
409
+ ETHZ/eth01/images/image_00000409_0.png
410
+ ETHZ/eth01/images/image_00000410_0.png
411
+ ETHZ/eth01/images/image_00000411_0.png
412
+ ETHZ/eth01/images/image_00000412_0.png
413
+ ETHZ/eth01/images/image_00000413_0.png
414
+ ETHZ/eth01/images/image_00000414_0.png
415
+ ETHZ/eth01/images/image_00000415_0.png
416
+ ETHZ/eth01/images/image_00000416_0.png
417
+ ETHZ/eth01/images/image_00000417_0.png
418
+ ETHZ/eth01/images/image_00000418_0.png
419
+ ETHZ/eth01/images/image_00000419_0.png
420
+ ETHZ/eth01/images/image_00000420_0.png
421
+ ETHZ/eth01/images/image_00000421_0.png
422
+ ETHZ/eth01/images/image_00000422_0.png
423
+ ETHZ/eth01/images/image_00000423_0.png
424
+ ETHZ/eth01/images/image_00000424_0.png
425
+ ETHZ/eth01/images/image_00000425_0.png
426
+ ETHZ/eth01/images/image_00000426_0.png
427
+ ETHZ/eth01/images/image_00000427_0.png
428
+ ETHZ/eth01/images/image_00000428_0.png
429
+ ETHZ/eth01/images/image_00000429_0.png
430
+ ETHZ/eth01/images/image_00000430_0.png
431
+ ETHZ/eth01/images/image_00000431_0.png
432
+ ETHZ/eth01/images/image_00000432_0.png
433
+ ETHZ/eth01/images/image_00000433_0.png
434
+ ETHZ/eth01/images/image_00000434_0.png
435
+ ETHZ/eth01/images/image_00000435_0.png
436
+ ETHZ/eth01/images/image_00000436_0.png
437
+ ETHZ/eth01/images/image_00000437_0.png
438
+ ETHZ/eth01/images/image_00000438_0.png
439
+ ETHZ/eth01/images/image_00000439_0.png
440
+ ETHZ/eth01/images/image_00000440_0.png
441
+ ETHZ/eth01/images/image_00000441_0.png
442
+ ETHZ/eth01/images/image_00000442_0.png
443
+ ETHZ/eth01/images/image_00000443_0.png
444
+ ETHZ/eth01/images/image_00000444_0.png
445
+ ETHZ/eth01/images/image_00000445_0.png
446
+ ETHZ/eth01/images/image_00000446_0.png
447
+ ETHZ/eth01/images/image_00000447_0.png
448
+ ETHZ/eth01/images/image_00000448_0.png
449
+ ETHZ/eth01/images/image_00000449_0.png
450
+ ETHZ/eth01/images/image_00000450_0.png
451
+ ETHZ/eth01/images/image_00000451_0.png
452
+ ETHZ/eth01/images/image_00000452_0.png
453
+ ETHZ/eth01/images/image_00000453_0.png
454
+ ETHZ/eth01/images/image_00000454_0.png
455
+ ETHZ/eth01/images/image_00000455_0.png
456
+ ETHZ/eth01/images/image_00000456_0.png
457
+ ETHZ/eth01/images/image_00000457_0.png
458
+ ETHZ/eth01/images/image_00000458_0.png
459
+ ETHZ/eth01/images/image_00000459_0.png
460
+ ETHZ/eth01/images/image_00000460_0.png
461
+ ETHZ/eth01/images/image_00000461_0.png
462
+ ETHZ/eth01/images/image_00000462_0.png
463
+ ETHZ/eth01/images/image_00000463_0.png
464
+ ETHZ/eth01/images/image_00000464_0.png
465
+ ETHZ/eth01/images/image_00000465_0.png
466
+ ETHZ/eth01/images/image_00000466_0.png
467
+ ETHZ/eth01/images/image_00000467_0.png
468
+ ETHZ/eth01/images/image_00000468_0.png
469
+ ETHZ/eth01/images/image_00000469_0.png
470
+ ETHZ/eth01/images/image_00000470_0.png
471
+ ETHZ/eth01/images/image_00000471_0.png
472
+ ETHZ/eth01/images/image_00000472_0.png
473
+ ETHZ/eth01/images/image_00000473_0.png
474
+ ETHZ/eth01/images/image_00000474_0.png
475
+ ETHZ/eth01/images/image_00000475_0.png
476
+ ETHZ/eth01/images/image_00000476_0.png
477
+ ETHZ/eth01/images/image_00000477_0.png
478
+ ETHZ/eth01/images/image_00000478_0.png
479
+ ETHZ/eth01/images/image_00000479_0.png
480
+ ETHZ/eth01/images/image_00000480_0.png
481
+ ETHZ/eth01/images/image_00000481_0.png
482
+ ETHZ/eth01/images/image_00000482_0.png
483
+ ETHZ/eth01/images/image_00000483_0.png
484
+ ETHZ/eth01/images/image_00000484_0.png
485
+ ETHZ/eth01/images/image_00000485_0.png
486
+ ETHZ/eth01/images/image_00000486_0.png
487
+ ETHZ/eth01/images/image_00000487_0.png
488
+ ETHZ/eth01/images/image_00000488_0.png
489
+ ETHZ/eth01/images/image_00000489_0.png
490
+ ETHZ/eth01/images/image_00000490_0.png
491
+ ETHZ/eth01/images/image_00000491_0.png
492
+ ETHZ/eth01/images/image_00000492_0.png
493
+ ETHZ/eth01/images/image_00000493_0.png
494
+ ETHZ/eth01/images/image_00000494_0.png
495
+ ETHZ/eth01/images/image_00000495_0.png
496
+ ETHZ/eth01/images/image_00000496_0.png
497
+ ETHZ/eth01/images/image_00000497_0.png
498
+ ETHZ/eth01/images/image_00000498_0.png
499
+ ETHZ/eth01/images/image_00000499_0.png
500
+ ETHZ/eth01/images/image_00000500_0.png
501
+ ETHZ/eth01/images/image_00000501_0.png
502
+ ETHZ/eth01/images/image_00000502_0.png
503
+ ETHZ/eth01/images/image_00000503_0.png
504
+ ETHZ/eth01/images/image_00000504_0.png
505
+ ETHZ/eth01/images/image_00000505_0.png
506
+ ETHZ/eth01/images/image_00000506_0.png
507
+ ETHZ/eth01/images/image_00000507_0.png
508
+ ETHZ/eth01/images/image_00000508_0.png
509
+ ETHZ/eth01/images/image_00000509_0.png
510
+ ETHZ/eth01/images/image_00000510_0.png
511
+ ETHZ/eth01/images/image_00000511_0.png
512
+ ETHZ/eth01/images/image_00000512_0.png
513
+ ETHZ/eth01/images/image_00000513_0.png
514
+ ETHZ/eth01/images/image_00000514_0.png
515
+ ETHZ/eth01/images/image_00000515_0.png
516
+ ETHZ/eth01/images/image_00000516_0.png
517
+ ETHZ/eth01/images/image_00000517_0.png
518
+ ETHZ/eth01/images/image_00000518_0.png
519
+ ETHZ/eth01/images/image_00000519_0.png
520
+ ETHZ/eth01/images/image_00000520_0.png
521
+ ETHZ/eth01/images/image_00000521_0.png
522
+ ETHZ/eth01/images/image_00000522_0.png
523
+ ETHZ/eth01/images/image_00000523_0.png
524
+ ETHZ/eth01/images/image_00000524_0.png
525
+ ETHZ/eth01/images/image_00000525_0.png
526
+ ETHZ/eth01/images/image_00000526_0.png
527
+ ETHZ/eth01/images/image_00000527_0.png
528
+ ETHZ/eth01/images/image_00000528_0.png
529
+ ETHZ/eth01/images/image_00000529_0.png
530
+ ETHZ/eth01/images/image_00000530_0.png
531
+ ETHZ/eth01/images/image_00000531_0.png
532
+ ETHZ/eth01/images/image_00000532_0.png
533
+ ETHZ/eth01/images/image_00000533_0.png
534
+ ETHZ/eth01/images/image_00000534_0.png
535
+ ETHZ/eth01/images/image_00000535_0.png
536
+ ETHZ/eth01/images/image_00000536_0.png
537
+ ETHZ/eth01/images/image_00000537_0.png
538
+ ETHZ/eth01/images/image_00000538_0.png
539
+ ETHZ/eth01/images/image_00000539_0.png
540
+ ETHZ/eth01/images/image_00000540_0.png
541
+ ETHZ/eth01/images/image_00000541_0.png
542
+ ETHZ/eth01/images/image_00000542_0.png
543
+ ETHZ/eth01/images/image_00000543_0.png
544
+ ETHZ/eth01/images/image_00000544_0.png
545
+ ETHZ/eth01/images/image_00000545_0.png
546
+ ETHZ/eth01/images/image_00000546_0.png
547
+ ETHZ/eth01/images/image_00000547_0.png
548
+ ETHZ/eth01/images/image_00000548_0.png
549
+ ETHZ/eth01/images/image_00000549_0.png
550
+ ETHZ/eth01/images/image_00000550_0.png
551
+ ETHZ/eth01/images/image_00000551_0.png
552
+ ETHZ/eth01/images/image_00000552_0.png
553
+ ETHZ/eth01/images/image_00000553_0.png
554
+ ETHZ/eth01/images/image_00000554_0.png
555
+ ETHZ/eth01/images/image_00000555_0.png
556
+ ETHZ/eth01/images/image_00000556_0.png
557
+ ETHZ/eth01/images/image_00000557_0.png
558
+ ETHZ/eth01/images/image_00000558_0.png
559
+ ETHZ/eth01/images/image_00000559_0.png
560
+ ETHZ/eth01/images/image_00000560_0.png
561
+ ETHZ/eth01/images/image_00000561_0.png
562
+ ETHZ/eth01/images/image_00000562_0.png
563
+ ETHZ/eth01/images/image_00000563_0.png
564
+ ETHZ/eth01/images/image_00000564_0.png
565
+ ETHZ/eth01/images/image_00000565_0.png
566
+ ETHZ/eth01/images/image_00000566_0.png
567
+ ETHZ/eth01/images/image_00000567_0.png
568
+ ETHZ/eth01/images/image_00000568_0.png
569
+ ETHZ/eth01/images/image_00000569_0.png
570
+ ETHZ/eth01/images/image_00000570_0.png
571
+ ETHZ/eth01/images/image_00000571_0.png
572
+ ETHZ/eth01/images/image_00000572_0.png
573
+ ETHZ/eth01/images/image_00000573_0.png
574
+ ETHZ/eth01/images/image_00000574_0.png
575
+ ETHZ/eth01/images/image_00000575_0.png
576
+ ETHZ/eth01/images/image_00000576_0.png
577
+ ETHZ/eth01/images/image_00000577_0.png
578
+ ETHZ/eth01/images/image_00000578_0.png
579
+ ETHZ/eth01/images/image_00000579_0.png
580
+ ETHZ/eth01/images/image_00000580_0.png
581
+ ETHZ/eth01/images/image_00000581_0.png
582
+ ETHZ/eth01/images/image_00000582_0.png
583
+ ETHZ/eth01/images/image_00000583_0.png
584
+ ETHZ/eth01/images/image_00000584_0.png
585
+ ETHZ/eth01/images/image_00000585_0.png
586
+ ETHZ/eth01/images/image_00000586_0.png
587
+ ETHZ/eth01/images/image_00000587_0.png
588
+ ETHZ/eth01/images/image_00000588_0.png
589
+ ETHZ/eth01/images/image_00000589_0.png
590
+ ETHZ/eth01/images/image_00000590_0.png
591
+ ETHZ/eth01/images/image_00000591_0.png
592
+ ETHZ/eth01/images/image_00000592_0.png
593
+ ETHZ/eth01/images/image_00000593_0.png
594
+ ETHZ/eth01/images/image_00000594_0.png
595
+ ETHZ/eth01/images/image_00000595_0.png
596
+ ETHZ/eth01/images/image_00000596_0.png
597
+ ETHZ/eth01/images/image_00000597_0.png
598
+ ETHZ/eth01/images/image_00000598_0.png
599
+ ETHZ/eth01/images/image_00000599_0.png
600
+ ETHZ/eth01/images/image_00000600_0.png
601
+ ETHZ/eth01/images/image_00000601_0.png
602
+ ETHZ/eth01/images/image_00000602_0.png
603
+ ETHZ/eth01/images/image_00000603_0.png
604
+ ETHZ/eth01/images/image_00000604_0.png
605
+ ETHZ/eth01/images/image_00000605_0.png
606
+ ETHZ/eth01/images/image_00000606_0.png
607
+ ETHZ/eth01/images/image_00000607_0.png
608
+ ETHZ/eth01/images/image_00000608_0.png
609
+ ETHZ/eth01/images/image_00000609_0.png
610
+ ETHZ/eth01/images/image_00000610_0.png
611
+ ETHZ/eth01/images/image_00000611_0.png
612
+ ETHZ/eth01/images/image_00000612_0.png
613
+ ETHZ/eth01/images/image_00000613_0.png
614
+ ETHZ/eth01/images/image_00000614_0.png
615
+ ETHZ/eth01/images/image_00000615_0.png
616
+ ETHZ/eth01/images/image_00000616_0.png
617
+ ETHZ/eth01/images/image_00000617_0.png
618
+ ETHZ/eth01/images/image_00000618_0.png
619
+ ETHZ/eth01/images/image_00000619_0.png
620
+ ETHZ/eth01/images/image_00000620_0.png
621
+ ETHZ/eth01/images/image_00000621_0.png
622
+ ETHZ/eth01/images/image_00000622_0.png
623
+ ETHZ/eth01/images/image_00000623_0.png
624
+ ETHZ/eth01/images/image_00000624_0.png
625
+ ETHZ/eth01/images/image_00000625_0.png
626
+ ETHZ/eth01/images/image_00000626_0.png
627
+ ETHZ/eth01/images/image_00000627_0.png
628
+ ETHZ/eth01/images/image_00000628_0.png
629
+ ETHZ/eth01/images/image_00000629_0.png
630
+ ETHZ/eth01/images/image_00000630_0.png
631
+ ETHZ/eth01/images/image_00000631_0.png
632
+ ETHZ/eth01/images/image_00000632_0.png
633
+ ETHZ/eth01/images/image_00000633_0.png
634
+ ETHZ/eth01/images/image_00000634_0.png
635
+ ETHZ/eth01/images/image_00000635_0.png
636
+ ETHZ/eth01/images/image_00000636_0.png
637
+ ETHZ/eth01/images/image_00000637_0.png
638
+ ETHZ/eth01/images/image_00000638_0.png
639
+ ETHZ/eth01/images/image_00000639_0.png
640
+ ETHZ/eth01/images/image_00000640_0.png
641
+ ETHZ/eth01/images/image_00000641_0.png
642
+ ETHZ/eth01/images/image_00000642_0.png
643
+ ETHZ/eth01/images/image_00000643_0.png
644
+ ETHZ/eth01/images/image_00000644_0.png
645
+ ETHZ/eth01/images/image_00000645_0.png
646
+ ETHZ/eth01/images/image_00000646_0.png
647
+ ETHZ/eth01/images/image_00000647_0.png
648
+ ETHZ/eth01/images/image_00000648_0.png
649
+ ETHZ/eth01/images/image_00000649_0.png
650
+ ETHZ/eth01/images/image_00000650_0.png
651
+ ETHZ/eth01/images/image_00000651_0.png
652
+ ETHZ/eth01/images/image_00000652_0.png
653
+ ETHZ/eth01/images/image_00000653_0.png
654
+ ETHZ/eth01/images/image_00000654_0.png
655
+ ETHZ/eth01/images/image_00000655_0.png
656
+ ETHZ/eth01/images/image_00000656_0.png
657
+ ETHZ/eth01/images/image_00000657_0.png
658
+ ETHZ/eth01/images/image_00000658_0.png
659
+ ETHZ/eth01/images/image_00000659_0.png
660
+ ETHZ/eth01/images/image_00000660_0.png
661
+ ETHZ/eth01/images/image_00000661_0.png
662
+ ETHZ/eth01/images/image_00000662_0.png
663
+ ETHZ/eth01/images/image_00000663_0.png
664
+ ETHZ/eth01/images/image_00000664_0.png
665
+ ETHZ/eth01/images/image_00000665_0.png
666
+ ETHZ/eth01/images/image_00000666_0.png
667
+ ETHZ/eth01/images/image_00000667_0.png
668
+ ETHZ/eth01/images/image_00000668_0.png
669
+ ETHZ/eth01/images/image_00000669_0.png
670
+ ETHZ/eth01/images/image_00000670_0.png
671
+ ETHZ/eth01/images/image_00000671_0.png
672
+ ETHZ/eth01/images/image_00000672_0.png
673
+ ETHZ/eth01/images/image_00000673_0.png
674
+ ETHZ/eth01/images/image_00000674_0.png
675
+ ETHZ/eth01/images/image_00000675_0.png
676
+ ETHZ/eth01/images/image_00000676_0.png
677
+ ETHZ/eth01/images/image_00000677_0.png
678
+ ETHZ/eth01/images/image_00000678_0.png
679
+ ETHZ/eth01/images/image_00000679_0.png
680
+ ETHZ/eth01/images/image_00000680_0.png
681
+ ETHZ/eth01/images/image_00000681_0.png
682
+ ETHZ/eth01/images/image_00000682_0.png
683
+ ETHZ/eth01/images/image_00000683_0.png
684
+ ETHZ/eth01/images/image_00000684_0.png
685
+ ETHZ/eth01/images/image_00000685_0.png
686
+ ETHZ/eth01/images/image_00000686_0.png
687
+ ETHZ/eth01/images/image_00000687_0.png
688
+ ETHZ/eth01/images/image_00000688_0.png
689
+ ETHZ/eth01/images/image_00000689_0.png
690
+ ETHZ/eth01/images/image_00000690_0.png
691
+ ETHZ/eth01/images/image_00000691_0.png
692
+ ETHZ/eth01/images/image_00000692_0.png
693
+ ETHZ/eth01/images/image_00000693_0.png
694
+ ETHZ/eth01/images/image_00000694_0.png
695
+ ETHZ/eth01/images/image_00000695_0.png
696
+ ETHZ/eth01/images/image_00000696_0.png
697
+ ETHZ/eth01/images/image_00000697_0.png
698
+ ETHZ/eth01/images/image_00000698_0.png
699
+ ETHZ/eth01/images/image_00000699_0.png
700
+ ETHZ/eth01/images/image_00000700_0.png
701
+ ETHZ/eth01/images/image_00000701_0.png
702
+ ETHZ/eth01/images/image_00000702_0.png
703
+ ETHZ/eth01/images/image_00000703_0.png
704
+ ETHZ/eth01/images/image_00000704_0.png
705
+ ETHZ/eth01/images/image_00000705_0.png
706
+ ETHZ/eth01/images/image_00000706_0.png
707
+ ETHZ/eth01/images/image_00000707_0.png
708
+ ETHZ/eth01/images/image_00000708_0.png
709
+ ETHZ/eth01/images/image_00000709_0.png
710
+ ETHZ/eth01/images/image_00000710_0.png
711
+ ETHZ/eth01/images/image_00000711_0.png
712
+ ETHZ/eth01/images/image_00000712_0.png
713
+ ETHZ/eth01/images/image_00000713_0.png
714
+ ETHZ/eth01/images/image_00000714_0.png
715
+ ETHZ/eth01/images/image_00000715_0.png
716
+ ETHZ/eth01/images/image_00000716_0.png
717
+ ETHZ/eth01/images/image_00000717_0.png
718
+ ETHZ/eth01/images/image_00000718_0.png
719
+ ETHZ/eth01/images/image_00000719_0.png
720
+ ETHZ/eth01/images/image_00000720_0.png
721
+ ETHZ/eth01/images/image_00000721_0.png
722
+ ETHZ/eth01/images/image_00000722_0.png
723
+ ETHZ/eth01/images/image_00000723_0.png
724
+ ETHZ/eth01/images/image_00000724_0.png
725
+ ETHZ/eth01/images/image_00000725_0.png
726
+ ETHZ/eth01/images/image_00000726_0.png
727
+ ETHZ/eth01/images/image_00000727_0.png
728
+ ETHZ/eth01/images/image_00000728_0.png
729
+ ETHZ/eth01/images/image_00000729_0.png
730
+ ETHZ/eth01/images/image_00000730_0.png
731
+ ETHZ/eth01/images/image_00000731_0.png
732
+ ETHZ/eth01/images/image_00000732_0.png
733
+ ETHZ/eth01/images/image_00000733_0.png
734
+ ETHZ/eth01/images/image_00000734_0.png
735
+ ETHZ/eth01/images/image_00000735_0.png
736
+ ETHZ/eth01/images/image_00000736_0.png
737
+ ETHZ/eth01/images/image_00000737_0.png
738
+ ETHZ/eth01/images/image_00000738_0.png
739
+ ETHZ/eth01/images/image_00000739_0.png
740
+ ETHZ/eth01/images/image_00000740_0.png
741
+ ETHZ/eth01/images/image_00000741_0.png
742
+ ETHZ/eth01/images/image_00000742_0.png
743
+ ETHZ/eth01/images/image_00000743_0.png
744
+ ETHZ/eth01/images/image_00000744_0.png
745
+ ETHZ/eth01/images/image_00000745_0.png
746
+ ETHZ/eth01/images/image_00000746_0.png
747
+ ETHZ/eth01/images/image_00000747_0.png
748
+ ETHZ/eth01/images/image_00000748_0.png
749
+ ETHZ/eth01/images/image_00000749_0.png
750
+ ETHZ/eth01/images/image_00000750_0.png
751
+ ETHZ/eth01/images/image_00000751_0.png
752
+ ETHZ/eth01/images/image_00000752_0.png
753
+ ETHZ/eth01/images/image_00000753_0.png
754
+ ETHZ/eth01/images/image_00000754_0.png
755
+ ETHZ/eth01/images/image_00000755_0.png
756
+ ETHZ/eth01/images/image_00000756_0.png
757
+ ETHZ/eth01/images/image_00000757_0.png
758
+ ETHZ/eth01/images/image_00000758_0.png
759
+ ETHZ/eth01/images/image_00000759_0.png
760
+ ETHZ/eth01/images/image_00000760_0.png
761
+ ETHZ/eth01/images/image_00000761_0.png
762
+ ETHZ/eth01/images/image_00000762_0.png
763
+ ETHZ/eth01/images/image_00000763_0.png
764
+ ETHZ/eth01/images/image_00000764_0.png
765
+ ETHZ/eth01/images/image_00000765_0.png
766
+ ETHZ/eth01/images/image_00000766_0.png
767
+ ETHZ/eth01/images/image_00000767_0.png
768
+ ETHZ/eth01/images/image_00000768_0.png
769
+ ETHZ/eth01/images/image_00000769_0.png
770
+ ETHZ/eth01/images/image_00000770_0.png
771
+ ETHZ/eth01/images/image_00000771_0.png
772
+ ETHZ/eth01/images/image_00000772_0.png
773
+ ETHZ/eth01/images/image_00000773_0.png
774
+ ETHZ/eth01/images/image_00000774_0.png
775
+ ETHZ/eth01/images/image_00000775_0.png
776
+ ETHZ/eth01/images/image_00000776_0.png
777
+ ETHZ/eth01/images/image_00000777_0.png
778
+ ETHZ/eth01/images/image_00000778_0.png
779
+ ETHZ/eth01/images/image_00000779_0.png
780
+ ETHZ/eth01/images/image_00000780_0.png
781
+ ETHZ/eth01/images/image_00000781_0.png
782
+ ETHZ/eth01/images/image_00000782_0.png
783
+ ETHZ/eth01/images/image_00000783_0.png
784
+ ETHZ/eth01/images/image_00000784_0.png
785
+ ETHZ/eth01/images/image_00000785_0.png
786
+ ETHZ/eth01/images/image_00000786_0.png
787
+ ETHZ/eth01/images/image_00000787_0.png
788
+ ETHZ/eth01/images/image_00000788_0.png
789
+ ETHZ/eth01/images/image_00000789_0.png
790
+ ETHZ/eth01/images/image_00000790_0.png
791
+ ETHZ/eth01/images/image_00000791_0.png
792
+ ETHZ/eth01/images/image_00000792_0.png
793
+ ETHZ/eth01/images/image_00000793_0.png
794
+ ETHZ/eth01/images/image_00000794_0.png
795
+ ETHZ/eth01/images/image_00000795_0.png
796
+ ETHZ/eth01/images/image_00000796_0.png
797
+ ETHZ/eth01/images/image_00000797_0.png
798
+ ETHZ/eth01/images/image_00000798_0.png
799
+ ETHZ/eth01/images/image_00000799_0.png
800
+ ETHZ/eth01/images/image_00000800_0.png
801
+ ETHZ/eth01/images/image_00000801_0.png
802
+ ETHZ/eth01/images/image_00000802_0.png
803
+ ETHZ/eth01/images/image_00000803_0.png
804
+ ETHZ/eth01/images/image_00000804_0.png
805
+ ETHZ/eth01/images/image_00000805_0.png
806
+ ETHZ/eth01/images/image_00000806_0.png
807
+ ETHZ/eth01/images/image_00000807_0.png
808
+ ETHZ/eth01/images/image_00000808_0.png
809
+ ETHZ/eth01/images/image_00000809_0.png
810
+ ETHZ/eth01/images/image_00000810_0.png
811
+ ETHZ/eth01/images/image_00000811_0.png
812
+ ETHZ/eth01/images/image_00000812_0.png
813
+ ETHZ/eth01/images/image_00000813_0.png
814
+ ETHZ/eth01/images/image_00000814_0.png
815
+ ETHZ/eth01/images/image_00000815_0.png
816
+ ETHZ/eth01/images/image_00000816_0.png
817
+ ETHZ/eth01/images/image_00000817_0.png
818
+ ETHZ/eth01/images/image_00000818_0.png
819
+ ETHZ/eth01/images/image_00000819_0.png
820
+ ETHZ/eth01/images/image_00000820_0.png
821
+ ETHZ/eth01/images/image_00000821_0.png
822
+ ETHZ/eth01/images/image_00000822_0.png
823
+ ETHZ/eth01/images/image_00000823_0.png
824
+ ETHZ/eth01/images/image_00000824_0.png
825
+ ETHZ/eth01/images/image_00000825_0.png
826
+ ETHZ/eth01/images/image_00000826_0.png
827
+ ETHZ/eth01/images/image_00000827_0.png
828
+ ETHZ/eth01/images/image_00000828_0.png
829
+ ETHZ/eth01/images/image_00000829_0.png
830
+ ETHZ/eth01/images/image_00000830_0.png
831
+ ETHZ/eth01/images/image_00000831_0.png
832
+ ETHZ/eth01/images/image_00000832_0.png
833
+ ETHZ/eth01/images/image_00000833_0.png
834
+ ETHZ/eth01/images/image_00000834_0.png
835
+ ETHZ/eth01/images/image_00000835_0.png
836
+ ETHZ/eth01/images/image_00000836_0.png
837
+ ETHZ/eth01/images/image_00000837_0.png
838
+ ETHZ/eth01/images/image_00000838_0.png
839
+ ETHZ/eth01/images/image_00000839_0.png
840
+ ETHZ/eth01/images/image_00000840_0.png
841
+ ETHZ/eth01/images/image_00000841_0.png
842
+ ETHZ/eth01/images/image_00000842_0.png
843
+ ETHZ/eth01/images/image_00000843_0.png
844
+ ETHZ/eth01/images/image_00000844_0.png
845
+ ETHZ/eth01/images/image_00000845_0.png
846
+ ETHZ/eth01/images/image_00000846_0.png
847
+ ETHZ/eth01/images/image_00000847_0.png
848
+ ETHZ/eth01/images/image_00000848_0.png
849
+ ETHZ/eth01/images/image_00000849_0.png
850
+ ETHZ/eth01/images/image_00000850_0.png
851
+ ETHZ/eth01/images/image_00000851_0.png
852
+ ETHZ/eth01/images/image_00000852_0.png
853
+ ETHZ/eth01/images/image_00000853_0.png
854
+ ETHZ/eth01/images/image_00000854_0.png
855
+ ETHZ/eth01/images/image_00000855_0.png
856
+ ETHZ/eth01/images/image_00000856_0.png
857
+ ETHZ/eth01/images/image_00000857_0.png
858
+ ETHZ/eth01/images/image_00000858_0.png
859
+ ETHZ/eth01/images/image_00000859_0.png
860
+ ETHZ/eth01/images/image_00000860_0.png
861
+ ETHZ/eth01/images/image_00000861_0.png
862
+ ETHZ/eth01/images/image_00000862_0.png
863
+ ETHZ/eth01/images/image_00000863_0.png
864
+ ETHZ/eth01/images/image_00000864_0.png
865
+ ETHZ/eth01/images/image_00000865_0.png
866
+ ETHZ/eth01/images/image_00000866_0.png
867
+ ETHZ/eth01/images/image_00000867_0.png
868
+ ETHZ/eth01/images/image_00000868_0.png
869
+ ETHZ/eth01/images/image_00000869_0.png
870
+ ETHZ/eth01/images/image_00000870_0.png
871
+ ETHZ/eth01/images/image_00000871_0.png
872
+ ETHZ/eth01/images/image_00000872_0.png
873
+ ETHZ/eth01/images/image_00000873_0.png
874
+ ETHZ/eth01/images/image_00000874_0.png
875
+ ETHZ/eth01/images/image_00000875_0.png
876
+ ETHZ/eth01/images/image_00000876_0.png
877
+ ETHZ/eth01/images/image_00000877_0.png
878
+ ETHZ/eth01/images/image_00000878_0.png
879
+ ETHZ/eth01/images/image_00000879_0.png
880
+ ETHZ/eth01/images/image_00000880_0.png
881
+ ETHZ/eth01/images/image_00000881_0.png
882
+ ETHZ/eth01/images/image_00000882_0.png
883
+ ETHZ/eth01/images/image_00000883_0.png
884
+ ETHZ/eth01/images/image_00000884_0.png
885
+ ETHZ/eth01/images/image_00000885_0.png
886
+ ETHZ/eth01/images/image_00000886_0.png
887
+ ETHZ/eth01/images/image_00000887_0.png
888
+ ETHZ/eth01/images/image_00000888_0.png
889
+ ETHZ/eth01/images/image_00000889_0.png
890
+ ETHZ/eth01/images/image_00000890_0.png
891
+ ETHZ/eth01/images/image_00000891_0.png
892
+ ETHZ/eth01/images/image_00000892_0.png
893
+ ETHZ/eth01/images/image_00000893_0.png
894
+ ETHZ/eth01/images/image_00000894_0.png
895
+ ETHZ/eth01/images/image_00000895_0.png
896
+ ETHZ/eth01/images/image_00000896_0.png
897
+ ETHZ/eth01/images/image_00000897_0.png
898
+ ETHZ/eth01/images/image_00000898_0.png
899
+ ETHZ/eth01/images/image_00000899_0.png
900
+ ETHZ/eth01/images/image_00000900_0.png
901
+ ETHZ/eth01/images/image_00000901_0.png
902
+ ETHZ/eth01/images/image_00000902_0.png
903
+ ETHZ/eth01/images/image_00000903_0.png
904
+ ETHZ/eth01/images/image_00000904_0.png
905
+ ETHZ/eth01/images/image_00000905_0.png
906
+ ETHZ/eth01/images/image_00000906_0.png
907
+ ETHZ/eth01/images/image_00000907_0.png
908
+ ETHZ/eth01/images/image_00000908_0.png
909
+ ETHZ/eth01/images/image_00000909_0.png
910
+ ETHZ/eth01/images/image_00000910_0.png
911
+ ETHZ/eth01/images/image_00000911_0.png
912
+ ETHZ/eth01/images/image_00000912_0.png
913
+ ETHZ/eth01/images/image_00000913_0.png
914
+ ETHZ/eth01/images/image_00000914_0.png
915
+ ETHZ/eth01/images/image_00000915_0.png
916
+ ETHZ/eth01/images/image_00000916_0.png
917
+ ETHZ/eth01/images/image_00000917_0.png
918
+ ETHZ/eth01/images/image_00000918_0.png
919
+ ETHZ/eth01/images/image_00000919_0.png
920
+ ETHZ/eth01/images/image_00000920_0.png
921
+ ETHZ/eth01/images/image_00000921_0.png
922
+ ETHZ/eth01/images/image_00000922_0.png
923
+ ETHZ/eth01/images/image_00000923_0.png
924
+ ETHZ/eth01/images/image_00000924_0.png
925
+ ETHZ/eth01/images/image_00000925_0.png
926
+ ETHZ/eth01/images/image_00000926_0.png
927
+ ETHZ/eth01/images/image_00000927_0.png
928
+ ETHZ/eth01/images/image_00000928_0.png
929
+ ETHZ/eth01/images/image_00000929_0.png
930
+ ETHZ/eth01/images/image_00000930_0.png
931
+ ETHZ/eth01/images/image_00000931_0.png
932
+ ETHZ/eth01/images/image_00000932_0.png
933
+ ETHZ/eth01/images/image_00000933_0.png
934
+ ETHZ/eth01/images/image_00000934_0.png
935
+ ETHZ/eth01/images/image_00000935_0.png
936
+ ETHZ/eth01/images/image_00000936_0.png
937
+ ETHZ/eth01/images/image_00000937_0.png
938
+ ETHZ/eth01/images/image_00000938_0.png
939
+ ETHZ/eth01/images/image_00000939_0.png
940
+ ETHZ/eth01/images/image_00000940_0.png
941
+ ETHZ/eth01/images/image_00000941_0.png
942
+ ETHZ/eth01/images/image_00000942_0.png
943
+ ETHZ/eth01/images/image_00000943_0.png
944
+ ETHZ/eth01/images/image_00000944_0.png
945
+ ETHZ/eth01/images/image_00000945_0.png
946
+ ETHZ/eth01/images/image_00000946_0.png
947
+ ETHZ/eth01/images/image_00000947_0.png
948
+ ETHZ/eth01/images/image_00000948_0.png
949
+ ETHZ/eth01/images/image_00000949_0.png
950
+ ETHZ/eth01/images/image_00000950_0.png
951
+ ETHZ/eth01/images/image_00000951_0.png
952
+ ETHZ/eth01/images/image_00000952_0.png
953
+ ETHZ/eth01/images/image_00000953_0.png
954
+ ETHZ/eth01/images/image_00000954_0.png
955
+ ETHZ/eth01/images/image_00000955_0.png
956
+ ETHZ/eth01/images/image_00000956_0.png
957
+ ETHZ/eth01/images/image_00000957_0.png
958
+ ETHZ/eth01/images/image_00000958_0.png
959
+ ETHZ/eth01/images/image_00000959_0.png
960
+ ETHZ/eth01/images/image_00000960_0.png
961
+ ETHZ/eth01/images/image_00000961_0.png
962
+ ETHZ/eth01/images/image_00000962_0.png
963
+ ETHZ/eth01/images/image_00000963_0.png
964
+ ETHZ/eth01/images/image_00000964_0.png
965
+ ETHZ/eth01/images/image_00000965_0.png
966
+ ETHZ/eth01/images/image_00000966_0.png
967
+ ETHZ/eth01/images/image_00000967_0.png
968
+ ETHZ/eth01/images/image_00000968_0.png
969
+ ETHZ/eth01/images/image_00000969_0.png
970
+ ETHZ/eth01/images/image_00000970_0.png
971
+ ETHZ/eth01/images/image_00000971_0.png
972
+ ETHZ/eth01/images/image_00000972_0.png
973
+ ETHZ/eth01/images/image_00000973_0.png
974
+ ETHZ/eth01/images/image_00000974_0.png
975
+ ETHZ/eth01/images/image_00000975_0.png
976
+ ETHZ/eth01/images/image_00000976_0.png
977
+ ETHZ/eth01/images/image_00000977_0.png
978
+ ETHZ/eth01/images/image_00000978_0.png
979
+ ETHZ/eth01/images/image_00000979_0.png
980
+ ETHZ/eth01/images/image_00000980_0.png
981
+ ETHZ/eth01/images/image_00000981_0.png
982
+ ETHZ/eth01/images/image_00000982_0.png
983
+ ETHZ/eth01/images/image_00000983_0.png
984
+ ETHZ/eth01/images/image_00000984_0.png
985
+ ETHZ/eth01/images/image_00000985_0.png
986
+ ETHZ/eth01/images/image_00000986_0.png
987
+ ETHZ/eth01/images/image_00000987_0.png
988
+ ETHZ/eth01/images/image_00000988_0.png
989
+ ETHZ/eth01/images/image_00000989_0.png
990
+ ETHZ/eth01/images/image_00000990_0.png
991
+ ETHZ/eth01/images/image_00000991_0.png
992
+ ETHZ/eth01/images/image_00000992_0.png
993
+ ETHZ/eth01/images/image_00000993_0.png
994
+ ETHZ/eth01/images/image_00000994_0.png
995
+ ETHZ/eth01/images/image_00000995_0.png
996
+ ETHZ/eth01/images/image_00000996_0.png
997
+ ETHZ/eth01/images/image_00000997_0.png
998
+ ETHZ/eth01/images/image_00000998_0.png
999
+ ETHZ/eth01/images/image_00000999_0.png
1000
+ ETHZ/eth02/images/image_00000000_0.png
1001
+ ETHZ/eth02/images/image_00000001_0.png
1002
+ ETHZ/eth02/images/image_00000002_0.png
1003
+ ETHZ/eth02/images/image_00000003_0.png
1004
+ ETHZ/eth02/images/image_00000004_0.png
1005
+ ETHZ/eth02/images/image_00000005_0.png
1006
+ ETHZ/eth02/images/image_00000006_0.png
1007
+ ETHZ/eth02/images/image_00000007_0.png
1008
+ ETHZ/eth02/images/image_00000008_0.png
1009
+ ETHZ/eth02/images/image_00000009_0.png
1010
+ ETHZ/eth02/images/image_00000010_0.png
1011
+ ETHZ/eth02/images/image_00000011_0.png
1012
+ ETHZ/eth02/images/image_00000012_0.png
1013
+ ETHZ/eth02/images/image_00000013_0.png
1014
+ ETHZ/eth02/images/image_00000014_0.png
1015
+ ETHZ/eth02/images/image_00000015_0.png
1016
+ ETHZ/eth02/images/image_00000016_0.png
1017
+ ETHZ/eth02/images/image_00000017_0.png
1018
+ ETHZ/eth02/images/image_00000018_0.png
1019
+ ETHZ/eth02/images/image_00000019_0.png
1020
+ ETHZ/eth02/images/image_00000020_0.png
1021
+ ETHZ/eth02/images/image_00000021_0.png
1022
+ ETHZ/eth02/images/image_00000022_0.png
1023
+ ETHZ/eth02/images/image_00000023_0.png
1024
+ ETHZ/eth02/images/image_00000024_0.png
1025
+ ETHZ/eth02/images/image_00000025_0.png
1026
+ ETHZ/eth02/images/image_00000026_0.png
1027
+ ETHZ/eth02/images/image_00000027_0.png
1028
+ ETHZ/eth02/images/image_00000028_0.png
1029
+ ETHZ/eth02/images/image_00000029_0.png
1030
+ ETHZ/eth02/images/image_00000030_0.png
1031
+ ETHZ/eth02/images/image_00000031_0.png
1032
+ ETHZ/eth02/images/image_00000032_0.png
1033
+ ETHZ/eth02/images/image_00000033_0.png
1034
+ ETHZ/eth02/images/image_00000034_0.png
1035
+ ETHZ/eth02/images/image_00000035_0.png
1036
+ ETHZ/eth02/images/image_00000036_0.png
1037
+ ETHZ/eth02/images/image_00000037_0.png
1038
+ ETHZ/eth02/images/image_00000038_0.png
1039
+ ETHZ/eth02/images/image_00000039_0.png
1040
+ ETHZ/eth02/images/image_00000040_0.png
1041
+ ETHZ/eth02/images/image_00000041_0.png
1042
+ ETHZ/eth02/images/image_00000042_0.png
1043
+ ETHZ/eth02/images/image_00000043_0.png
1044
+ ETHZ/eth02/images/image_00000044_0.png
1045
+ ETHZ/eth02/images/image_00000045_0.png
1046
+ ETHZ/eth02/images/image_00000046_0.png
1047
+ ETHZ/eth02/images/image_00000047_0.png
1048
+ ETHZ/eth02/images/image_00000048_0.png
1049
+ ETHZ/eth02/images/image_00000049_0.png
1050
+ ETHZ/eth02/images/image_00000050_0.png
1051
+ ETHZ/eth02/images/image_00000051_0.png
1052
+ ETHZ/eth02/images/image_00000052_0.png
1053
+ ETHZ/eth02/images/image_00000053_0.png
1054
+ ETHZ/eth02/images/image_00000054_0.png
1055
+ ETHZ/eth02/images/image_00000055_0.png
1056
+ ETHZ/eth02/images/image_00000056_0.png
1057
+ ETHZ/eth02/images/image_00000057_0.png
1058
+ ETHZ/eth02/images/image_00000058_0.png
1059
+ ETHZ/eth02/images/image_00000059_0.png
1060
+ ETHZ/eth02/images/image_00000060_0.png
1061
+ ETHZ/eth02/images/image_00000061_0.png
1062
+ ETHZ/eth02/images/image_00000062_0.png
1063
+ ETHZ/eth02/images/image_00000063_0.png
1064
+ ETHZ/eth02/images/image_00000064_0.png
1065
+ ETHZ/eth02/images/image_00000065_0.png
1066
+ ETHZ/eth02/images/image_00000066_0.png
1067
+ ETHZ/eth02/images/image_00000067_0.png
1068
+ ETHZ/eth02/images/image_00000068_0.png
1069
+ ETHZ/eth02/images/image_00000069_0.png
1070
+ ETHZ/eth02/images/image_00000070_0.png
1071
+ ETHZ/eth02/images/image_00000071_0.png
1072
+ ETHZ/eth02/images/image_00000072_0.png
1073
+ ETHZ/eth02/images/image_00000073_0.png
1074
+ ETHZ/eth02/images/image_00000074_0.png
1075
+ ETHZ/eth02/images/image_00000075_0.png
1076
+ ETHZ/eth02/images/image_00000076_0.png
1077
+ ETHZ/eth02/images/image_00000077_0.png
1078
+ ETHZ/eth02/images/image_00000078_0.png
1079
+ ETHZ/eth02/images/image_00000079_0.png
1080
+ ETHZ/eth02/images/image_00000080_0.png
1081
+ ETHZ/eth02/images/image_00000081_0.png
1082
+ ETHZ/eth02/images/image_00000082_0.png
1083
+ ETHZ/eth02/images/image_00000083_0.png
1084
+ ETHZ/eth02/images/image_00000084_0.png
1085
+ ETHZ/eth02/images/image_00000085_0.png
1086
+ ETHZ/eth02/images/image_00000086_0.png
1087
+ ETHZ/eth02/images/image_00000087_0.png
1088
+ ETHZ/eth02/images/image_00000088_0.png
1089
+ ETHZ/eth02/images/image_00000089_0.png
1090
+ ETHZ/eth02/images/image_00000090_0.png
1091
+ ETHZ/eth02/images/image_00000091_0.png
1092
+ ETHZ/eth02/images/image_00000092_0.png
1093
+ ETHZ/eth02/images/image_00000093_0.png
1094
+ ETHZ/eth02/images/image_00000094_0.png
1095
+ ETHZ/eth02/images/image_00000095_0.png
1096
+ ETHZ/eth02/images/image_00000096_0.png
1097
+ ETHZ/eth02/images/image_00000097_0.png
1098
+ ETHZ/eth02/images/image_00000098_0.png
1099
+ ETHZ/eth02/images/image_00000099_0.png
1100
+ ETHZ/eth02/images/image_00000100_0.png
1101
+ ETHZ/eth02/images/image_00000101_0.png
1102
+ ETHZ/eth02/images/image_00000102_0.png
1103
+ ETHZ/eth02/images/image_00000103_0.png
1104
+ ETHZ/eth02/images/image_00000104_0.png
1105
+ ETHZ/eth02/images/image_00000105_0.png
1106
+ ETHZ/eth02/images/image_00000106_0.png
1107
+ ETHZ/eth02/images/image_00000107_0.png
1108
+ ETHZ/eth02/images/image_00000108_0.png
1109
+ ETHZ/eth02/images/image_00000109_0.png
1110
+ ETHZ/eth02/images/image_00000110_0.png
1111
+ ETHZ/eth02/images/image_00000111_0.png
1112
+ ETHZ/eth02/images/image_00000112_0.png
1113
+ ETHZ/eth02/images/image_00000113_0.png
1114
+ ETHZ/eth02/images/image_00000114_0.png
1115
+ ETHZ/eth02/images/image_00000115_0.png
1116
+ ETHZ/eth02/images/image_00000116_0.png
1117
+ ETHZ/eth02/images/image_00000117_0.png
1118
+ ETHZ/eth02/images/image_00000118_0.png
1119
+ ETHZ/eth02/images/image_00000119_0.png
1120
+ ETHZ/eth02/images/image_00000120_0.png
1121
+ ETHZ/eth02/images/image_00000121_0.png
1122
+ ETHZ/eth02/images/image_00000122_0.png
1123
+ ETHZ/eth02/images/image_00000123_0.png
1124
+ ETHZ/eth02/images/image_00000124_0.png
1125
+ ETHZ/eth02/images/image_00000125_0.png
1126
+ ETHZ/eth02/images/image_00000126_0.png
1127
+ ETHZ/eth02/images/image_00000127_0.png
1128
+ ETHZ/eth02/images/image_00000128_0.png
1129
+ ETHZ/eth02/images/image_00000129_0.png
1130
+ ETHZ/eth02/images/image_00000130_0.png
1131
+ ETHZ/eth02/images/image_00000131_0.png
1132
+ ETHZ/eth02/images/image_00000132_0.png
1133
+ ETHZ/eth02/images/image_00000133_0.png
1134
+ ETHZ/eth02/images/image_00000134_0.png
1135
+ ETHZ/eth02/images/image_00000135_0.png
1136
+ ETHZ/eth02/images/image_00000136_0.png
1137
+ ETHZ/eth02/images/image_00000137_0.png
1138
+ ETHZ/eth02/images/image_00000138_0.png
1139
+ ETHZ/eth02/images/image_00000139_0.png
1140
+ ETHZ/eth02/images/image_00000140_0.png
1141
+ ETHZ/eth02/images/image_00000141_0.png
1142
+ ETHZ/eth02/images/image_00000142_0.png
1143
+ ETHZ/eth02/images/image_00000143_0.png
1144
+ ETHZ/eth02/images/image_00000144_0.png
1145
+ ETHZ/eth02/images/image_00000145_0.png
1146
+ ETHZ/eth02/images/image_00000146_0.png
1147
+ ETHZ/eth02/images/image_00000147_0.png
1148
+ ETHZ/eth02/images/image_00000148_0.png
1149
+ ETHZ/eth02/images/image_00000149_0.png
1150
+ ETHZ/eth02/images/image_00000150_0.png
1151
+ ETHZ/eth02/images/image_00000151_0.png
1152
+ ETHZ/eth02/images/image_00000152_0.png
1153
+ ETHZ/eth02/images/image_00000153_0.png
1154
+ ETHZ/eth02/images/image_00000154_0.png
1155
+ ETHZ/eth02/images/image_00000155_0.png
1156
+ ETHZ/eth02/images/image_00000156_0.png
1157
+ ETHZ/eth02/images/image_00000157_0.png
1158
+ ETHZ/eth02/images/image_00000158_0.png
1159
+ ETHZ/eth02/images/image_00000159_0.png
1160
+ ETHZ/eth02/images/image_00000160_0.png
1161
+ ETHZ/eth02/images/image_00000161_0.png
1162
+ ETHZ/eth02/images/image_00000162_0.png
1163
+ ETHZ/eth02/images/image_00000163_0.png
1164
+ ETHZ/eth02/images/image_00000164_0.png
1165
+ ETHZ/eth02/images/image_00000165_0.png
1166
+ ETHZ/eth02/images/image_00000166_0.png
1167
+ ETHZ/eth02/images/image_00000167_0.png
1168
+ ETHZ/eth02/images/image_00000168_0.png
1169
+ ETHZ/eth02/images/image_00000169_0.png
1170
+ ETHZ/eth02/images/image_00000170_0.png
1171
+ ETHZ/eth02/images/image_00000171_0.png
1172
+ ETHZ/eth02/images/image_00000172_0.png
1173
+ ETHZ/eth02/images/image_00000173_0.png
1174
+ ETHZ/eth02/images/image_00000174_0.png
1175
+ ETHZ/eth02/images/image_00000175_0.png
1176
+ ETHZ/eth02/images/image_00000176_0.png
1177
+ ETHZ/eth02/images/image_00000177_0.png
1178
+ ETHZ/eth02/images/image_00000178_0.png
1179
+ ETHZ/eth02/images/image_00000179_0.png
1180
+ ETHZ/eth02/images/image_00000180_0.png
1181
+ ETHZ/eth02/images/image_00000181_0.png
1182
+ ETHZ/eth02/images/image_00000182_0.png
1183
+ ETHZ/eth02/images/image_00000183_0.png
1184
+ ETHZ/eth02/images/image_00000184_0.png
1185
+ ETHZ/eth02/images/image_00000185_0.png
1186
+ ETHZ/eth02/images/image_00000186_0.png
1187
+ ETHZ/eth02/images/image_00000187_0.png
1188
+ ETHZ/eth02/images/image_00000188_0.png
1189
+ ETHZ/eth02/images/image_00000189_0.png
1190
+ ETHZ/eth02/images/image_00000190_0.png
1191
+ ETHZ/eth02/images/image_00000191_0.png
1192
+ ETHZ/eth02/images/image_00000192_0.png
1193
+ ETHZ/eth02/images/image_00000193_0.png
1194
+ ETHZ/eth02/images/image_00000194_0.png
1195
+ ETHZ/eth02/images/image_00000195_0.png
1196
+ ETHZ/eth02/images/image_00000196_0.png
1197
+ ETHZ/eth02/images/image_00000197_0.png
1198
+ ETHZ/eth02/images/image_00000198_0.png
1199
+ ETHZ/eth02/images/image_00000199_0.png
1200
+ ETHZ/eth02/images/image_00000200_0.png
1201
+ ETHZ/eth02/images/image_00000201_0.png
1202
+ ETHZ/eth02/images/image_00000202_0.png
1203
+ ETHZ/eth02/images/image_00000203_0.png
1204
+ ETHZ/eth02/images/image_00000204_0.png
1205
+ ETHZ/eth02/images/image_00000205_0.png
1206
+ ETHZ/eth02/images/image_00000206_0.png
1207
+ ETHZ/eth02/images/image_00000207_0.png
1208
+ ETHZ/eth02/images/image_00000208_0.png
1209
+ ETHZ/eth02/images/image_00000209_0.png
1210
+ ETHZ/eth02/images/image_00000210_0.png
1211
+ ETHZ/eth02/images/image_00000211_0.png
1212
+ ETHZ/eth02/images/image_00000212_0.png
1213
+ ETHZ/eth02/images/image_00000213_0.png
1214
+ ETHZ/eth02/images/image_00000214_0.png
1215
+ ETHZ/eth02/images/image_00000215_0.png
1216
+ ETHZ/eth02/images/image_00000216_0.png
1217
+ ETHZ/eth02/images/image_00000217_0.png
1218
+ ETHZ/eth02/images/image_00000218_0.png
1219
+ ETHZ/eth02/images/image_00000219_0.png
1220
+ ETHZ/eth02/images/image_00000220_0.png
1221
+ ETHZ/eth02/images/image_00000221_0.png
1222
+ ETHZ/eth02/images/image_00000222_0.png
1223
+ ETHZ/eth02/images/image_00000223_0.png
1224
+ ETHZ/eth02/images/image_00000224_0.png
1225
+ ETHZ/eth02/images/image_00000225_0.png
1226
+ ETHZ/eth02/images/image_00000226_0.png
1227
+ ETHZ/eth02/images/image_00000227_0.png
1228
+ ETHZ/eth02/images/image_00000228_0.png
1229
+ ETHZ/eth02/images/image_00000229_0.png
1230
+ ETHZ/eth02/images/image_00000230_0.png
1231
+ ETHZ/eth02/images/image_00000231_0.png
1232
+ ETHZ/eth02/images/image_00000232_0.png
1233
+ ETHZ/eth02/images/image_00000233_0.png
1234
+ ETHZ/eth02/images/image_00000234_0.png
1235
+ ETHZ/eth02/images/image_00000235_0.png
1236
+ ETHZ/eth02/images/image_00000236_0.png
1237
+ ETHZ/eth02/images/image_00000237_0.png
1238
+ ETHZ/eth02/images/image_00000238_0.png
1239
+ ETHZ/eth02/images/image_00000239_0.png
1240
+ ETHZ/eth02/images/image_00000240_0.png
1241
+ ETHZ/eth02/images/image_00000241_0.png
1242
+ ETHZ/eth02/images/image_00000242_0.png
1243
+ ETHZ/eth02/images/image_00000243_0.png
1244
+ ETHZ/eth02/images/image_00000244_0.png
1245
+ ETHZ/eth02/images/image_00000245_0.png
1246
+ ETHZ/eth02/images/image_00000246_0.png
1247
+ ETHZ/eth02/images/image_00000247_0.png
1248
+ ETHZ/eth02/images/image_00000248_0.png
1249
+ ETHZ/eth02/images/image_00000249_0.png
1250
+ ETHZ/eth02/images/image_00000250_0.png
1251
+ ETHZ/eth02/images/image_00000251_0.png
1252
+ ETHZ/eth02/images/image_00000252_0.png
1253
+ ETHZ/eth02/images/image_00000253_0.png
1254
+ ETHZ/eth02/images/image_00000254_0.png
1255
+ ETHZ/eth02/images/image_00000255_0.png
1256
+ ETHZ/eth02/images/image_00000256_0.png
1257
+ ETHZ/eth02/images/image_00000257_0.png
1258
+ ETHZ/eth02/images/image_00000258_0.png
1259
+ ETHZ/eth02/images/image_00000259_0.png
1260
+ ETHZ/eth02/images/image_00000260_0.png
1261
+ ETHZ/eth02/images/image_00000261_0.png
1262
+ ETHZ/eth02/images/image_00000262_0.png
1263
+ ETHZ/eth02/images/image_00000263_0.png
1264
+ ETHZ/eth02/images/image_00000264_0.png
1265
+ ETHZ/eth02/images/image_00000265_0.png
1266
+ ETHZ/eth02/images/image_00000266_0.png
1267
+ ETHZ/eth02/images/image_00000267_0.png
1268
+ ETHZ/eth02/images/image_00000268_0.png
1269
+ ETHZ/eth02/images/image_00000269_0.png
1270
+ ETHZ/eth02/images/image_00000270_0.png
1271
+ ETHZ/eth02/images/image_00000271_0.png
1272
+ ETHZ/eth02/images/image_00000272_0.png
1273
+ ETHZ/eth02/images/image_00000273_0.png
1274
+ ETHZ/eth02/images/image_00000274_0.png
1275
+ ETHZ/eth02/images/image_00000275_0.png
1276
+ ETHZ/eth02/images/image_00000276_0.png
1277
+ ETHZ/eth02/images/image_00000277_0.png
1278
+ ETHZ/eth02/images/image_00000278_0.png
1279
+ ETHZ/eth02/images/image_00000279_0.png
1280
+ ETHZ/eth02/images/image_00000280_0.png
1281
+ ETHZ/eth02/images/image_00000281_0.png
1282
+ ETHZ/eth02/images/image_00000282_0.png
1283
+ ETHZ/eth02/images/image_00000283_0.png
1284
+ ETHZ/eth02/images/image_00000284_0.png
1285
+ ETHZ/eth02/images/image_00000285_0.png
1286
+ ETHZ/eth02/images/image_00000286_0.png
1287
+ ETHZ/eth02/images/image_00000287_0.png
1288
+ ETHZ/eth02/images/image_00000288_0.png
1289
+ ETHZ/eth02/images/image_00000289_0.png
1290
+ ETHZ/eth02/images/image_00000290_0.png
1291
+ ETHZ/eth02/images/image_00000291_0.png
1292
+ ETHZ/eth02/images/image_00000292_0.png
1293
+ ETHZ/eth02/images/image_00000293_0.png
1294
+ ETHZ/eth02/images/image_00000294_0.png
1295
+ ETHZ/eth02/images/image_00000295_0.png
1296
+ ETHZ/eth02/images/image_00000296_0.png
1297
+ ETHZ/eth02/images/image_00000297_0.png
1298
+ ETHZ/eth02/images/image_00000298_0.png
1299
+ ETHZ/eth02/images/image_00000299_0.png
1300
+ ETHZ/eth02/images/image_00000300_0.png
1301
+ ETHZ/eth02/images/image_00000301_0.png
1302
+ ETHZ/eth02/images/image_00000302_0.png
1303
+ ETHZ/eth02/images/image_00000303_0.png
1304
+ ETHZ/eth02/images/image_00000304_0.png
1305
+ ETHZ/eth02/images/image_00000305_0.png
1306
+ ETHZ/eth02/images/image_00000306_0.png
1307
+ ETHZ/eth02/images/image_00000307_0.png
1308
+ ETHZ/eth02/images/image_00000308_0.png
1309
+ ETHZ/eth02/images/image_00000309_0.png
1310
+ ETHZ/eth02/images/image_00000310_0.png
1311
+ ETHZ/eth02/images/image_00000311_0.png
1312
+ ETHZ/eth02/images/image_00000312_0.png
1313
+ ETHZ/eth02/images/image_00000313_0.png
1314
+ ETHZ/eth02/images/image_00000314_0.png
1315
+ ETHZ/eth02/images/image_00000315_0.png
1316
+ ETHZ/eth02/images/image_00000316_0.png
1317
+ ETHZ/eth02/images/image_00000317_0.png
1318
+ ETHZ/eth02/images/image_00000318_0.png
1319
+ ETHZ/eth02/images/image_00000319_0.png
1320
+ ETHZ/eth02/images/image_00000320_0.png
1321
+ ETHZ/eth02/images/image_00000321_0.png
1322
+ ETHZ/eth02/images/image_00000322_0.png
1323
+ ETHZ/eth02/images/image_00000323_0.png
1324
+ ETHZ/eth02/images/image_00000324_0.png
1325
+ ETHZ/eth02/images/image_00000325_0.png
1326
+ ETHZ/eth02/images/image_00000326_0.png
1327
+ ETHZ/eth02/images/image_00000327_0.png
1328
+ ETHZ/eth02/images/image_00000328_0.png
1329
+ ETHZ/eth02/images/image_00000329_0.png
1330
+ ETHZ/eth02/images/image_00000330_0.png
1331
+ ETHZ/eth02/images/image_00000331_0.png
1332
+ ETHZ/eth02/images/image_00000332_0.png
1333
+ ETHZ/eth02/images/image_00000333_0.png
1334
+ ETHZ/eth02/images/image_00000334_0.png
1335
+ ETHZ/eth02/images/image_00000335_0.png
1336
+ ETHZ/eth02/images/image_00000336_0.png
1337
+ ETHZ/eth02/images/image_00000337_0.png
1338
+ ETHZ/eth02/images/image_00000338_0.png
1339
+ ETHZ/eth02/images/image_00000339_0.png
1340
+ ETHZ/eth02/images/image_00000340_0.png
1341
+ ETHZ/eth02/images/image_00000341_0.png
1342
+ ETHZ/eth02/images/image_00000342_0.png
1343
+ ETHZ/eth02/images/image_00000343_0.png
1344
+ ETHZ/eth02/images/image_00000344_0.png
1345
+ ETHZ/eth02/images/image_00000345_0.png
1346
+ ETHZ/eth02/images/image_00000346_0.png
1347
+ ETHZ/eth02/images/image_00000347_0.png
1348
+ ETHZ/eth02/images/image_00000348_0.png
1349
+ ETHZ/eth02/images/image_00000349_0.png
1350
+ ETHZ/eth02/images/image_00000350_0.png
1351
+ ETHZ/eth02/images/image_00000351_0.png
1352
+ ETHZ/eth02/images/image_00000352_0.png
1353
+ ETHZ/eth02/images/image_00000353_0.png
1354
+ ETHZ/eth02/images/image_00000354_0.png
1355
+ ETHZ/eth02/images/image_00000355_0.png
1356
+ ETHZ/eth02/images/image_00000356_0.png
1357
+ ETHZ/eth02/images/image_00000357_0.png
1358
+ ETHZ/eth02/images/image_00000358_0.png
1359
+ ETHZ/eth02/images/image_00000359_0.png
1360
+ ETHZ/eth02/images/image_00000360_0.png
1361
+ ETHZ/eth02/images/image_00000361_0.png
1362
+ ETHZ/eth02/images/image_00000362_0.png
1363
+ ETHZ/eth02/images/image_00000363_0.png
1364
+ ETHZ/eth02/images/image_00000364_0.png
1365
+ ETHZ/eth02/images/image_00000365_0.png
1366
+ ETHZ/eth02/images/image_00000366_0.png
1367
+ ETHZ/eth02/images/image_00000367_0.png
1368
+ ETHZ/eth02/images/image_00000368_0.png
1369
+ ETHZ/eth02/images/image_00000369_0.png
1370
+ ETHZ/eth02/images/image_00000370_0.png
1371
+ ETHZ/eth02/images/image_00000371_0.png
1372
+ ETHZ/eth02/images/image_00000372_0.png
1373
+ ETHZ/eth02/images/image_00000373_0.png
1374
+ ETHZ/eth02/images/image_00000374_0.png
1375
+ ETHZ/eth02/images/image_00000375_0.png
1376
+ ETHZ/eth02/images/image_00000376_0.png
1377
+ ETHZ/eth02/images/image_00000377_0.png
1378
+ ETHZ/eth02/images/image_00000378_0.png
1379
+ ETHZ/eth02/images/image_00000379_0.png
1380
+ ETHZ/eth02/images/image_00000380_0.png
1381
+ ETHZ/eth02/images/image_00000381_0.png
1382
+ ETHZ/eth02/images/image_00000382_0.png
1383
+ ETHZ/eth02/images/image_00000383_0.png
1384
+ ETHZ/eth02/images/image_00000384_0.png
1385
+ ETHZ/eth02/images/image_00000385_0.png
1386
+ ETHZ/eth02/images/image_00000386_0.png
1387
+ ETHZ/eth02/images/image_00000387_0.png
1388
+ ETHZ/eth02/images/image_00000388_0.png
1389
+ ETHZ/eth02/images/image_00000389_0.png
1390
+ ETHZ/eth02/images/image_00000390_0.png
1391
+ ETHZ/eth02/images/image_00000391_0.png
1392
+ ETHZ/eth02/images/image_00000392_0.png
1393
+ ETHZ/eth02/images/image_00000393_0.png
1394
+ ETHZ/eth02/images/image_00000394_0.png
1395
+ ETHZ/eth02/images/image_00000395_0.png
1396
+ ETHZ/eth02/images/image_00000396_0.png
1397
+ ETHZ/eth02/images/image_00000397_0.png
1398
+ ETHZ/eth02/images/image_00000398_0.png
1399
+ ETHZ/eth02/images/image_00000399_0.png
1400
+ ETHZ/eth02/images/image_00000400_0.png
1401
+ ETHZ/eth02/images/image_00000401_0.png
1402
+ ETHZ/eth02/images/image_00000402_0.png
1403
+ ETHZ/eth02/images/image_00000403_0.png
1404
+ ETHZ/eth02/images/image_00000404_0.png
1405
+ ETHZ/eth02/images/image_00000405_0.png
1406
+ ETHZ/eth02/images/image_00000406_0.png
1407
+ ETHZ/eth02/images/image_00000407_0.png
1408
+ ETHZ/eth02/images/image_00000408_0.png
1409
+ ETHZ/eth02/images/image_00000409_0.png
1410
+ ETHZ/eth02/images/image_00000410_0.png
1411
+ ETHZ/eth02/images/image_00000411_0.png
1412
+ ETHZ/eth02/images/image_00000412_0.png
1413
+ ETHZ/eth02/images/image_00000413_0.png
1414
+ ETHZ/eth02/images/image_00000414_0.png
1415
+ ETHZ/eth02/images/image_00000415_0.png
1416
+ ETHZ/eth02/images/image_00000416_0.png
1417
+ ETHZ/eth02/images/image_00000417_0.png
1418
+ ETHZ/eth02/images/image_00000418_0.png
1419
+ ETHZ/eth02/images/image_00000419_0.png
1420
+ ETHZ/eth02/images/image_00000420_0.png
1421
+ ETHZ/eth02/images/image_00000421_0.png
1422
+ ETHZ/eth02/images/image_00000422_0.png
1423
+ ETHZ/eth02/images/image_00000423_0.png
1424
+ ETHZ/eth02/images/image_00000424_0.png
1425
+ ETHZ/eth02/images/image_00000425_0.png
1426
+ ETHZ/eth02/images/image_00000426_0.png
1427
+ ETHZ/eth02/images/image_00000427_0.png
1428
+ ETHZ/eth02/images/image_00000428_0.png
1429
+ ETHZ/eth02/images/image_00000429_0.png
1430
+ ETHZ/eth02/images/image_00000430_0.png
1431
+ ETHZ/eth02/images/image_00000431_0.png
1432
+ ETHZ/eth02/images/image_00000432_0.png
1433
+ ETHZ/eth02/images/image_00000433_0.png
1434
+ ETHZ/eth02/images/image_00000434_0.png
1435
+ ETHZ/eth02/images/image_00000435_0.png
1436
+ ETHZ/eth02/images/image_00000436_0.png
1437
+ ETHZ/eth02/images/image_00000437_0.png
1438
+ ETHZ/eth02/images/image_00000438_0.png
1439
+ ETHZ/eth02/images/image_00000439_0.png
1440
+ ETHZ/eth02/images/image_00000440_0.png
1441
+ ETHZ/eth02/images/image_00000441_0.png
1442
+ ETHZ/eth02/images/image_00000442_0.png
1443
+ ETHZ/eth02/images/image_00000443_0.png
1444
+ ETHZ/eth02/images/image_00000444_0.png
1445
+ ETHZ/eth02/images/image_00000445_0.png
1446
+ ETHZ/eth03/images/image_00000100_0.png
1447
+ ETHZ/eth03/images/image_00000101_0.png
1448
+ ETHZ/eth03/images/image_00000102_0.png
1449
+ ETHZ/eth03/images/image_00000103_0.png
1450
+ ETHZ/eth03/images/image_00000104_0.png
1451
+ ETHZ/eth03/images/image_00000105_0.png
1452
+ ETHZ/eth03/images/image_00000106_0.png
1453
+ ETHZ/eth03/images/image_00000107_0.png
1454
+ ETHZ/eth03/images/image_00000108_0.png
1455
+ ETHZ/eth03/images/image_00000109_0.png
1456
+ ETHZ/eth03/images/image_00000110_0.png
1457
+ ETHZ/eth03/images/image_00000111_0.png
1458
+ ETHZ/eth03/images/image_00000112_0.png
1459
+ ETHZ/eth03/images/image_00000113_0.png
1460
+ ETHZ/eth03/images/image_00000114_0.png
1461
+ ETHZ/eth03/images/image_00000115_0.png
1462
+ ETHZ/eth03/images/image_00000116_0.png
1463
+ ETHZ/eth03/images/image_00000117_0.png
1464
+ ETHZ/eth03/images/image_00000118_0.png
1465
+ ETHZ/eth03/images/image_00000119_0.png
1466
+ ETHZ/eth03/images/image_00000120_0.png
1467
+ ETHZ/eth03/images/image_00000121_0.png
1468
+ ETHZ/eth03/images/image_00000122_0.png
1469
+ ETHZ/eth03/images/image_00000123_0.png
1470
+ ETHZ/eth03/images/image_00000124_0.png
1471
+ ETHZ/eth03/images/image_00000125_0.png
1472
+ ETHZ/eth03/images/image_00000126_0.png
1473
+ ETHZ/eth03/images/image_00000127_0.png
1474
+ ETHZ/eth03/images/image_00000128_0.png
1475
+ ETHZ/eth03/images/image_00000129_0.png
1476
+ ETHZ/eth03/images/image_00000130_0.png
1477
+ ETHZ/eth03/images/image_00000131_0.png
1478
+ ETHZ/eth03/images/image_00000132_0.png
1479
+ ETHZ/eth03/images/image_00000133_0.png
1480
+ ETHZ/eth03/images/image_00000134_0.png
1481
+ ETHZ/eth03/images/image_00000135_0.png
1482
+ ETHZ/eth03/images/image_00000136_0.png
1483
+ ETHZ/eth03/images/image_00000137_0.png
1484
+ ETHZ/eth03/images/image_00000138_0.png
1485
+ ETHZ/eth03/images/image_00000139_0.png
1486
+ ETHZ/eth03/images/image_00000140_0.png
1487
+ ETHZ/eth03/images/image_00000141_0.png
1488
+ ETHZ/eth03/images/image_00000142_0.png
1489
+ ETHZ/eth03/images/image_00000143_0.png
1490
+ ETHZ/eth03/images/image_00000144_0.png
1491
+ ETHZ/eth03/images/image_00000145_0.png
1492
+ ETHZ/eth03/images/image_00000146_0.png
1493
+ ETHZ/eth03/images/image_00000147_0.png
1494
+ ETHZ/eth03/images/image_00000148_0.png
1495
+ ETHZ/eth03/images/image_00000149_0.png
1496
+ ETHZ/eth03/images/image_00000150_0.png
1497
+ ETHZ/eth03/images/image_00000151_0.png
1498
+ ETHZ/eth03/images/image_00000152_0.png
1499
+ ETHZ/eth03/images/image_00000153_0.png
1500
+ ETHZ/eth03/images/image_00000154_0.png
1501
+ ETHZ/eth03/images/image_00000155_0.png
1502
+ ETHZ/eth03/images/image_00000156_0.png
1503
+ ETHZ/eth03/images/image_00000157_0.png
1504
+ ETHZ/eth03/images/image_00000158_0.png
1505
+ ETHZ/eth03/images/image_00000159_0.png
1506
+ ETHZ/eth03/images/image_00000160_0.png
1507
+ ETHZ/eth03/images/image_00000161_0.png
1508
+ ETHZ/eth03/images/image_00000162_0.png
1509
+ ETHZ/eth03/images/image_00000163_0.png
1510
+ ETHZ/eth03/images/image_00000164_0.png
1511
+ ETHZ/eth03/images/image_00000165_0.png
1512
+ ETHZ/eth03/images/image_00000166_0.png
1513
+ ETHZ/eth03/images/image_00000167_0.png
1514
+ ETHZ/eth03/images/image_00000168_0.png
1515
+ ETHZ/eth03/images/image_00000169_0.png
1516
+ ETHZ/eth03/images/image_00000170_0.png
1517
+ ETHZ/eth03/images/image_00000171_0.png
1518
+ ETHZ/eth03/images/image_00000172_0.png
1519
+ ETHZ/eth03/images/image_00000173_0.png
1520
+ ETHZ/eth03/images/image_00000174_0.png
1521
+ ETHZ/eth03/images/image_00000175_0.png
1522
+ ETHZ/eth03/images/image_00000176_0.png
1523
+ ETHZ/eth03/images/image_00000177_0.png
1524
+ ETHZ/eth03/images/image_00000178_0.png
1525
+ ETHZ/eth03/images/image_00000179_0.png
1526
+ ETHZ/eth03/images/image_00000180_0.png
1527
+ ETHZ/eth03/images/image_00000181_0.png
1528
+ ETHZ/eth03/images/image_00000182_0.png
1529
+ ETHZ/eth03/images/image_00000183_0.png
1530
+ ETHZ/eth03/images/image_00000184_0.png
1531
+ ETHZ/eth03/images/image_00000185_0.png
1532
+ ETHZ/eth03/images/image_00000186_0.png
1533
+ ETHZ/eth03/images/image_00000187_0.png
1534
+ ETHZ/eth03/images/image_00000188_0.png
1535
+ ETHZ/eth03/images/image_00000189_0.png
1536
+ ETHZ/eth03/images/image_00000190_0.png
1537
+ ETHZ/eth03/images/image_00000191_0.png
1538
+ ETHZ/eth03/images/image_00000192_0.png
1539
+ ETHZ/eth03/images/image_00000193_0.png
1540
+ ETHZ/eth03/images/image_00000194_0.png
1541
+ ETHZ/eth03/images/image_00000195_0.png
1542
+ ETHZ/eth03/images/image_00000196_0.png
1543
+ ETHZ/eth03/images/image_00000197_0.png
1544
+ ETHZ/eth03/images/image_00000198_0.png
1545
+ ETHZ/eth03/images/image_00000199_0.png
1546
+ ETHZ/eth03/images/image_00000200_0.png
1547
+ ETHZ/eth03/images/image_00000201_0.png
1548
+ ETHZ/eth03/images/image_00000202_0.png
1549
+ ETHZ/eth03/images/image_00000203_0.png
1550
+ ETHZ/eth03/images/image_00000204_0.png
1551
+ ETHZ/eth03/images/image_00000205_0.png
1552
+ ETHZ/eth03/images/image_00000206_0.png
1553
+ ETHZ/eth03/images/image_00000207_0.png
1554
+ ETHZ/eth03/images/image_00000208_0.png
1555
+ ETHZ/eth03/images/image_00000209_0.png
1556
+ ETHZ/eth03/images/image_00000210_0.png
1557
+ ETHZ/eth03/images/image_00000211_0.png
1558
+ ETHZ/eth03/images/image_00000212_0.png
1559
+ ETHZ/eth03/images/image_00000213_0.png
1560
+ ETHZ/eth03/images/image_00000214_0.png
1561
+ ETHZ/eth03/images/image_00000215_0.png
1562
+ ETHZ/eth03/images/image_00000216_0.png
1563
+ ETHZ/eth03/images/image_00000217_0.png
1564
+ ETHZ/eth03/images/image_00000218_0.png
1565
+ ETHZ/eth03/images/image_00000219_0.png
1566
+ ETHZ/eth03/images/image_00000220_0.png
1567
+ ETHZ/eth03/images/image_00000221_0.png
1568
+ ETHZ/eth03/images/image_00000222_0.png
1569
+ ETHZ/eth03/images/image_00000223_0.png
1570
+ ETHZ/eth03/images/image_00000224_0.png
1571
+ ETHZ/eth03/images/image_00000225_0.png
1572
+ ETHZ/eth03/images/image_00000226_0.png
1573
+ ETHZ/eth03/images/image_00000227_0.png
1574
+ ETHZ/eth03/images/image_00000228_0.png
1575
+ ETHZ/eth03/images/image_00000229_0.png
1576
+ ETHZ/eth03/images/image_00000230_0.png
1577
+ ETHZ/eth03/images/image_00000231_0.png
1578
+ ETHZ/eth03/images/image_00000232_0.png
1579
+ ETHZ/eth03/images/image_00000233_0.png
1580
+ ETHZ/eth03/images/image_00000234_0.png
1581
+ ETHZ/eth03/images/image_00000235_0.png
1582
+ ETHZ/eth03/images/image_00000236_0.png
1583
+ ETHZ/eth03/images/image_00000237_0.png
1584
+ ETHZ/eth03/images/image_00000238_0.png
1585
+ ETHZ/eth03/images/image_00000239_0.png
1586
+ ETHZ/eth03/images/image_00000240_0.png
1587
+ ETHZ/eth03/images/image_00000241_0.png
1588
+ ETHZ/eth03/images/image_00000242_0.png
1589
+ ETHZ/eth03/images/image_00000243_0.png
1590
+ ETHZ/eth03/images/image_00000244_0.png
1591
+ ETHZ/eth03/images/image_00000245_0.png
1592
+ ETHZ/eth03/images/image_00000246_0.png
1593
+ ETHZ/eth03/images/image_00000247_0.png
1594
+ ETHZ/eth03/images/image_00000248_0.png
1595
+ ETHZ/eth03/images/image_00000249_0.png
1596
+ ETHZ/eth03/images/image_00000250_0.png
1597
+ ETHZ/eth03/images/image_00000251_0.png
1598
+ ETHZ/eth03/images/image_00000252_0.png
1599
+ ETHZ/eth03/images/image_00000253_0.png
1600
+ ETHZ/eth03/images/image_00000254_0.png
1601
+ ETHZ/eth03/images/image_00000255_0.png
1602
+ ETHZ/eth03/images/image_00000256_0.png
1603
+ ETHZ/eth03/images/image_00000257_0.png
1604
+ ETHZ/eth03/images/image_00000258_0.png
1605
+ ETHZ/eth03/images/image_00000259_0.png
1606
+ ETHZ/eth03/images/image_00000260_0.png
1607
+ ETHZ/eth03/images/image_00000261_0.png
1608
+ ETHZ/eth03/images/image_00000262_0.png
1609
+ ETHZ/eth03/images/image_00000263_0.png
1610
+ ETHZ/eth03/images/image_00000264_0.png
1611
+ ETHZ/eth03/images/image_00000265_0.png
1612
+ ETHZ/eth03/images/image_00000266_0.png
1613
+ ETHZ/eth03/images/image_00000267_0.png
1614
+ ETHZ/eth03/images/image_00000268_0.png
1615
+ ETHZ/eth03/images/image_00000269_0.png
1616
+ ETHZ/eth03/images/image_00000270_0.png
1617
+ ETHZ/eth03/images/image_00000271_0.png
1618
+ ETHZ/eth03/images/image_00000272_0.png
1619
+ ETHZ/eth03/images/image_00000273_0.png
1620
+ ETHZ/eth03/images/image_00000274_0.png
1621
+ ETHZ/eth03/images/image_00000275_0.png
1622
+ ETHZ/eth03/images/image_00000276_0.png
1623
+ ETHZ/eth03/images/image_00000277_0.png
1624
+ ETHZ/eth03/images/image_00000278_0.png
1625
+ ETHZ/eth03/images/image_00000279_0.png
1626
+ ETHZ/eth03/images/image_00000280_0.png
1627
+ ETHZ/eth03/images/image_00000281_0.png
1628
+ ETHZ/eth03/images/image_00000282_0.png
1629
+ ETHZ/eth03/images/image_00000283_0.png
1630
+ ETHZ/eth03/images/image_00000284_0.png
1631
+ ETHZ/eth03/images/image_00000285_0.png
1632
+ ETHZ/eth03/images/image_00000286_0.png
1633
+ ETHZ/eth03/images/image_00000287_0.png
1634
+ ETHZ/eth03/images/image_00000288_0.png
1635
+ ETHZ/eth03/images/image_00000289_0.png
1636
+ ETHZ/eth03/images/image_00000290_0.png
1637
+ ETHZ/eth03/images/image_00000291_0.png
1638
+ ETHZ/eth03/images/image_00000292_0.png
1639
+ ETHZ/eth03/images/image_00000293_0.png
1640
+ ETHZ/eth03/images/image_00000294_0.png
1641
+ ETHZ/eth03/images/image_00000295_0.png
1642
+ ETHZ/eth03/images/image_00000296_0.png
1643
+ ETHZ/eth03/images/image_00000297_0.png
1644
+ ETHZ/eth03/images/image_00000298_0.png
1645
+ ETHZ/eth03/images/image_00000299_0.png
1646
+ ETHZ/eth03/images/image_00000300_0.png
1647
+ ETHZ/eth03/images/image_00000301_0.png
1648
+ ETHZ/eth03/images/image_00000302_0.png
1649
+ ETHZ/eth03/images/image_00000303_0.png
1650
+ ETHZ/eth03/images/image_00000304_0.png
1651
+ ETHZ/eth03/images/image_00000305_0.png
1652
+ ETHZ/eth03/images/image_00000306_0.png
1653
+ ETHZ/eth03/images/image_00000307_0.png
1654
+ ETHZ/eth03/images/image_00000308_0.png
1655
+ ETHZ/eth03/images/image_00000309_0.png
1656
+ ETHZ/eth03/images/image_00000310_0.png
1657
+ ETHZ/eth03/images/image_00000311_0.png
1658
+ ETHZ/eth03/images/image_00000312_0.png
1659
+ ETHZ/eth03/images/image_00000313_0.png
1660
+ ETHZ/eth03/images/image_00000314_0.png
1661
+ ETHZ/eth03/images/image_00000315_0.png
1662
+ ETHZ/eth03/images/image_00000316_0.png
1663
+ ETHZ/eth03/images/image_00000317_0.png
1664
+ ETHZ/eth03/images/image_00000318_0.png
1665
+ ETHZ/eth03/images/image_00000319_0.png
1666
+ ETHZ/eth03/images/image_00000320_0.png
1667
+ ETHZ/eth03/images/image_00000321_0.png
1668
+ ETHZ/eth03/images/image_00000322_0.png
1669
+ ETHZ/eth03/images/image_00000323_0.png
1670
+ ETHZ/eth03/images/image_00000324_0.png
1671
+ ETHZ/eth03/images/image_00000325_0.png
1672
+ ETHZ/eth03/images/image_00000326_0.png
1673
+ ETHZ/eth03/images/image_00000327_0.png
1674
+ ETHZ/eth03/images/image_00000328_0.png
1675
+ ETHZ/eth03/images/image_00000329_0.png
1676
+ ETHZ/eth03/images/image_00000330_0.png
1677
+ ETHZ/eth03/images/image_00000331_0.png
1678
+ ETHZ/eth03/images/image_00000332_0.png
1679
+ ETHZ/eth03/images/image_00000333_0.png
1680
+ ETHZ/eth03/images/image_00000334_0.png
1681
+ ETHZ/eth03/images/image_00000335_0.png
1682
+ ETHZ/eth03/images/image_00000336_0.png
1683
+ ETHZ/eth03/images/image_00000337_0.png
1684
+ ETHZ/eth03/images/image_00000338_0.png
1685
+ ETHZ/eth03/images/image_00000339_0.png
1686
+ ETHZ/eth03/images/image_00000340_0.png
1687
+ ETHZ/eth03/images/image_00000341_0.png
1688
+ ETHZ/eth03/images/image_00000342_0.png
1689
+ ETHZ/eth03/images/image_00000343_0.png
1690
+ ETHZ/eth03/images/image_00000344_0.png
1691
+ ETHZ/eth03/images/image_00000345_0.png
1692
+ ETHZ/eth03/images/image_00000346_0.png
1693
+ ETHZ/eth03/images/image_00000347_0.png
1694
+ ETHZ/eth03/images/image_00000348_0.png
1695
+ ETHZ/eth03/images/image_00000349_0.png
1696
+ ETHZ/eth03/images/image_00000350_0.png
1697
+ ETHZ/eth03/images/image_00000351_0.png
1698
+ ETHZ/eth03/images/image_00000352_0.png
1699
+ ETHZ/eth03/images/image_00000353_0.png
1700
+ ETHZ/eth03/images/image_00000354_0.png
1701
+ ETHZ/eth03/images/image_00000355_0.png
1702
+ ETHZ/eth03/images/image_00000356_0.png
1703
+ ETHZ/eth03/images/image_00000357_0.png
1704
+ ETHZ/eth03/images/image_00000358_0.png
1705
+ ETHZ/eth03/images/image_00000359_0.png
1706
+ ETHZ/eth03/images/image_00000360_0.png
1707
+ ETHZ/eth03/images/image_00000361_0.png
1708
+ ETHZ/eth03/images/image_00000362_0.png
1709
+ ETHZ/eth03/images/image_00000363_0.png
1710
+ ETHZ/eth03/images/image_00000364_0.png
1711
+ ETHZ/eth03/images/image_00000365_0.png
1712
+ ETHZ/eth03/images/image_00000366_0.png
1713
+ ETHZ/eth03/images/image_00000367_0.png
1714
+ ETHZ/eth03/images/image_00000368_0.png
1715
+ ETHZ/eth03/images/image_00000369_0.png
1716
+ ETHZ/eth03/images/image_00000370_0.png
1717
+ ETHZ/eth03/images/image_00000371_0.png
1718
+ ETHZ/eth03/images/image_00000372_0.png
1719
+ ETHZ/eth03/images/image_00000373_0.png
1720
+ ETHZ/eth03/images/image_00000374_0.png
1721
+ ETHZ/eth03/images/image_00000375_0.png
1722
+ ETHZ/eth03/images/image_00000376_0.png
1723
+ ETHZ/eth03/images/image_00000377_0.png
1724
+ ETHZ/eth03/images/image_00000378_0.png
1725
+ ETHZ/eth03/images/image_00000379_0.png
1726
+ ETHZ/eth03/images/image_00000380_0.png
1727
+ ETHZ/eth03/images/image_00000381_0.png
1728
+ ETHZ/eth03/images/image_00000382_0.png
1729
+ ETHZ/eth03/images/image_00000383_0.png
1730
+ ETHZ/eth03/images/image_00000384_0.png
1731
+ ETHZ/eth03/images/image_00000385_0.png
1732
+ ETHZ/eth03/images/image_00000386_0.png
1733
+ ETHZ/eth03/images/image_00000387_0.png
1734
+ ETHZ/eth03/images/image_00000388_0.png
1735
+ ETHZ/eth03/images/image_00000389_0.png
1736
+ ETHZ/eth03/images/image_00000390_0.png
1737
+ ETHZ/eth03/images/image_00000391_0.png
1738
+ ETHZ/eth03/images/image_00000392_0.png
1739
+ ETHZ/eth03/images/image_00000393_0.png
1740
+ ETHZ/eth03/images/image_00000394_0.png
1741
+ ETHZ/eth03/images/image_00000395_0.png
1742
+ ETHZ/eth03/images/image_00000396_0.png
1743
+ ETHZ/eth03/images/image_00000397_0.png
1744
+ ETHZ/eth03/images/image_00000398_0.png
1745
+ ETHZ/eth03/images/image_00000399_0.png
1746
+ ETHZ/eth03/images/image_00000400_0.png
1747
+ ETHZ/eth03/images/image_00000401_0.png
1748
+ ETHZ/eth03/images/image_00000402_0.png
1749
+ ETHZ/eth03/images/image_00000403_0.png
1750
+ ETHZ/eth03/images/image_00000404_0.png
1751
+ ETHZ/eth03/images/image_00000405_0.png
1752
+ ETHZ/eth03/images/image_00000406_0.png
1753
+ ETHZ/eth03/images/image_00000407_0.png
1754
+ ETHZ/eth03/images/image_00000408_0.png
1755
+ ETHZ/eth03/images/image_00000409_0.png
1756
+ ETHZ/eth03/images/image_00000410_0.png
1757
+ ETHZ/eth03/images/image_00000411_0.png
1758
+ ETHZ/eth03/images/image_00000412_0.png
1759
+ ETHZ/eth03/images/image_00000413_0.png
1760
+ ETHZ/eth03/images/image_00000414_0.png
1761
+ ETHZ/eth03/images/image_00000415_0.png
1762
+ ETHZ/eth03/images/image_00000416_0.png
1763
+ ETHZ/eth03/images/image_00000417_0.png
1764
+ ETHZ/eth03/images/image_00000418_0.png
1765
+ ETHZ/eth03/images/image_00000419_0.png
1766
+ ETHZ/eth03/images/image_00000420_0.png
1767
+ ETHZ/eth03/images/image_00000421_0.png
1768
+ ETHZ/eth03/images/image_00000422_0.png
1769
+ ETHZ/eth03/images/image_00000423_0.png
1770
+ ETHZ/eth03/images/image_00000424_0.png
1771
+ ETHZ/eth03/images/image_00000425_0.png
1772
+ ETHZ/eth03/images/image_00000426_0.png
1773
+ ETHZ/eth03/images/image_00000427_0.png
1774
+ ETHZ/eth03/images/image_00000428_0.png
1775
+ ETHZ/eth03/images/image_00000429_0.png
1776
+ ETHZ/eth03/images/image_00000430_0.png
1777
+ ETHZ/eth03/images/image_00000431_0.png
1778
+ ETHZ/eth03/images/image_00000432_0.png
1779
+ ETHZ/eth03/images/image_00000433_0.png
1780
+ ETHZ/eth03/images/image_00000434_0.png
1781
+ ETHZ/eth03/images/image_00000435_0.png
1782
+ ETHZ/eth03/images/image_00000436_0.png
1783
+ ETHZ/eth03/images/image_00000437_0.png
1784
+ ETHZ/eth03/images/image_00000438_0.png
1785
+ ETHZ/eth03/images/image_00000439_0.png
1786
+ ETHZ/eth03/images/image_00000440_0.png
1787
+ ETHZ/eth03/images/image_00000441_0.png
1788
+ ETHZ/eth03/images/image_00000442_0.png
1789
+ ETHZ/eth03/images/image_00000443_0.png
1790
+ ETHZ/eth03/images/image_00000444_0.png
1791
+ ETHZ/eth03/images/image_00000445_0.png
1792
+ ETHZ/eth03/images/image_00000446_0.png
1793
+ ETHZ/eth03/images/image_00000447_0.png
1794
+ ETHZ/eth03/images/image_00000448_0.png
1795
+ ETHZ/eth03/images/image_00000449_0.png
1796
+ ETHZ/eth03/images/image_00000450_0.png
1797
+ ETHZ/eth03/images/image_00000451_0.png
1798
+ ETHZ/eth03/images/image_00000452_0.png
1799
+ ETHZ/eth03/images/image_00000453_0.png
1800
+ ETHZ/eth05/images/image_00000000_0.png
1801
+ ETHZ/eth05/images/image_00000004_0.png
1802
+ ETHZ/eth05/images/image_00000008_0.png
1803
+ ETHZ/eth05/images/image_00000012_0.png
1804
+ ETHZ/eth05/images/image_00000016_0.png
1805
+ ETHZ/eth05/images/image_00000022_0.png
1806
+ ETHZ/eth05/images/image_00000026_0.png
1807
+ ETHZ/eth05/images/image_00000030_0.png
1808
+ ETHZ/eth05/images/image_00000034_0.png
1809
+ ETHZ/eth05/images/image_00000038_0.png
1810
+ ETHZ/eth05/images/image_00000042_0.png
1811
+ ETHZ/eth05/images/image_00000046_0.png
1812
+ ETHZ/eth05/images/image_00000050_0.png
1813
+ ETHZ/eth05/images/image_00000054_0.png
1814
+ ETHZ/eth05/images/image_00000058_0.png
1815
+ ETHZ/eth05/images/image_00000062_0.png
1816
+ ETHZ/eth05/images/image_00000066_0.png
1817
+ ETHZ/eth05/images/image_00000070_0.png
1818
+ ETHZ/eth05/images/image_00000074_0.png
1819
+ ETHZ/eth05/images/image_00000078_0.png
1820
+ ETHZ/eth05/images/image_00000082_0.png
1821
+ ETHZ/eth05/images/image_00000086_0.png
1822
+ ETHZ/eth05/images/image_00000090_0.png
1823
+ ETHZ/eth05/images/image_00000094_0.png
1824
+ ETHZ/eth05/images/image_00000098_0.png
1825
+ ETHZ/eth05/images/image_00000101_0.png
1826
+ ETHZ/eth05/images/image_00000105_0.png
1827
+ ETHZ/eth05/images/image_00000109_0.png
1828
+ ETHZ/eth05/images/image_00000113_0.png
1829
+ ETHZ/eth05/images/image_00000115_0.png
1830
+ ETHZ/eth05/images/image_00000119_0.png
1831
+ ETHZ/eth05/images/image_00000123_0.png
1832
+ ETHZ/eth05/images/image_00000127_0.png
1833
+ ETHZ/eth05/images/image_00000130_0.png
1834
+ ETHZ/eth05/images/image_00000134_0.png
1835
+ ETHZ/eth05/images/image_00000138_0.png
1836
+ ETHZ/eth05/images/image_00000142_0.png
1837
+ ETHZ/eth05/images/image_00000145_0.png
1838
+ ETHZ/eth05/images/image_00000149_0.png
1839
+ ETHZ/eth05/images/image_00000153_0.png
1840
+ ETHZ/eth05/images/image_00000157_0.png
1841
+ ETHZ/eth05/images/image_00000161_0.png
1842
+ ETHZ/eth05/images/image_00000165_0.png
1843
+ ETHZ/eth05/images/image_00000169_0.png
1844
+ ETHZ/eth05/images/image_00000173_0.png
1845
+ ETHZ/eth05/images/image_00000177_0.png
1846
+ ETHZ/eth05/images/image_00000181_0.png
1847
+ ETHZ/eth05/images/image_00000185_0.png
1848
+ ETHZ/eth05/images/image_00000189_0.png
1849
+ ETHZ/eth05/images/image_00000193_0.png
1850
+ ETHZ/eth05/images/image_00000197_0.png
1851
+ ETHZ/eth05/images/image_00000201_0.png
1852
+ ETHZ/eth05/images/image_00000205_0.png
1853
+ ETHZ/eth05/images/image_00000209_0.png
1854
+ ETHZ/eth05/images/image_00000213_0.png
1855
+ ETHZ/eth05/images/image_00000217_0.png
1856
+ ETHZ/eth07/images/image_00004900_0.png
1857
+ ETHZ/eth07/images/image_00004904_0.png
1858
+ ETHZ/eth07/images/image_00004908_0.png
1859
+ ETHZ/eth07/images/image_00004912_0.png
1860
+ ETHZ/eth07/images/image_00004916_0.png
1861
+ ETHZ/eth07/images/image_00004920_0.png
1862
+ ETHZ/eth07/images/image_00004924_0.png
1863
+ ETHZ/eth07/images/image_00004928_0.png
1864
+ ETHZ/eth07/images/image_00004932_0.png
1865
+ ETHZ/eth07/images/image_00004936_0.png
1866
+ ETHZ/eth07/images/image_00004940_0.png
1867
+ ETHZ/eth07/images/image_00004944_0.png
1868
+ ETHZ/eth07/images/image_00004948_0.png
1869
+ ETHZ/eth07/images/image_00004952_0.png
1870
+ ETHZ/eth07/images/image_00004956_0.png
1871
+ ETHZ/eth07/images/image_00004960_0.png
1872
+ ETHZ/eth07/images/image_00004964_0.png
1873
+ ETHZ/eth07/images/image_00004968_0.png
1874
+ ETHZ/eth07/images/image_00004972_0.png
1875
+ ETHZ/eth07/images/image_00004976_0.png
1876
+ ETHZ/eth07/images/image_00004980_0.png
1877
+ ETHZ/eth07/images/image_00004984_0.png
1878
+ ETHZ/eth07/images/image_00004988_0.png
1879
+ ETHZ/eth07/images/image_00004992_0.png
1880
+ ETHZ/eth07/images/image_00004996_0.png
1881
+ ETHZ/eth07/images/image_00005000_0.png
1882
+ ETHZ/eth07/images/image_00005004_0.png
1883
+ ETHZ/eth07/images/image_00005008_0.png
1884
+ ETHZ/eth07/images/image_00005012_0.png
1885
+ ETHZ/eth07/images/image_00005016_0.png
1886
+ ETHZ/eth07/images/image_00005020_0.png
1887
+ ETHZ/eth07/images/image_00005024_0.png
1888
+ ETHZ/eth07/images/image_00005028_0.png
1889
+ ETHZ/eth07/images/image_00005032_0.png
1890
+ ETHZ/eth07/images/image_00005036_0.png
1891
+ ETHZ/eth07/images/image_00005040_0.png
1892
+ ETHZ/eth07/images/image_00005044_0.png
1893
+ ETHZ/eth07/images/image_00005048_0.png
1894
+ ETHZ/eth07/images/image_00005052_0.png
1895
+ ETHZ/eth07/images/image_00005056_0.png
1896
+ ETHZ/eth07/images/image_00005060_0.png
1897
+ ETHZ/eth07/images/image_00005064_0.png
1898
+ ETHZ/eth07/images/image_00005068_0.png
1899
+ ETHZ/eth07/images/image_00005072_0.png
1900
+ ETHZ/eth07/images/image_00005076_0.png
1901
+ ETHZ/eth07/images/image_00005080_0.png
1902
+ ETHZ/eth07/images/image_00005084_0.png
1903
+ ETHZ/eth07/images/image_00005088_0.png
1904
+ ETHZ/eth07/images/image_00005092_0.png
1905
+ ETHZ/eth07/images/image_00005096_0.png
1906
+ ETHZ/eth07/images/image_00005100_0.png
1907
+ ETHZ/eth07/images/image_00005104_0.png
1908
+ ETHZ/eth07/images/image_00005108_0.png
1909
+ ETHZ/eth07/images/image_00005112_0.png
1910
+ ETHZ/eth07/images/image_00005116_0.png
1911
+ ETHZ/eth07/images/image_00005120_0.png
1912
+ ETHZ/eth07/images/image_00005124_0.png
1913
+ ETHZ/eth07/images/image_00005128_0.png
1914
+ ETHZ/eth07/images/image_00005132_0.png
1915
+ ETHZ/eth07/images/image_00005136_0.png
1916
+ ETHZ/eth07/images/image_00005140_0.png
1917
+ ETHZ/eth07/images/image_00005144_0.png
1918
+ ETHZ/eth07/images/image_00005148_0.png
1919
+ ETHZ/eth07/images/image_00005152_0.png
1920
+ ETHZ/eth07/images/image_00005156_0.png
1921
+ ETHZ/eth07/images/image_00005160_0.png
1922
+ ETHZ/eth07/images/image_00005164_0.png
1923
+ ETHZ/eth07/images/image_00005168_0.png
1924
+ ETHZ/eth07/images/image_00005172_0.png
1925
+ ETHZ/eth07/images/image_00005176_0.png
1926
+ ETHZ/eth07/images/image_00005180_0.png
1927
+ ETHZ/eth07/images/image_00005184_0.png
1928
+ ETHZ/eth07/images/image_00005188_0.png
1929
+ ETHZ/eth07/images/image_00005192_0.png
1930
+ ETHZ/eth07/images/image_00005196_0.png
1931
+ ETHZ/eth07/images/image_00005200_0.png
1932
+ ETHZ/eth07/images/image_00005204_0.png
1933
+ ETHZ/eth07/images/image_00005208_0.png
1934
+ ETHZ/eth07/images/image_00005212_0.png
1935
+ ETHZ/eth07/images/image_00005216_0.png
1936
+ ETHZ/eth07/images/image_00005220_0.png
1937
+ ETHZ/eth07/images/image_00005224_0.png
1938
+ ETHZ/eth07/images/image_00005228_0.png
1939
+ ETHZ/eth07/images/image_00005232_0.png
1940
+ ETHZ/eth07/images/image_00005236_0.png
1941
+ ETHZ/eth07/images/image_00005240_0.png
1942
+ ETHZ/eth07/images/image_00005244_0.png
1943
+ ETHZ/eth07/images/image_00005248_0.png
1944
+ ETHZ/eth07/images/image_00005252_0.png
1945
+ ETHZ/eth07/images/image_00005256_0.png
1946
+ ETHZ/eth07/images/image_00005260_0.png
1947
+ ETHZ/eth07/images/image_00005264_0.png
1948
+ ETHZ/eth07/images/image_00005268_0.png
1949
+ ETHZ/eth07/images/image_00005272_0.png
1950
+ ETHZ/eth07/images/image_00005276_0.png
1951
+ ETHZ/eth07/images/image_00005280_0.png
1952
+ ETHZ/eth07/images/image_00005284_0.png
1953
+ ETHZ/eth07/images/image_00005288_0.png
1954
+ ETHZ/eth07/images/image_00005292_0.png
1955
+ ETHZ/eth07/images/image_00005296_0.png
1956
+ ETHZ/eth07/images/image_00005300_0.png
1957
+ ETHZ/eth07/images/image_00005304_0.png
1958
+ ETHZ/eth07/images/image_00005308_0.png
1959
+ ETHZ/eth07/images/image_00005312_0.png
1960
+ ETHZ/eth07/images/image_00005316_0.png
1961
+ ETHZ/eth07/images/image_00005320_0.png
1962
+ ETHZ/eth07/images/image_00005324_0.png
1963
+ ETHZ/eth07/images/image_00005328_0.png
1964
+ ETHZ/eth07/images/image_00005332_0.png
1965
+ ETHZ/eth07/images/image_00005336_0.png
1966
+ ETHZ/eth07/images/image_00005340_0.png
1967
+ ETHZ/eth07/images/image_00005344_0.png
1968
+ ETHZ/eth07/images/image_00005348_0.png
1969
+ ETHZ/eth07/images/image_00005352_0.png
1970
+ ETHZ/eth07/images/image_00005356_0.png
1971
+ ETHZ/eth07/images/image_00005360_0.png
1972
+ ETHZ/eth07/images/image_00005364_0.png
1973
+ ETHZ/eth07/images/image_00005368_0.png
1974
+ ETHZ/eth07/images/image_00005372_0.png
1975
+ ETHZ/eth07/images/image_00005376_0.png
1976
+ ETHZ/eth07/images/image_00005380_0.png
1977
+ ETHZ/eth07/images/image_00005384_0.png
1978
+ ETHZ/eth07/images/image_00005388_0.png
1979
+ ETHZ/eth07/images/image_00005392_0.png
1980
+ ETHZ/eth07/images/image_00005396_0.png
1981
+ ETHZ/eth07/images/image_00005400_0.png
1982
+ ETHZ/eth07/images/image_00005404_0.png
1983
+ ETHZ/eth07/images/image_00005408_0.png
1984
+ ETHZ/eth07/images/image_00005412_0.png
1985
+ ETHZ/eth07/images/image_00005416_0.png
1986
+ ETHZ/eth07/images/image_00005420_0.png
1987
+ ETHZ/eth07/images/image_00005424_0.png
1988
+ ETHZ/eth07/images/image_00005428_0.png
1989
+ ETHZ/eth07/images/image_00005432_0.png
1990
+ ETHZ/eth07/images/image_00005436_0.png
1991
+ ETHZ/eth07/images/image_00005440_0.png
1992
+ ETHZ/eth07/images/image_00005444_0.png
1993
+ ETHZ/eth07/images/image_00005448_0.png
1994
+ ETHZ/eth07/images/image_00005452_0.png
1995
+ ETHZ/eth07/images/image_00005456_0.png
1996
+ ETHZ/eth07/images/image_00005460_0.png
1997
+ ETHZ/eth07/images/image_00005464_0.png
1998
+ ETHZ/eth07/images/image_00005468_0.png
1999
+ ETHZ/eth07/images/image_00005472_0.png
2000
+ ETHZ/eth07/images/image_00005476_0.png
2001
+ ETHZ/eth07/images/image_00005480_0.png
2002
+ ETHZ/eth07/images/image_00005484_0.png
2003
+ ETHZ/eth07/images/image_00005488_0.png
2004
+ ETHZ/eth07/images/image_00005492_0.png
2005
+ ETHZ/eth07/images/image_00005496_0.png
2006
+ ETHZ/eth07/images/image_00005500_0.png
2007
+ ETHZ/eth07/images/image_00005504_0.png
2008
+ ETHZ/eth07/images/image_00005508_0.png
2009
+ ETHZ/eth07/images/image_00005512_0.png
2010
+ ETHZ/eth07/images/image_00005516_0.png
2011
+ ETHZ/eth07/images/image_00005520_0.png
2012
+ ETHZ/eth07/images/image_00005524_0.png
2013
+ ETHZ/eth07/images/image_00005528_0.png
2014
+ ETHZ/eth07/images/image_00005532_0.png
2015
+ ETHZ/eth07/images/image_00005536_0.png
2016
+ ETHZ/eth07/images/image_00005540_0.png
2017
+ ETHZ/eth07/images/image_00005544_0.png
2018
+ ETHZ/eth07/images/image_00005548_0.png
2019
+ ETHZ/eth07/images/image_00005552_0.png
2020
+ ETHZ/eth07/images/image_00005556_0.png
2021
+ ETHZ/eth07/images/image_00005560_0.png
2022
+ ETHZ/eth07/images/image_00005564_0.png
2023
+ ETHZ/eth07/images/image_00005568_0.png
2024
+ ETHZ/eth07/images/image_00005572_0.png
2025
+ ETHZ/eth07/images/image_00005576_0.png
2026
+ ETHZ/eth07/images/image_00005580_0.png
2027
+ ETHZ/eth07/images/image_00005584_0.png
2028
+ ETHZ/eth07/images/image_00005588_0.png
2029
+ ETHZ/eth07/images/image_00005592_0.png
2030
+ ETHZ/eth07/images/image_00005596_0.png
2031
+ ETHZ/eth07/images/image_00005600_0.png
2032
+ ETHZ/eth07/images/image_00005604_0.png
2033
+ ETHZ/eth07/images/image_00005608_0.png
2034
+ ETHZ/eth07/images/image_00005612_0.png
2035
+ ETHZ/eth07/images/image_00005616_0.png
2036
+ ETHZ/eth07/images/image_00005620_0.png
2037
+ ETHZ/eth07/images/image_00005624_0.png
2038
+ ETHZ/eth07/images/image_00005628_0.png
2039
+ ETHZ/eth07/images/image_00005632_0.png
2040
+ ETHZ/eth07/images/image_00005636_0.png
2041
+ ETHZ/eth07/images/image_00005640_0.png
2042
+ ETHZ/eth07/images/image_00005644_0.png
2043
+ ETHZ/eth07/images/image_00005648_0.png
2044
+ ETHZ/eth07/images/image_00005652_0.png
2045
+ ETHZ/eth07/images/image_00005656_0.png
2046
+ ETHZ/eth07/images/image_00005660_0.png
2047
+ ETHZ/eth07/images/image_00005664_0.png
2048
+ ETHZ/eth07/images/image_00005668_0.png
2049
+ ETHZ/eth07/images/image_00005672_0.png
2050
+ ETHZ/eth07/images/image_00005676_0.png
2051
+ ETHZ/eth07/images/image_00005680_0.png
2052
+ ETHZ/eth07/images/image_00005684_0.png
2053
+ ETHZ/eth07/images/image_00005688_0.png
2054
+ ETHZ/eth07/images/image_00005692_0.png
2055
+ ETHZ/eth07/images/image_00005696_0.png
2056
+ ETHZ/eth07/images/image_00005700_0.png
deploy/ONNXRuntime/README.md ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ## ByteTrack-ONNXRuntime in Python
2
+
3
+ This doc introduces how to convert your pytorch model into onnx, and how to run an onnxruntime demo to verify your convertion.
4
+
5
+ ### Convert Your Model to ONNX
6
+
7
+ ```shell
8
+ cd <ByteTrack_HOME>
9
+ python3 tools/export_onnx.py --output-name bytetrack_s.onnx -f exps/example/mot/yolox_s_mix_det.py -c pretrained/bytetrack_s_mot17.pth.tar
10
+ ```
11
+
12
+ ### ONNXRuntime Demo
13
+
14
+ You can run onnx demo with **16 FPS** (96-core Intel(R) Xeon(R) Platinum 8163 CPU @ 2.50GHz):
15
+
16
+ ```shell
17
+ cd <ByteTrack_HOME>/deploy/ONNXRuntime
18
+ python3 onnx_inference.py
19
+ ```
deploy/ONNXRuntime/onnx_inference.py ADDED
@@ -0,0 +1,160 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import argparse
2
+ import os
3
+
4
+ import cv2
5
+ import numpy as np
6
+ from loguru import logger
7
+
8
+ import onnxruntime
9
+
10
+ from yolox.data.data_augment import preproc as preprocess
11
+ from yolox.utils import mkdir, multiclass_nms, demo_postprocess, vis
12
+ from yolox.utils.visualize import plot_tracking
13
+ from yolox.tracker.byte_tracker import BYTETracker
14
+ from yolox.tracking_utils.timer import Timer
15
+
16
+
17
+ def make_parser():
18
+ parser = argparse.ArgumentParser("onnxruntime inference sample")
19
+ parser.add_argument(
20
+ "-m",
21
+ "--model",
22
+ type=str,
23
+ default="../../bytetrack_s.onnx",
24
+ help="Input your onnx model.",
25
+ )
26
+ parser.add_argument(
27
+ "-i",
28
+ "--video_path",
29
+ type=str,
30
+ default='../../videos/palace.mp4',
31
+ help="Path to your input image.",
32
+ )
33
+ parser.add_argument(
34
+ "-o",
35
+ "--output_dir",
36
+ type=str,
37
+ default='demo_output',
38
+ help="Path to your output directory.",
39
+ )
40
+ parser.add_argument(
41
+ "-s",
42
+ "--score_thr",
43
+ type=float,
44
+ default=0.1,
45
+ help="Score threshould to filter the result.",
46
+ )
47
+ parser.add_argument(
48
+ "-n",
49
+ "--nms_thr",
50
+ type=float,
51
+ default=0.7,
52
+ help="NMS threshould.",
53
+ )
54
+ parser.add_argument(
55
+ "--input_shape",
56
+ type=str,
57
+ default="608,1088",
58
+ help="Specify an input shape for inference.",
59
+ )
60
+ parser.add_argument(
61
+ "--with_p6",
62
+ action="store_true",
63
+ help="Whether your model uses p6 in FPN/PAN.",
64
+ )
65
+ # tracking args
66
+ parser.add_argument("--track_thresh", type=float, default=0.5, help="tracking confidence threshold")
67
+ parser.add_argument("--track_buffer", type=int, default=30, help="the frames for keep lost tracks")
68
+ parser.add_argument("--match_thresh", type=int, default=0.8, help="matching threshold for tracking")
69
+ parser.add_argument('--min-box-area', type=float, default=10, help='filter out tiny boxes')
70
+ parser.add_argument("--mot20", dest="mot20", default=False, action="store_true", help="test mot20.")
71
+ return parser
72
+
73
+
74
+ class Predictor(object):
75
+ def __init__(self, args):
76
+ self.rgb_means = (0.485, 0.456, 0.406)
77
+ self.std = (0.229, 0.224, 0.225)
78
+ self.args = args
79
+ self.session = onnxruntime.InferenceSession(args.model)
80
+ self.input_shape = tuple(map(int, args.input_shape.split(',')))
81
+
82
+ def inference(self, ori_img, timer):
83
+ img_info = {"id": 0}
84
+ height, width = ori_img.shape[:2]
85
+ img_info["height"] = height
86
+ img_info["width"] = width
87
+ img_info["raw_img"] = ori_img
88
+
89
+ img, ratio = preprocess(ori_img, self.input_shape, self.rgb_means, self.std)
90
+ img_info["ratio"] = ratio
91
+ ort_inputs = {self.session.get_inputs()[0].name: img[None, :, :, :]}
92
+ timer.tic()
93
+ output = self.session.run(None, ort_inputs)
94
+ predictions = demo_postprocess(output[0], self.input_shape, p6=self.args.with_p6)[0]
95
+
96
+ boxes = predictions[:, :4]
97
+ scores = predictions[:, 4:5] * predictions[:, 5:]
98
+
99
+ boxes_xyxy = np.ones_like(boxes)
100
+ boxes_xyxy[:, 0] = boxes[:, 0] - boxes[:, 2]/2.
101
+ boxes_xyxy[:, 1] = boxes[:, 1] - boxes[:, 3]/2.
102
+ boxes_xyxy[:, 2] = boxes[:, 0] + boxes[:, 2]/2.
103
+ boxes_xyxy[:, 3] = boxes[:, 1] + boxes[:, 3]/2.
104
+ boxes_xyxy /= ratio
105
+ dets = multiclass_nms(boxes_xyxy, scores, nms_thr=self.args.nms_thr, score_thr=self.args.score_thr)
106
+ return dets[:, :-1], img_info
107
+
108
+
109
+ def imageflow_demo(predictor, args):
110
+ cap = cv2.VideoCapture(args.video_path)
111
+ width = cap.get(cv2.CAP_PROP_FRAME_WIDTH) # float
112
+ height = cap.get(cv2.CAP_PROP_FRAME_HEIGHT) # float
113
+ fps = cap.get(cv2.CAP_PROP_FPS)
114
+ save_folder = args.output_dir
115
+ os.makedirs(save_folder, exist_ok=True)
116
+ save_path = os.path.join(save_folder, args.video_path.split("/")[-1])
117
+ logger.info(f"video save_path is {save_path}")
118
+ vid_writer = cv2.VideoWriter(
119
+ save_path, cv2.VideoWriter_fourcc(*"mp4v"), fps, (int(width), int(height))
120
+ )
121
+ tracker = BYTETracker(args, frame_rate=30)
122
+ timer = Timer()
123
+ frame_id = 0
124
+ results = []
125
+ while True:
126
+ if frame_id % 20 == 0:
127
+ logger.info('Processing frame {} ({:.2f} fps)'.format(frame_id, 1. / max(1e-5, timer.average_time)))
128
+ ret_val, frame = cap.read()
129
+ if ret_val:
130
+ outputs, img_info = predictor.inference(frame, timer)
131
+ online_targets = tracker.update(outputs, [img_info['height'], img_info['width']], [img_info['height'], img_info['width']])
132
+ online_tlwhs = []
133
+ online_ids = []
134
+ online_scores = []
135
+ for t in online_targets:
136
+ tlwh = t.tlwh
137
+ tid = t.track_id
138
+ vertical = tlwh[2] / tlwh[3] > 1.6
139
+ if tlwh[2] * tlwh[3] > args.min_box_area and not vertical:
140
+ online_tlwhs.append(tlwh)
141
+ online_ids.append(tid)
142
+ online_scores.append(t.score)
143
+ timer.toc()
144
+ results.append((frame_id + 1, online_tlwhs, online_ids, online_scores))
145
+ online_im = plot_tracking(img_info['raw_img'], online_tlwhs, online_ids, frame_id=frame_id + 1,
146
+ fps=1. / timer.average_time)
147
+ vid_writer.write(online_im)
148
+ ch = cv2.waitKey(1)
149
+ if ch == 27 or ch == ord("q") or ch == ord("Q"):
150
+ break
151
+ else:
152
+ break
153
+ frame_id += 1
154
+
155
+
156
+ if __name__ == '__main__':
157
+ args = make_parser().parse_args()
158
+
159
+ predictor = Predictor(args)
160
+ imageflow_demo(predictor, args)
deploy/TensorRT/cpp/CMakeLists.txt ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ cmake_minimum_required(VERSION 2.6)
2
+
3
+ project(bytetrack)
4
+
5
+ add_definitions(-std=c++11)
6
+
7
+ option(CUDA_USE_STATIC_CUDA_RUNTIME OFF)
8
+ set(CMAKE_CXX_STANDARD 11)
9
+ set(CMAKE_BUILD_TYPE Debug)
10
+
11
+ find_package(CUDA REQUIRED)
12
+
13
+ include_directories(${PROJECT_SOURCE_DIR}/include)
14
+ include_directories(/usr/local/include/eigen3)
15
+ link_directories(${PROJECT_SOURCE_DIR}/include)
16
+ # include and link dirs of cuda and tensorrt, you need adapt them if yours are different
17
+ # cuda
18
+ include_directories(/usr/local/cuda/include)
19
+ link_directories(/usr/local/cuda/lib64)
20
+ # cudnn
21
+ include_directories(/data/cuda/cuda-10.2/cudnn/v8.0.4/include)
22
+ link_directories(/data/cuda/cuda-10.2/cudnn/v8.0.4/lib64)
23
+ # tensorrt
24
+ include_directories(/opt/tiger/demo/TensorRT-7.2.3.4/include)
25
+ link_directories(/opt/tiger/demo/TensorRT-7.2.3.4/lib)
26
+
27
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall -Ofast -Wfatal-errors -D_MWAITXINTRIN_H_INCLUDED")
28
+
29
+ find_package(OpenCV)
30
+ include_directories(${OpenCV_INCLUDE_DIRS})
31
+
32
+ file(GLOB My_Source_Files ${PROJECT_SOURCE_DIR}/src/*.cpp)
33
+ add_executable(bytetrack ${My_Source_Files})
34
+ target_link_libraries(bytetrack nvinfer)
35
+ target_link_libraries(bytetrack cudart)
36
+ target_link_libraries(bytetrack ${OpenCV_LIBS})
37
+
38
+ add_definitions(-O2 -pthread)
39
+
deploy/TensorRT/cpp/README.md ADDED
@@ -0,0 +1,58 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # ByteTrack-TensorRT in C++
2
+
3
+ ## Installation
4
+
5
+ Install opencv with ```sudo apt-get install libopencv-dev``` (we don't need a higher version of opencv like v3.3+).
6
+
7
+ Install eigen-3.3.9 [[google]](https://drive.google.com/file/d/1rqO74CYCNrmRAg8Rra0JP3yZtJ-rfket/view?usp=sharing), [[baidu(code:ueq4)]](https://pan.baidu.com/s/15kEfCxpy-T7tz60msxxExg).
8
+
9
+ ```shell
10
+ unzip eigen-3.3.9.zip
11
+ cd eigen-3.3.9
12
+ mkdir build
13
+ cd build
14
+ cmake ..
15
+ sudo make install
16
+ ```
17
+
18
+ ## Prepare serialized engine file
19
+
20
+ Follow the TensorRT Python demo to convert and save the serialized engine file.
21
+
22
+ Check the 'model_trt.engine' file, which will be automatically saved at the YOLOX_output dir.
23
+
24
+ ## Build the demo
25
+
26
+ You should set the TensorRT path and CUDA path in CMakeLists.txt.
27
+
28
+ For bytetrack_s model, we set the input frame size 1088 x 608. For bytetrack_m, bytetrack_l, bytetrack_x models, we set the input frame size 1440 x 800. You can modify the INPUT_W and INPUT_H in src/bytetrack.cpp
29
+
30
+ ```c++
31
+ static const int INPUT_W = 1088;
32
+ static const int INPUT_H = 608;
33
+ ```
34
+
35
+ You can first build the demo:
36
+
37
+ ```shell
38
+ cd <ByteTrack_HOME>/demo/TensorRT/cpp
39
+ mkdir build
40
+ cd build
41
+ cmake ..
42
+ make
43
+ ```
44
+
45
+ Then you can run the demo with **200 FPS**:
46
+
47
+ ```shell
48
+ ./bytetrack ../../../../YOLOX_outputs/yolox_s_mix_det/model_trt.engine -i ../../../../videos/palace.mp4
49
+ ```
50
+
51
+ (If you find the output video lose some frames, you can convert the input video by running:
52
+
53
+ ```shell
54
+ cd <ByteTrack_HOME>
55
+ python3 tools/convert_video.py
56
+ ```
57
+ to generate an appropriate input video for TensorRT C++ demo. )
58
+
deploy/TensorRT/cpp/include/BYTETracker.h ADDED
@@ -0,0 +1,49 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #pragma once
2
+
3
+ #include "STrack.h"
4
+
5
+ struct Object
6
+ {
7
+ cv::Rect_<float> rect;
8
+ int label;
9
+ float prob;
10
+ };
11
+
12
+ class BYTETracker
13
+ {
14
+ public:
15
+ BYTETracker(int frame_rate = 30, int track_buffer = 30);
16
+ ~BYTETracker();
17
+
18
+ vector<STrack> update(const vector<Object>& objects);
19
+ Scalar get_color(int idx);
20
+
21
+ private:
22
+ vector<STrack*> joint_stracks(vector<STrack*> &tlista, vector<STrack> &tlistb);
23
+ vector<STrack> joint_stracks(vector<STrack> &tlista, vector<STrack> &tlistb);
24
+
25
+ vector<STrack> sub_stracks(vector<STrack> &tlista, vector<STrack> &tlistb);
26
+ void remove_duplicate_stracks(vector<STrack> &resa, vector<STrack> &resb, vector<STrack> &stracksa, vector<STrack> &stracksb);
27
+
28
+ void linear_assignment(vector<vector<float> > &cost_matrix, int cost_matrix_size, int cost_matrix_size_size, float thresh,
29
+ vector<vector<int> > &matches, vector<int> &unmatched_a, vector<int> &unmatched_b);
30
+ vector<vector<float> > iou_distance(vector<STrack*> &atracks, vector<STrack> &btracks, int &dist_size, int &dist_size_size);
31
+ vector<vector<float> > iou_distance(vector<STrack> &atracks, vector<STrack> &btracks);
32
+ vector<vector<float> > ious(vector<vector<float> > &atlbrs, vector<vector<float> > &btlbrs);
33
+
34
+ double lapjv(const vector<vector<float> > &cost, vector<int> &rowsol, vector<int> &colsol,
35
+ bool extend_cost = false, float cost_limit = LONG_MAX, bool return_cost = true);
36
+
37
+ private:
38
+
39
+ float track_thresh;
40
+ float high_thresh;
41
+ float match_thresh;
42
+ int frame_id;
43
+ int max_time_lost;
44
+
45
+ vector<STrack> tracked_stracks;
46
+ vector<STrack> lost_stracks;
47
+ vector<STrack> removed_stracks;
48
+ byte_kalman::KalmanFilter kalman_filter;
49
+ };
deploy/TensorRT/cpp/include/STrack.h ADDED
@@ -0,0 +1,50 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #pragma once
2
+
3
+ #include <opencv2/opencv.hpp>
4
+ #include "kalmanFilter.h"
5
+
6
+ using namespace cv;
7
+ using namespace std;
8
+
9
+ enum TrackState { New = 0, Tracked, Lost, Removed };
10
+
11
+ class STrack
12
+ {
13
+ public:
14
+ STrack(vector<float> tlwh_, float score);
15
+ ~STrack();
16
+
17
+ vector<float> static tlbr_to_tlwh(vector<float> &tlbr);
18
+ void static multi_predict(vector<STrack*> &stracks, byte_kalman::KalmanFilter &kalman_filter);
19
+ void static_tlwh();
20
+ void static_tlbr();
21
+ vector<float> tlwh_to_xyah(vector<float> tlwh_tmp);
22
+ vector<float> to_xyah();
23
+ void mark_lost();
24
+ void mark_removed();
25
+ int next_id();
26
+ int end_frame();
27
+
28
+ void activate(byte_kalman::KalmanFilter &kalman_filter, int frame_id);
29
+ void re_activate(STrack &new_track, int frame_id, bool new_id = false);
30
+ void update(STrack &new_track, int frame_id);
31
+
32
+ public:
33
+ bool is_activated;
34
+ int track_id;
35
+ int state;
36
+
37
+ vector<float> _tlwh;
38
+ vector<float> tlwh;
39
+ vector<float> tlbr;
40
+ int frame_id;
41
+ int tracklet_len;
42
+ int start_frame;
43
+
44
+ KAL_MEAN mean;
45
+ KAL_COVA covariance;
46
+ float score;
47
+
48
+ private:
49
+ byte_kalman::KalmanFilter kalman_filter;
50
+ };
deploy/TensorRT/cpp/include/dataType.h ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #pragma once
2
+
3
+ #include <cstddef>
4
+ #include <vector>
5
+
6
+ #include <Eigen/Core>
7
+ #include <Eigen/Dense>
8
+ typedef Eigen::Matrix<float, 1, 4, Eigen::RowMajor> DETECTBOX;
9
+ typedef Eigen::Matrix<float, -1, 4, Eigen::RowMajor> DETECTBOXSS;
10
+ typedef Eigen::Matrix<float, 1, 128, Eigen::RowMajor> FEATURE;
11
+ typedef Eigen::Matrix<float, Eigen::Dynamic, 128, Eigen::RowMajor> FEATURESS;
12
+ //typedef std::vector<FEATURE> FEATURESS;
13
+
14
+ //Kalmanfilter
15
+ //typedef Eigen::Matrix<float, 8, 8, Eigen::RowMajor> KAL_FILTER;
16
+ typedef Eigen::Matrix<float, 1, 8, Eigen::RowMajor> KAL_MEAN;
17
+ typedef Eigen::Matrix<float, 8, 8, Eigen::RowMajor> KAL_COVA;
18
+ typedef Eigen::Matrix<float, 1, 4, Eigen::RowMajor> KAL_HMEAN;
19
+ typedef Eigen::Matrix<float, 4, 4, Eigen::RowMajor> KAL_HCOVA;
20
+ using KAL_DATA = std::pair<KAL_MEAN, KAL_COVA>;
21
+ using KAL_HDATA = std::pair<KAL_HMEAN, KAL_HCOVA>;
22
+
23
+ //main
24
+ using RESULT_DATA = std::pair<int, DETECTBOX>;
25
+
26
+ //tracker:
27
+ using TRACKER_DATA = std::pair<int, FEATURESS>;
28
+ using MATCH_DATA = std::pair<int, int>;
29
+ typedef struct t {
30
+ std::vector<MATCH_DATA> matches;
31
+ std::vector<int> unmatched_tracks;
32
+ std::vector<int> unmatched_detections;
33
+ }TRACHER_MATCHD;
34
+
35
+ //linear_assignment:
36
+ typedef Eigen::Matrix<float, -1, -1, Eigen::RowMajor> DYNAMICM;
deploy/TensorRT/cpp/include/kalmanFilter.h ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #pragma once
2
+
3
+ #include "dataType.h"
4
+
5
+ namespace byte_kalman
6
+ {
7
+ class KalmanFilter
8
+ {
9
+ public:
10
+ static const double chi2inv95[10];
11
+ KalmanFilter();
12
+ KAL_DATA initiate(const DETECTBOX& measurement);
13
+ void predict(KAL_MEAN& mean, KAL_COVA& covariance);
14
+ KAL_HDATA project(const KAL_MEAN& mean, const KAL_COVA& covariance);
15
+ KAL_DATA update(const KAL_MEAN& mean,
16
+ const KAL_COVA& covariance,
17
+ const DETECTBOX& measurement);
18
+
19
+ Eigen::Matrix<float, 1, -1> gating_distance(
20
+ const KAL_MEAN& mean,
21
+ const KAL_COVA& covariance,
22
+ const std::vector<DETECTBOX>& measurements,
23
+ bool only_position = false);
24
+
25
+ private:
26
+ Eigen::Matrix<float, 8, 8, Eigen::RowMajor> _motion_mat;
27
+ Eigen::Matrix<float, 4, 8, Eigen::RowMajor> _update_mat;
28
+ float _std_weight_position;
29
+ float _std_weight_velocity;
30
+ };
31
+ }
deploy/TensorRT/cpp/include/lapjv.h ADDED
@@ -0,0 +1,63 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #ifndef LAPJV_H
2
+ #define LAPJV_H
3
+
4
+ #define LARGE 1000000
5
+
6
+ #if !defined TRUE
7
+ #define TRUE 1
8
+ #endif
9
+ #if !defined FALSE
10
+ #define FALSE 0
11
+ #endif
12
+
13
+ #define NEW(x, t, n) if ((x = (t *)malloc(sizeof(t) * (n))) == 0) { return -1; }
14
+ #define FREE(x) if (x != 0) { free(x); x = 0; }
15
+ #define SWAP_INDICES(a, b) { int_t _temp_index = a; a = b; b = _temp_index; }
16
+
17
+ #if 0
18
+ #include <assert.h>
19
+ #define ASSERT(cond) assert(cond)
20
+ #define PRINTF(fmt, ...) printf(fmt, ##__VA_ARGS__)
21
+ #define PRINT_COST_ARRAY(a, n) \
22
+ while (1) { \
23
+ printf(#a" = ["); \
24
+ if ((n) > 0) { \
25
+ printf("%f", (a)[0]); \
26
+ for (uint_t j = 1; j < n; j++) { \
27
+ printf(", %f", (a)[j]); \
28
+ } \
29
+ } \
30
+ printf("]\n"); \
31
+ break; \
32
+ }
33
+ #define PRINT_INDEX_ARRAY(a, n) \
34
+ while (1) { \
35
+ printf(#a" = ["); \
36
+ if ((n) > 0) { \
37
+ printf("%d", (a)[0]); \
38
+ for (uint_t j = 1; j < n; j++) { \
39
+ printf(", %d", (a)[j]); \
40
+ } \
41
+ } \
42
+ printf("]\n"); \
43
+ break; \
44
+ }
45
+ #else
46
+ #define ASSERT(cond)
47
+ #define PRINTF(fmt, ...)
48
+ #define PRINT_COST_ARRAY(a, n)
49
+ #define PRINT_INDEX_ARRAY(a, n)
50
+ #endif
51
+
52
+
53
+ typedef signed int int_t;
54
+ typedef unsigned int uint_t;
55
+ typedef double cost_t;
56
+ typedef char boolean;
57
+ typedef enum fp_t { FP_1 = 1, FP_2 = 2, FP_DYNAMIC = 3 } fp_t;
58
+
59
+ extern int_t lapjv_internal(
60
+ const uint_t n, cost_t *cost[],
61
+ int_t *x, int_t *y);
62
+
63
+ #endif // LAPJV_H
deploy/TensorRT/cpp/include/logging.h ADDED
@@ -0,0 +1,503 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ * Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved.
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+ #ifndef TENSORRT_LOGGING_H
18
+ #define TENSORRT_LOGGING_H
19
+
20
+ #include "NvInferRuntimeCommon.h"
21
+ #include <cassert>
22
+ #include <ctime>
23
+ #include <iomanip>
24
+ #include <iostream>
25
+ #include <ostream>
26
+ #include <sstream>
27
+ #include <string>
28
+
29
+ using Severity = nvinfer1::ILogger::Severity;
30
+
31
+ class LogStreamConsumerBuffer : public std::stringbuf
32
+ {
33
+ public:
34
+ LogStreamConsumerBuffer(std::ostream& stream, const std::string& prefix, bool shouldLog)
35
+ : mOutput(stream)
36
+ , mPrefix(prefix)
37
+ , mShouldLog(shouldLog)
38
+ {
39
+ }
40
+
41
+ LogStreamConsumerBuffer(LogStreamConsumerBuffer&& other)
42
+ : mOutput(other.mOutput)
43
+ {
44
+ }
45
+
46
+ ~LogStreamConsumerBuffer()
47
+ {
48
+ // std::streambuf::pbase() gives a pointer to the beginning of the buffered part of the output sequence
49
+ // std::streambuf::pptr() gives a pointer to the current position of the output sequence
50
+ // if the pointer to the beginning is not equal to the pointer to the current position,
51
+ // call putOutput() to log the output to the stream
52
+ if (pbase() != pptr())
53
+ {
54
+ putOutput();
55
+ }
56
+ }
57
+
58
+ // synchronizes the stream buffer and returns 0 on success
59
+ // synchronizing the stream buffer consists of inserting the buffer contents into the stream,
60
+ // resetting the buffer and flushing the stream
61
+ virtual int sync()
62
+ {
63
+ putOutput();
64
+ return 0;
65
+ }
66
+
67
+ void putOutput()
68
+ {
69
+ if (mShouldLog)
70
+ {
71
+ // prepend timestamp
72
+ std::time_t timestamp = std::time(nullptr);
73
+ tm* tm_local = std::localtime(&timestamp);
74
+ std::cout << "[";
75
+ std::cout << std::setw(2) << std::setfill('0') << 1 + tm_local->tm_mon << "/";
76
+ std::cout << std::setw(2) << std::setfill('0') << tm_local->tm_mday << "/";
77
+ std::cout << std::setw(4) << std::setfill('0') << 1900 + tm_local->tm_year << "-";
78
+ std::cout << std::setw(2) << std::setfill('0') << tm_local->tm_hour << ":";
79
+ std::cout << std::setw(2) << std::setfill('0') << tm_local->tm_min << ":";
80
+ std::cout << std::setw(2) << std::setfill('0') << tm_local->tm_sec << "] ";
81
+ // std::stringbuf::str() gets the string contents of the buffer
82
+ // insert the buffer contents pre-appended by the appropriate prefix into the stream
83
+ mOutput << mPrefix << str();
84
+ // set the buffer to empty
85
+ str("");
86
+ // flush the stream
87
+ mOutput.flush();
88
+ }
89
+ }
90
+
91
+ void setShouldLog(bool shouldLog)
92
+ {
93
+ mShouldLog = shouldLog;
94
+ }
95
+
96
+ private:
97
+ std::ostream& mOutput;
98
+ std::string mPrefix;
99
+ bool mShouldLog;
100
+ };
101
+
102
+ //!
103
+ //! \class LogStreamConsumerBase
104
+ //! \brief Convenience object used to initialize LogStreamConsumerBuffer before std::ostream in LogStreamConsumer
105
+ //!
106
+ class LogStreamConsumerBase
107
+ {
108
+ public:
109
+ LogStreamConsumerBase(std::ostream& stream, const std::string& prefix, bool shouldLog)
110
+ : mBuffer(stream, prefix, shouldLog)
111
+ {
112
+ }
113
+
114
+ protected:
115
+ LogStreamConsumerBuffer mBuffer;
116
+ };
117
+
118
+ //!
119
+ //! \class LogStreamConsumer
120
+ //! \brief Convenience object used to facilitate use of C++ stream syntax when logging messages.
121
+ //! Order of base classes is LogStreamConsumerBase and then std::ostream.
122
+ //! This is because the LogStreamConsumerBase class is used to initialize the LogStreamConsumerBuffer member field
123
+ //! in LogStreamConsumer and then the address of the buffer is passed to std::ostream.
124
+ //! This is necessary to prevent the address of an uninitialized buffer from being passed to std::ostream.
125
+ //! Please do not change the order of the parent classes.
126
+ //!
127
+ class LogStreamConsumer : protected LogStreamConsumerBase, public std::ostream
128
+ {
129
+ public:
130
+ //! \brief Creates a LogStreamConsumer which logs messages with level severity.
131
+ //! Reportable severity determines if the messages are severe enough to be logged.
132
+ LogStreamConsumer(Severity reportableSeverity, Severity severity)
133
+ : LogStreamConsumerBase(severityOstream(severity), severityPrefix(severity), severity <= reportableSeverity)
134
+ , std::ostream(&mBuffer) // links the stream buffer with the stream
135
+ , mShouldLog(severity <= reportableSeverity)
136
+ , mSeverity(severity)
137
+ {
138
+ }
139
+
140
+ LogStreamConsumer(LogStreamConsumer&& other)
141
+ : LogStreamConsumerBase(severityOstream(other.mSeverity), severityPrefix(other.mSeverity), other.mShouldLog)
142
+ , std::ostream(&mBuffer) // links the stream buffer with the stream
143
+ , mShouldLog(other.mShouldLog)
144
+ , mSeverity(other.mSeverity)
145
+ {
146
+ }
147
+
148
+ void setReportableSeverity(Severity reportableSeverity)
149
+ {
150
+ mShouldLog = mSeverity <= reportableSeverity;
151
+ mBuffer.setShouldLog(mShouldLog);
152
+ }
153
+
154
+ private:
155
+ static std::ostream& severityOstream(Severity severity)
156
+ {
157
+ return severity >= Severity::kINFO ? std::cout : std::cerr;
158
+ }
159
+
160
+ static std::string severityPrefix(Severity severity)
161
+ {
162
+ switch (severity)
163
+ {
164
+ case Severity::kINTERNAL_ERROR: return "[F] ";
165
+ case Severity::kERROR: return "[E] ";
166
+ case Severity::kWARNING: return "[W] ";
167
+ case Severity::kINFO: return "[I] ";
168
+ case Severity::kVERBOSE: return "[V] ";
169
+ default: assert(0); return "";
170
+ }
171
+ }
172
+
173
+ bool mShouldLog;
174
+ Severity mSeverity;
175
+ };
176
+
177
+ //! \class Logger
178
+ //!
179
+ //! \brief Class which manages logging of TensorRT tools and samples
180
+ //!
181
+ //! \details This class provides a common interface for TensorRT tools and samples to log information to the console,
182
+ //! and supports logging two types of messages:
183
+ //!
184
+ //! - Debugging messages with an associated severity (info, warning, error, or internal error/fatal)
185
+ //! - Test pass/fail messages
186
+ //!
187
+ //! The advantage of having all samples use this class for logging as opposed to emitting directly to stdout/stderr is
188
+ //! that the logic for controlling the verbosity and formatting of sample output is centralized in one location.
189
+ //!
190
+ //! In the future, this class could be extended to support dumping test results to a file in some standard format
191
+ //! (for example, JUnit XML), and providing additional metadata (e.g. timing the duration of a test run).
192
+ //!
193
+ //! TODO: For backwards compatibility with existing samples, this class inherits directly from the nvinfer1::ILogger
194
+ //! interface, which is problematic since there isn't a clean separation between messages coming from the TensorRT
195
+ //! library and messages coming from the sample.
196
+ //!
197
+ //! In the future (once all samples are updated to use Logger::getTRTLogger() to access the ILogger) we can refactor the
198
+ //! class to eliminate the inheritance and instead make the nvinfer1::ILogger implementation a member of the Logger
199
+ //! object.
200
+
201
+ class Logger : public nvinfer1::ILogger
202
+ {
203
+ public:
204
+ Logger(Severity severity = Severity::kWARNING)
205
+ : mReportableSeverity(severity)
206
+ {
207
+ }
208
+
209
+ //!
210
+ //! \enum TestResult
211
+ //! \brief Represents the state of a given test
212
+ //!
213
+ enum class TestResult
214
+ {
215
+ kRUNNING, //!< The test is running
216
+ kPASSED, //!< The test passed
217
+ kFAILED, //!< The test failed
218
+ kWAIVED //!< The test was waived
219
+ };
220
+
221
+ //!
222
+ //! \brief Forward-compatible method for retrieving the nvinfer::ILogger associated with this Logger
223
+ //! \return The nvinfer1::ILogger associated with this Logger
224
+ //!
225
+ //! TODO Once all samples are updated to use this method to register the logger with TensorRT,
226
+ //! we can eliminate the inheritance of Logger from ILogger
227
+ //!
228
+ nvinfer1::ILogger& getTRTLogger()
229
+ {
230
+ return *this;
231
+ }
232
+
233
+ //!
234
+ //! \brief Implementation of the nvinfer1::ILogger::log() virtual method
235
+ //!
236
+ //! Note samples should not be calling this function directly; it will eventually go away once we eliminate the
237
+ //! inheritance from nvinfer1::ILogger
238
+ //!
239
+ void log(Severity severity, const char* msg) override
240
+ {
241
+ LogStreamConsumer(mReportableSeverity, severity) << "[TRT] " << std::string(msg) << std::endl;
242
+ }
243
+
244
+ //!
245
+ //! \brief Method for controlling the verbosity of logging output
246
+ //!
247
+ //! \param severity The logger will only emit messages that have severity of this level or higher.
248
+ //!
249
+ void setReportableSeverity(Severity severity)
250
+ {
251
+ mReportableSeverity = severity;
252
+ }
253
+
254
+ //!
255
+ //! \brief Opaque handle that holds logging information for a particular test
256
+ //!
257
+ //! This object is an opaque handle to information used by the Logger to print test results.
258
+ //! The sample must call Logger::defineTest() in order to obtain a TestAtom that can be used
259
+ //! with Logger::reportTest{Start,End}().
260
+ //!
261
+ class TestAtom
262
+ {
263
+ public:
264
+ TestAtom(TestAtom&&) = default;
265
+
266
+ private:
267
+ friend class Logger;
268
+
269
+ TestAtom(bool started, const std::string& name, const std::string& cmdline)
270
+ : mStarted(started)
271
+ , mName(name)
272
+ , mCmdline(cmdline)
273
+ {
274
+ }
275
+
276
+ bool mStarted;
277
+ std::string mName;
278
+ std::string mCmdline;
279
+ };
280
+
281
+ //!
282
+ //! \brief Define a test for logging
283
+ //!
284
+ //! \param[in] name The name of the test. This should be a string starting with
285
+ //! "TensorRT" and containing dot-separated strings containing
286
+ //! the characters [A-Za-z0-9_].
287
+ //! For example, "TensorRT.sample_googlenet"
288
+ //! \param[in] cmdline The command line used to reproduce the test
289
+ //
290
+ //! \return a TestAtom that can be used in Logger::reportTest{Start,End}().
291
+ //!
292
+ static TestAtom defineTest(const std::string& name, const std::string& cmdline)
293
+ {
294
+ return TestAtom(false, name, cmdline);
295
+ }
296
+
297
+ //!
298
+ //! \brief A convenience overloaded version of defineTest() that accepts an array of command-line arguments
299
+ //! as input
300
+ //!
301
+ //! \param[in] name The name of the test
302
+ //! \param[in] argc The number of command-line arguments
303
+ //! \param[in] argv The array of command-line arguments (given as C strings)
304
+ //!
305
+ //! \return a TestAtom that can be used in Logger::reportTest{Start,End}().
306
+ static TestAtom defineTest(const std::string& name, int argc, char const* const* argv)
307
+ {
308
+ auto cmdline = genCmdlineString(argc, argv);
309
+ return defineTest(name, cmdline);
310
+ }
311
+
312
+ //!
313
+ //! \brief Report that a test has started.
314
+ //!
315
+ //! \pre reportTestStart() has not been called yet for the given testAtom
316
+ //!
317
+ //! \param[in] testAtom The handle to the test that has started
318
+ //!
319
+ static void reportTestStart(TestAtom& testAtom)
320
+ {
321
+ reportTestResult(testAtom, TestResult::kRUNNING);
322
+ assert(!testAtom.mStarted);
323
+ testAtom.mStarted = true;
324
+ }
325
+
326
+ //!
327
+ //! \brief Report that a test has ended.
328
+ //!
329
+ //! \pre reportTestStart() has been called for the given testAtom
330
+ //!
331
+ //! \param[in] testAtom The handle to the test that has ended
332
+ //! \param[in] result The result of the test. Should be one of TestResult::kPASSED,
333
+ //! TestResult::kFAILED, TestResult::kWAIVED
334
+ //!
335
+ static void reportTestEnd(const TestAtom& testAtom, TestResult result)
336
+ {
337
+ assert(result != TestResult::kRUNNING);
338
+ assert(testAtom.mStarted);
339
+ reportTestResult(testAtom, result);
340
+ }
341
+
342
+ static int reportPass(const TestAtom& testAtom)
343
+ {
344
+ reportTestEnd(testAtom, TestResult::kPASSED);
345
+ return EXIT_SUCCESS;
346
+ }
347
+
348
+ static int reportFail(const TestAtom& testAtom)
349
+ {
350
+ reportTestEnd(testAtom, TestResult::kFAILED);
351
+ return EXIT_FAILURE;
352
+ }
353
+
354
+ static int reportWaive(const TestAtom& testAtom)
355
+ {
356
+ reportTestEnd(testAtom, TestResult::kWAIVED);
357
+ return EXIT_SUCCESS;
358
+ }
359
+
360
+ static int reportTest(const TestAtom& testAtom, bool pass)
361
+ {
362
+ return pass ? reportPass(testAtom) : reportFail(testAtom);
363
+ }
364
+
365
+ Severity getReportableSeverity() const
366
+ {
367
+ return mReportableSeverity;
368
+ }
369
+
370
+ private:
371
+ //!
372
+ //! \brief returns an appropriate string for prefixing a log message with the given severity
373
+ //!
374
+ static const char* severityPrefix(Severity severity)
375
+ {
376
+ switch (severity)
377
+ {
378
+ case Severity::kINTERNAL_ERROR: return "[F] ";
379
+ case Severity::kERROR: return "[E] ";
380
+ case Severity::kWARNING: return "[W] ";
381
+ case Severity::kINFO: return "[I] ";
382
+ case Severity::kVERBOSE: return "[V] ";
383
+ default: assert(0); return "";
384
+ }
385
+ }
386
+
387
+ //!
388
+ //! \brief returns an appropriate string for prefixing a test result message with the given result
389
+ //!
390
+ static const char* testResultString(TestResult result)
391
+ {
392
+ switch (result)
393
+ {
394
+ case TestResult::kRUNNING: return "RUNNING";
395
+ case TestResult::kPASSED: return "PASSED";
396
+ case TestResult::kFAILED: return "FAILED";
397
+ case TestResult::kWAIVED: return "WAIVED";
398
+ default: assert(0); return "";
399
+ }
400
+ }
401
+
402
+ //!
403
+ //! \brief returns an appropriate output stream (cout or cerr) to use with the given severity
404
+ //!
405
+ static std::ostream& severityOstream(Severity severity)
406
+ {
407
+ return severity >= Severity::kINFO ? std::cout : std::cerr;
408
+ }
409
+
410
+ //!
411
+ //! \brief method that implements logging test results
412
+ //!
413
+ static void reportTestResult(const TestAtom& testAtom, TestResult result)
414
+ {
415
+ severityOstream(Severity::kINFO) << "&&&& " << testResultString(result) << " " << testAtom.mName << " # "
416
+ << testAtom.mCmdline << std::endl;
417
+ }
418
+
419
+ //!
420
+ //! \brief generate a command line string from the given (argc, argv) values
421
+ //!
422
+ static std::string genCmdlineString(int argc, char const* const* argv)
423
+ {
424
+ std::stringstream ss;
425
+ for (int i = 0; i < argc; i++)
426
+ {
427
+ if (i > 0)
428
+ ss << " ";
429
+ ss << argv[i];
430
+ }
431
+ return ss.str();
432
+ }
433
+
434
+ Severity mReportableSeverity;
435
+ };
436
+
437
+ namespace
438
+ {
439
+
440
+ //!
441
+ //! \brief produces a LogStreamConsumer object that can be used to log messages of severity kVERBOSE
442
+ //!
443
+ //! Example usage:
444
+ //!
445
+ //! LOG_VERBOSE(logger) << "hello world" << std::endl;
446
+ //!
447
+ inline LogStreamConsumer LOG_VERBOSE(const Logger& logger)
448
+ {
449
+ return LogStreamConsumer(logger.getReportableSeverity(), Severity::kVERBOSE);
450
+ }
451
+
452
+ //!
453
+ //! \brief produces a LogStreamConsumer object that can be used to log messages of severity kINFO
454
+ //!
455
+ //! Example usage:
456
+ //!
457
+ //! LOG_INFO(logger) << "hello world" << std::endl;
458
+ //!
459
+ inline LogStreamConsumer LOG_INFO(const Logger& logger)
460
+ {
461
+ return LogStreamConsumer(logger.getReportableSeverity(), Severity::kINFO);
462
+ }
463
+
464
+ //!
465
+ //! \brief produces a LogStreamConsumer object that can be used to log messages of severity kWARNING
466
+ //!
467
+ //! Example usage:
468
+ //!
469
+ //! LOG_WARN(logger) << "hello world" << std::endl;
470
+ //!
471
+ inline LogStreamConsumer LOG_WARN(const Logger& logger)
472
+ {
473
+ return LogStreamConsumer(logger.getReportableSeverity(), Severity::kWARNING);
474
+ }
475
+
476
+ //!
477
+ //! \brief produces a LogStreamConsumer object that can be used to log messages of severity kERROR
478
+ //!
479
+ //! Example usage:
480
+ //!
481
+ //! LOG_ERROR(logger) << "hello world" << std::endl;
482
+ //!
483
+ inline LogStreamConsumer LOG_ERROR(const Logger& logger)
484
+ {
485
+ return LogStreamConsumer(logger.getReportableSeverity(), Severity::kERROR);
486
+ }
487
+
488
+ //!
489
+ //! \brief produces a LogStreamConsumer object that can be used to log messages of severity kINTERNAL_ERROR
490
+ // ("fatal" severity)
491
+ //!
492
+ //! Example usage:
493
+ //!
494
+ //! LOG_FATAL(logger) << "hello world" << std::endl;
495
+ //!
496
+ inline LogStreamConsumer LOG_FATAL(const Logger& logger)
497
+ {
498
+ return LogStreamConsumer(logger.getReportableSeverity(), Severity::kINTERNAL_ERROR);
499
+ }
500
+
501
+ } // anonymous namespace
502
+
503
+ #endif // TENSORRT_LOGGING_H
deploy/TensorRT/cpp/src/BYTETracker.cpp ADDED
@@ -0,0 +1,241 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #include "BYTETracker.h"
2
+ #include <fstream>
3
+
4
+ BYTETracker::BYTETracker(int frame_rate, int track_buffer)
5
+ {
6
+ track_thresh = 0.5;
7
+ high_thresh = 0.6;
8
+ match_thresh = 0.8;
9
+
10
+ frame_id = 0;
11
+ max_time_lost = int(frame_rate / 30.0 * track_buffer);
12
+ cout << "Init ByteTrack!" << endl;
13
+ }
14
+
15
+ BYTETracker::~BYTETracker()
16
+ {
17
+ }
18
+
19
+ vector<STrack> BYTETracker::update(const vector<Object>& objects)
20
+ {
21
+
22
+ ////////////////// Step 1: Get detections //////////////////
23
+ this->frame_id++;
24
+ vector<STrack> activated_stracks;
25
+ vector<STrack> refind_stracks;
26
+ vector<STrack> removed_stracks;
27
+ vector<STrack> lost_stracks;
28
+ vector<STrack> detections;
29
+ vector<STrack> detections_low;
30
+
31
+ vector<STrack> detections_cp;
32
+ vector<STrack> tracked_stracks_swap;
33
+ vector<STrack> resa, resb;
34
+ vector<STrack> output_stracks;
35
+
36
+ vector<STrack*> unconfirmed;
37
+ vector<STrack*> tracked_stracks;
38
+ vector<STrack*> strack_pool;
39
+ vector<STrack*> r_tracked_stracks;
40
+
41
+ if (objects.size() > 0)
42
+ {
43
+ for (int i = 0; i < objects.size(); i++)
44
+ {
45
+ vector<float> tlbr_;
46
+ tlbr_.resize(4);
47
+ tlbr_[0] = objects[i].rect.x;
48
+ tlbr_[1] = objects[i].rect.y;
49
+ tlbr_[2] = objects[i].rect.x + objects[i].rect.width;
50
+ tlbr_[3] = objects[i].rect.y + objects[i].rect.height;
51
+
52
+ float score = objects[i].prob;
53
+
54
+ STrack strack(STrack::tlbr_to_tlwh(tlbr_), score);
55
+ if (score >= track_thresh)
56
+ {
57
+ detections.push_back(strack);
58
+ }
59
+ else
60
+ {
61
+ detections_low.push_back(strack);
62
+ }
63
+
64
+ }
65
+ }
66
+
67
+ // Add newly detected tracklets to tracked_stracks
68
+ for (int i = 0; i < this->tracked_stracks.size(); i++)
69
+ {
70
+ if (!this->tracked_stracks[i].is_activated)
71
+ unconfirmed.push_back(&this->tracked_stracks[i]);
72
+ else
73
+ tracked_stracks.push_back(&this->tracked_stracks[i]);
74
+ }
75
+
76
+ ////////////////// Step 2: First association, with IoU //////////////////
77
+ strack_pool = joint_stracks(tracked_stracks, this->lost_stracks);
78
+ STrack::multi_predict(strack_pool, this->kalman_filter);
79
+
80
+ vector<vector<float> > dists;
81
+ int dist_size = 0, dist_size_size = 0;
82
+ dists = iou_distance(strack_pool, detections, dist_size, dist_size_size);
83
+
84
+ vector<vector<int> > matches;
85
+ vector<int> u_track, u_detection;
86
+ linear_assignment(dists, dist_size, dist_size_size, match_thresh, matches, u_track, u_detection);
87
+
88
+ for (int i = 0; i < matches.size(); i++)
89
+ {
90
+ STrack *track = strack_pool[matches[i][0]];
91
+ STrack *det = &detections[matches[i][1]];
92
+ if (track->state == TrackState::Tracked)
93
+ {
94
+ track->update(*det, this->frame_id);
95
+ activated_stracks.push_back(*track);
96
+ }
97
+ else
98
+ {
99
+ track->re_activate(*det, this->frame_id, false);
100
+ refind_stracks.push_back(*track);
101
+ }
102
+ }
103
+
104
+ ////////////////// Step 3: Second association, using low score dets //////////////////
105
+ for (int i = 0; i < u_detection.size(); i++)
106
+ {
107
+ detections_cp.push_back(detections[u_detection[i]]);
108
+ }
109
+ detections.clear();
110
+ detections.assign(detections_low.begin(), detections_low.end());
111
+
112
+ for (int i = 0; i < u_track.size(); i++)
113
+ {
114
+ if (strack_pool[u_track[i]]->state == TrackState::Tracked)
115
+ {
116
+ r_tracked_stracks.push_back(strack_pool[u_track[i]]);
117
+ }
118
+ }
119
+
120
+ dists.clear();
121
+ dists = iou_distance(r_tracked_stracks, detections, dist_size, dist_size_size);
122
+
123
+ matches.clear();
124
+ u_track.clear();
125
+ u_detection.clear();
126
+ linear_assignment(dists, dist_size, dist_size_size, 0.5, matches, u_track, u_detection);
127
+
128
+ for (int i = 0; i < matches.size(); i++)
129
+ {
130
+ STrack *track = r_tracked_stracks[matches[i][0]];
131
+ STrack *det = &detections[matches[i][1]];
132
+ if (track->state == TrackState::Tracked)
133
+ {
134
+ track->update(*det, this->frame_id);
135
+ activated_stracks.push_back(*track);
136
+ }
137
+ else
138
+ {
139
+ track->re_activate(*det, this->frame_id, false);
140
+ refind_stracks.push_back(*track);
141
+ }
142
+ }
143
+
144
+ for (int i = 0; i < u_track.size(); i++)
145
+ {
146
+ STrack *track = r_tracked_stracks[u_track[i]];
147
+ if (track->state != TrackState::Lost)
148
+ {
149
+ track->mark_lost();
150
+ lost_stracks.push_back(*track);
151
+ }
152
+ }
153
+
154
+ // Deal with unconfirmed tracks, usually tracks with only one beginning frame
155
+ detections.clear();
156
+ detections.assign(detections_cp.begin(), detections_cp.end());
157
+
158
+ dists.clear();
159
+ dists = iou_distance(unconfirmed, detections, dist_size, dist_size_size);
160
+
161
+ matches.clear();
162
+ vector<int> u_unconfirmed;
163
+ u_detection.clear();
164
+ linear_assignment(dists, dist_size, dist_size_size, 0.7, matches, u_unconfirmed, u_detection);
165
+
166
+ for (int i = 0; i < matches.size(); i++)
167
+ {
168
+ unconfirmed[matches[i][0]]->update(detections[matches[i][1]], this->frame_id);
169
+ activated_stracks.push_back(*unconfirmed[matches[i][0]]);
170
+ }
171
+
172
+ for (int i = 0; i < u_unconfirmed.size(); i++)
173
+ {
174
+ STrack *track = unconfirmed[u_unconfirmed[i]];
175
+ track->mark_removed();
176
+ removed_stracks.push_back(*track);
177
+ }
178
+
179
+ ////////////////// Step 4: Init new stracks //////////////////
180
+ for (int i = 0; i < u_detection.size(); i++)
181
+ {
182
+ STrack *track = &detections[u_detection[i]];
183
+ if (track->score < this->high_thresh)
184
+ continue;
185
+ track->activate(this->kalman_filter, this->frame_id);
186
+ activated_stracks.push_back(*track);
187
+ }
188
+
189
+ ////////////////// Step 5: Update state //////////////////
190
+ for (int i = 0; i < this->lost_stracks.size(); i++)
191
+ {
192
+ if (this->frame_id - this->lost_stracks[i].end_frame() > this->max_time_lost)
193
+ {
194
+ this->lost_stracks[i].mark_removed();
195
+ removed_stracks.push_back(this->lost_stracks[i]);
196
+ }
197
+ }
198
+
199
+ for (int i = 0; i < this->tracked_stracks.size(); i++)
200
+ {
201
+ if (this->tracked_stracks[i].state == TrackState::Tracked)
202
+ {
203
+ tracked_stracks_swap.push_back(this->tracked_stracks[i]);
204
+ }
205
+ }
206
+ this->tracked_stracks.clear();
207
+ this->tracked_stracks.assign(tracked_stracks_swap.begin(), tracked_stracks_swap.end());
208
+
209
+ this->tracked_stracks = joint_stracks(this->tracked_stracks, activated_stracks);
210
+ this->tracked_stracks = joint_stracks(this->tracked_stracks, refind_stracks);
211
+
212
+ //std::cout << activated_stracks.size() << std::endl;
213
+
214
+ this->lost_stracks = sub_stracks(this->lost_stracks, this->tracked_stracks);
215
+ for (int i = 0; i < lost_stracks.size(); i++)
216
+ {
217
+ this->lost_stracks.push_back(lost_stracks[i]);
218
+ }
219
+
220
+ this->lost_stracks = sub_stracks(this->lost_stracks, this->removed_stracks);
221
+ for (int i = 0; i < removed_stracks.size(); i++)
222
+ {
223
+ this->removed_stracks.push_back(removed_stracks[i]);
224
+ }
225
+
226
+ remove_duplicate_stracks(resa, resb, this->tracked_stracks, this->lost_stracks);
227
+
228
+ this->tracked_stracks.clear();
229
+ this->tracked_stracks.assign(resa.begin(), resa.end());
230
+ this->lost_stracks.clear();
231
+ this->lost_stracks.assign(resb.begin(), resb.end());
232
+
233
+ for (int i = 0; i < this->tracked_stracks.size(); i++)
234
+ {
235
+ if (this->tracked_stracks[i].is_activated)
236
+ {
237
+ output_stracks.push_back(this->tracked_stracks[i]);
238
+ }
239
+ }
240
+ return output_stracks;
241
+ }
deploy/TensorRT/cpp/src/STrack.cpp ADDED
@@ -0,0 +1,192 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #include "STrack.h"
2
+
3
+ STrack::STrack(vector<float> tlwh_, float score)
4
+ {
5
+ _tlwh.resize(4);
6
+ _tlwh.assign(tlwh_.begin(), tlwh_.end());
7
+
8
+ is_activated = false;
9
+ track_id = 0;
10
+ state = TrackState::New;
11
+
12
+ tlwh.resize(4);
13
+ tlbr.resize(4);
14
+
15
+ static_tlwh();
16
+ static_tlbr();
17
+ frame_id = 0;
18
+ tracklet_len = 0;
19
+ this->score = score;
20
+ start_frame = 0;
21
+ }
22
+
23
+ STrack::~STrack()
24
+ {
25
+ }
26
+
27
+ void STrack::activate(byte_kalman::KalmanFilter &kalman_filter, int frame_id)
28
+ {
29
+ this->kalman_filter = kalman_filter;
30
+ this->track_id = this->next_id();
31
+
32
+ vector<float> _tlwh_tmp(4);
33
+ _tlwh_tmp[0] = this->_tlwh[0];
34
+ _tlwh_tmp[1] = this->_tlwh[1];
35
+ _tlwh_tmp[2] = this->_tlwh[2];
36
+ _tlwh_tmp[3] = this->_tlwh[3];
37
+ vector<float> xyah = tlwh_to_xyah(_tlwh_tmp);
38
+ DETECTBOX xyah_box;
39
+ xyah_box[0] = xyah[0];
40
+ xyah_box[1] = xyah[1];
41
+ xyah_box[2] = xyah[2];
42
+ xyah_box[3] = xyah[3];
43
+ auto mc = this->kalman_filter.initiate(xyah_box);
44
+ this->mean = mc.first;
45
+ this->covariance = mc.second;
46
+
47
+ static_tlwh();
48
+ static_tlbr();
49
+
50
+ this->tracklet_len = 0;
51
+ this->state = TrackState::Tracked;
52
+ if (frame_id == 1)
53
+ {
54
+ this->is_activated = true;
55
+ }
56
+ //this->is_activated = true;
57
+ this->frame_id = frame_id;
58
+ this->start_frame = frame_id;
59
+ }
60
+
61
+ void STrack::re_activate(STrack &new_track, int frame_id, bool new_id)
62
+ {
63
+ vector<float> xyah = tlwh_to_xyah(new_track.tlwh);
64
+ DETECTBOX xyah_box;
65
+ xyah_box[0] = xyah[0];
66
+ xyah_box[1] = xyah[1];
67
+ xyah_box[2] = xyah[2];
68
+ xyah_box[3] = xyah[3];
69
+ auto mc = this->kalman_filter.update(this->mean, this->covariance, xyah_box);
70
+ this->mean = mc.first;
71
+ this->covariance = mc.second;
72
+
73
+ static_tlwh();
74
+ static_tlbr();
75
+
76
+ this->tracklet_len = 0;
77
+ this->state = TrackState::Tracked;
78
+ this->is_activated = true;
79
+ this->frame_id = frame_id;
80
+ this->score = new_track.score;
81
+ if (new_id)
82
+ this->track_id = next_id();
83
+ }
84
+
85
+ void STrack::update(STrack &new_track, int frame_id)
86
+ {
87
+ this->frame_id = frame_id;
88
+ this->tracklet_len++;
89
+
90
+ vector<float> xyah = tlwh_to_xyah(new_track.tlwh);
91
+ DETECTBOX xyah_box;
92
+ xyah_box[0] = xyah[0];
93
+ xyah_box[1] = xyah[1];
94
+ xyah_box[2] = xyah[2];
95
+ xyah_box[3] = xyah[3];
96
+
97
+ auto mc = this->kalman_filter.update(this->mean, this->covariance, xyah_box);
98
+ this->mean = mc.first;
99
+ this->covariance = mc.second;
100
+
101
+ static_tlwh();
102
+ static_tlbr();
103
+
104
+ this->state = TrackState::Tracked;
105
+ this->is_activated = true;
106
+
107
+ this->score = new_track.score;
108
+ }
109
+
110
+ void STrack::static_tlwh()
111
+ {
112
+ if (this->state == TrackState::New)
113
+ {
114
+ tlwh[0] = _tlwh[0];
115
+ tlwh[1] = _tlwh[1];
116
+ tlwh[2] = _tlwh[2];
117
+ tlwh[3] = _tlwh[3];
118
+ return;
119
+ }
120
+
121
+ tlwh[0] = mean[0];
122
+ tlwh[1] = mean[1];
123
+ tlwh[2] = mean[2];
124
+ tlwh[3] = mean[3];
125
+
126
+ tlwh[2] *= tlwh[3];
127
+ tlwh[0] -= tlwh[2] / 2;
128
+ tlwh[1] -= tlwh[3] / 2;
129
+ }
130
+
131
+ void STrack::static_tlbr()
132
+ {
133
+ tlbr.clear();
134
+ tlbr.assign(tlwh.begin(), tlwh.end());
135
+ tlbr[2] += tlbr[0];
136
+ tlbr[3] += tlbr[1];
137
+ }
138
+
139
+ vector<float> STrack::tlwh_to_xyah(vector<float> tlwh_tmp)
140
+ {
141
+ vector<float> tlwh_output = tlwh_tmp;
142
+ tlwh_output[0] += tlwh_output[2] / 2;
143
+ tlwh_output[1] += tlwh_output[3] / 2;
144
+ tlwh_output[2] /= tlwh_output[3];
145
+ return tlwh_output;
146
+ }
147
+
148
+ vector<float> STrack::to_xyah()
149
+ {
150
+ return tlwh_to_xyah(tlwh);
151
+ }
152
+
153
+ vector<float> STrack::tlbr_to_tlwh(vector<float> &tlbr)
154
+ {
155
+ tlbr[2] -= tlbr[0];
156
+ tlbr[3] -= tlbr[1];
157
+ return tlbr;
158
+ }
159
+
160
+ void STrack::mark_lost()
161
+ {
162
+ state = TrackState::Lost;
163
+ }
164
+
165
+ void STrack::mark_removed()
166
+ {
167
+ state = TrackState::Removed;
168
+ }
169
+
170
+ int STrack::next_id()
171
+ {
172
+ static int _count = 0;
173
+ _count++;
174
+ return _count;
175
+ }
176
+
177
+ int STrack::end_frame()
178
+ {
179
+ return this->frame_id;
180
+ }
181
+
182
+ void STrack::multi_predict(vector<STrack*> &stracks, byte_kalman::KalmanFilter &kalman_filter)
183
+ {
184
+ for (int i = 0; i < stracks.size(); i++)
185
+ {
186
+ if (stracks[i]->state != TrackState::Tracked)
187
+ {
188
+ stracks[i]->mean[7] = 0;
189
+ }
190
+ kalman_filter.predict(stracks[i]->mean, stracks[i]->covariance);
191
+ }
192
+ }
deploy/TensorRT/cpp/src/bytetrack.cpp ADDED
@@ -0,0 +1,506 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #include <fstream>
2
+ #include <iostream>
3
+ #include <sstream>
4
+ #include <numeric>
5
+ #include <chrono>
6
+ #include <vector>
7
+ #include <opencv2/opencv.hpp>
8
+ #include <dirent.h>
9
+ #include "NvInfer.h"
10
+ #include "cuda_runtime_api.h"
11
+ #include "logging.h"
12
+ #include "BYTETracker.h"
13
+
14
+ #define CHECK(status) \
15
+ do\
16
+ {\
17
+ auto ret = (status);\
18
+ if (ret != 0)\
19
+ {\
20
+ cerr << "Cuda failure: " << ret << endl;\
21
+ abort();\
22
+ }\
23
+ } while (0)
24
+
25
+ #define DEVICE 0 // GPU id
26
+ #define NMS_THRESH 0.7
27
+ #define BBOX_CONF_THRESH 0.1
28
+
29
+ using namespace nvinfer1;
30
+
31
+ // stuff we know about the network and the input/output blobs
32
+ static const int INPUT_W = 1088;
33
+ static const int INPUT_H = 608;
34
+ const char* INPUT_BLOB_NAME = "input_0";
35
+ const char* OUTPUT_BLOB_NAME = "output_0";
36
+ static Logger gLogger;
37
+
38
+ Mat static_resize(Mat& img) {
39
+ float r = min(INPUT_W / (img.cols*1.0), INPUT_H / (img.rows*1.0));
40
+ // r = std::min(r, 1.0f);
41
+ int unpad_w = r * img.cols;
42
+ int unpad_h = r * img.rows;
43
+ Mat re(unpad_h, unpad_w, CV_8UC3);
44
+ resize(img, re, re.size());
45
+ Mat out(INPUT_H, INPUT_W, CV_8UC3, Scalar(114, 114, 114));
46
+ re.copyTo(out(Rect(0, 0, re.cols, re.rows)));
47
+ return out;
48
+ }
49
+
50
+ struct GridAndStride
51
+ {
52
+ int grid0;
53
+ int grid1;
54
+ int stride;
55
+ };
56
+
57
+ static void generate_grids_and_stride(const int target_w, const int target_h, vector<int>& strides, vector<GridAndStride>& grid_strides)
58
+ {
59
+ for (auto stride : strides)
60
+ {
61
+ int num_grid_w = target_w / stride;
62
+ int num_grid_h = target_h / stride;
63
+ for (int g1 = 0; g1 < num_grid_h; g1++)
64
+ {
65
+ for (int g0 = 0; g0 < num_grid_w; g0++)
66
+ {
67
+ grid_strides.push_back((GridAndStride){g0, g1, stride});
68
+ }
69
+ }
70
+ }
71
+ }
72
+
73
+ static inline float intersection_area(const Object& a, const Object& b)
74
+ {
75
+ Rect_<float> inter = a.rect & b.rect;
76
+ return inter.area();
77
+ }
78
+
79
+ static void qsort_descent_inplace(vector<Object>& faceobjects, int left, int right)
80
+ {
81
+ int i = left;
82
+ int j = right;
83
+ float p = faceobjects[(left + right) / 2].prob;
84
+
85
+ while (i <= j)
86
+ {
87
+ while (faceobjects[i].prob > p)
88
+ i++;
89
+
90
+ while (faceobjects[j].prob < p)
91
+ j--;
92
+
93
+ if (i <= j)
94
+ {
95
+ // swap
96
+ swap(faceobjects[i], faceobjects[j]);
97
+
98
+ i++;
99
+ j--;
100
+ }
101
+ }
102
+
103
+ #pragma omp parallel sections
104
+ {
105
+ #pragma omp section
106
+ {
107
+ if (left < j) qsort_descent_inplace(faceobjects, left, j);
108
+ }
109
+ #pragma omp section
110
+ {
111
+ if (i < right) qsort_descent_inplace(faceobjects, i, right);
112
+ }
113
+ }
114
+ }
115
+
116
+ static void qsort_descent_inplace(vector<Object>& objects)
117
+ {
118
+ if (objects.empty())
119
+ return;
120
+
121
+ qsort_descent_inplace(objects, 0, objects.size() - 1);
122
+ }
123
+
124
+ static void nms_sorted_bboxes(const vector<Object>& faceobjects, vector<int>& picked, float nms_threshold)
125
+ {
126
+ picked.clear();
127
+
128
+ const int n = faceobjects.size();
129
+
130
+ vector<float> areas(n);
131
+ for (int i = 0; i < n; i++)
132
+ {
133
+ areas[i] = faceobjects[i].rect.area();
134
+ }
135
+
136
+ for (int i = 0; i < n; i++)
137
+ {
138
+ const Object& a = faceobjects[i];
139
+
140
+ int keep = 1;
141
+ for (int j = 0; j < (int)picked.size(); j++)
142
+ {
143
+ const Object& b = faceobjects[picked[j]];
144
+
145
+ // intersection over union
146
+ float inter_area = intersection_area(a, b);
147
+ float union_area = areas[i] + areas[picked[j]] - inter_area;
148
+ // float IoU = inter_area / union_area
149
+ if (inter_area / union_area > nms_threshold)
150
+ keep = 0;
151
+ }
152
+
153
+ if (keep)
154
+ picked.push_back(i);
155
+ }
156
+ }
157
+
158
+
159
+ static void generate_yolox_proposals(vector<GridAndStride> grid_strides, float* feat_blob, float prob_threshold, vector<Object>& objects)
160
+ {
161
+ const int num_class = 1;
162
+
163
+ const int num_anchors = grid_strides.size();
164
+
165
+ for (int anchor_idx = 0; anchor_idx < num_anchors; anchor_idx++)
166
+ {
167
+ const int grid0 = grid_strides[anchor_idx].grid0;
168
+ const int grid1 = grid_strides[anchor_idx].grid1;
169
+ const int stride = grid_strides[anchor_idx].stride;
170
+
171
+ const int basic_pos = anchor_idx * (num_class + 5);
172
+
173
+ // yolox/models/yolo_head.py decode logic
174
+ float x_center = (feat_blob[basic_pos+0] + grid0) * stride;
175
+ float y_center = (feat_blob[basic_pos+1] + grid1) * stride;
176
+ float w = exp(feat_blob[basic_pos+2]) * stride;
177
+ float h = exp(feat_blob[basic_pos+3]) * stride;
178
+ float x0 = x_center - w * 0.5f;
179
+ float y0 = y_center - h * 0.5f;
180
+
181
+ float box_objectness = feat_blob[basic_pos+4];
182
+ for (int class_idx = 0; class_idx < num_class; class_idx++)
183
+ {
184
+ float box_cls_score = feat_blob[basic_pos + 5 + class_idx];
185
+ float box_prob = box_objectness * box_cls_score;
186
+ if (box_prob > prob_threshold)
187
+ {
188
+ Object obj;
189
+ obj.rect.x = x0;
190
+ obj.rect.y = y0;
191
+ obj.rect.width = w;
192
+ obj.rect.height = h;
193
+ obj.label = class_idx;
194
+ obj.prob = box_prob;
195
+
196
+ objects.push_back(obj);
197
+ }
198
+
199
+ } // class loop
200
+
201
+ } // point anchor loop
202
+ }
203
+
204
+ float* blobFromImage(Mat& img){
205
+ cvtColor(img, img, COLOR_BGR2RGB);
206
+
207
+ float* blob = new float[img.total()*3];
208
+ int channels = 3;
209
+ int img_h = img.rows;
210
+ int img_w = img.cols;
211
+ vector<float> mean = {0.485, 0.456, 0.406};
212
+ vector<float> std = {0.229, 0.224, 0.225};
213
+ for (size_t c = 0; c < channels; c++)
214
+ {
215
+ for (size_t h = 0; h < img_h; h++)
216
+ {
217
+ for (size_t w = 0; w < img_w; w++)
218
+ {
219
+ blob[c * img_w * img_h + h * img_w + w] =
220
+ (((float)img.at<Vec3b>(h, w)[c]) / 255.0f - mean[c]) / std[c];
221
+ }
222
+ }
223
+ }
224
+ return blob;
225
+ }
226
+
227
+
228
+ static void decode_outputs(float* prob, vector<Object>& objects, float scale, const int img_w, const int img_h) {
229
+ vector<Object> proposals;
230
+ vector<int> strides = {8, 16, 32};
231
+ vector<GridAndStride> grid_strides;
232
+ generate_grids_and_stride(INPUT_W, INPUT_H, strides, grid_strides);
233
+ generate_yolox_proposals(grid_strides, prob, BBOX_CONF_THRESH, proposals);
234
+ //std::cout << "num of boxes before nms: " << proposals.size() << std::endl;
235
+
236
+ qsort_descent_inplace(proposals);
237
+
238
+ vector<int> picked;
239
+ nms_sorted_bboxes(proposals, picked, NMS_THRESH);
240
+
241
+
242
+ int count = picked.size();
243
+
244
+ //std::cout << "num of boxes: " << count << std::endl;
245
+
246
+ objects.resize(count);
247
+ for (int i = 0; i < count; i++)
248
+ {
249
+ objects[i] = proposals[picked[i]];
250
+
251
+ // adjust offset to original unpadded
252
+ float x0 = (objects[i].rect.x) / scale;
253
+ float y0 = (objects[i].rect.y) / scale;
254
+ float x1 = (objects[i].rect.x + objects[i].rect.width) / scale;
255
+ float y1 = (objects[i].rect.y + objects[i].rect.height) / scale;
256
+
257
+ // clip
258
+ // x0 = std::max(std::min(x0, (float)(img_w - 1)), 0.f);
259
+ // y0 = std::max(std::min(y0, (float)(img_h - 1)), 0.f);
260
+ // x1 = std::max(std::min(x1, (float)(img_w - 1)), 0.f);
261
+ // y1 = std::max(std::min(y1, (float)(img_h - 1)), 0.f);
262
+
263
+ objects[i].rect.x = x0;
264
+ objects[i].rect.y = y0;
265
+ objects[i].rect.width = x1 - x0;
266
+ objects[i].rect.height = y1 - y0;
267
+ }
268
+ }
269
+
270
+ const float color_list[80][3] =
271
+ {
272
+ {0.000, 0.447, 0.741},
273
+ {0.850, 0.325, 0.098},
274
+ {0.929, 0.694, 0.125},
275
+ {0.494, 0.184, 0.556},
276
+ {0.466, 0.674, 0.188},
277
+ {0.301, 0.745, 0.933},
278
+ {0.635, 0.078, 0.184},
279
+ {0.300, 0.300, 0.300},
280
+ {0.600, 0.600, 0.600},
281
+ {1.000, 0.000, 0.000},
282
+ {1.000, 0.500, 0.000},
283
+ {0.749, 0.749, 0.000},
284
+ {0.000, 1.000, 0.000},
285
+ {0.000, 0.000, 1.000},
286
+ {0.667, 0.000, 1.000},
287
+ {0.333, 0.333, 0.000},
288
+ {0.333, 0.667, 0.000},
289
+ {0.333, 1.000, 0.000},
290
+ {0.667, 0.333, 0.000},
291
+ {0.667, 0.667, 0.000},
292
+ {0.667, 1.000, 0.000},
293
+ {1.000, 0.333, 0.000},
294
+ {1.000, 0.667, 0.000},
295
+ {1.000, 1.000, 0.000},
296
+ {0.000, 0.333, 0.500},
297
+ {0.000, 0.667, 0.500},
298
+ {0.000, 1.000, 0.500},
299
+ {0.333, 0.000, 0.500},
300
+ {0.333, 0.333, 0.500},
301
+ {0.333, 0.667, 0.500},
302
+ {0.333, 1.000, 0.500},
303
+ {0.667, 0.000, 0.500},
304
+ {0.667, 0.333, 0.500},
305
+ {0.667, 0.667, 0.500},
306
+ {0.667, 1.000, 0.500},
307
+ {1.000, 0.000, 0.500},
308
+ {1.000, 0.333, 0.500},
309
+ {1.000, 0.667, 0.500},
310
+ {1.000, 1.000, 0.500},
311
+ {0.000, 0.333, 1.000},
312
+ {0.000, 0.667, 1.000},
313
+ {0.000, 1.000, 1.000},
314
+ {0.333, 0.000, 1.000},
315
+ {0.333, 0.333, 1.000},
316
+ {0.333, 0.667, 1.000},
317
+ {0.333, 1.000, 1.000},
318
+ {0.667, 0.000, 1.000},
319
+ {0.667, 0.333, 1.000},
320
+ {0.667, 0.667, 1.000},
321
+ {0.667, 1.000, 1.000},
322
+ {1.000, 0.000, 1.000},
323
+ {1.000, 0.333, 1.000},
324
+ {1.000, 0.667, 1.000},
325
+ {0.333, 0.000, 0.000},
326
+ {0.500, 0.000, 0.000},
327
+ {0.667, 0.000, 0.000},
328
+ {0.833, 0.000, 0.000},
329
+ {1.000, 0.000, 0.000},
330
+ {0.000, 0.167, 0.000},
331
+ {0.000, 0.333, 0.000},
332
+ {0.000, 0.500, 0.000},
333
+ {0.000, 0.667, 0.000},
334
+ {0.000, 0.833, 0.000},
335
+ {0.000, 1.000, 0.000},
336
+ {0.000, 0.000, 0.167},
337
+ {0.000, 0.000, 0.333},
338
+ {0.000, 0.000, 0.500},
339
+ {0.000, 0.000, 0.667},
340
+ {0.000, 0.000, 0.833},
341
+ {0.000, 0.000, 1.000},
342
+ {0.000, 0.000, 0.000},
343
+ {0.143, 0.143, 0.143},
344
+ {0.286, 0.286, 0.286},
345
+ {0.429, 0.429, 0.429},
346
+ {0.571, 0.571, 0.571},
347
+ {0.714, 0.714, 0.714},
348
+ {0.857, 0.857, 0.857},
349
+ {0.000, 0.447, 0.741},
350
+ {0.314, 0.717, 0.741},
351
+ {0.50, 0.5, 0}
352
+ };
353
+
354
+ void doInference(IExecutionContext& context, float* input, float* output, const int output_size, Size input_shape) {
355
+ const ICudaEngine& engine = context.getEngine();
356
+
357
+ // Pointers to input and output device buffers to pass to engine.
358
+ // Engine requires exactly IEngine::getNbBindings() number of buffers.
359
+ assert(engine.getNbBindings() == 2);
360
+ void* buffers[2];
361
+
362
+ // In order to bind the buffers, we need to know the names of the input and output tensors.
363
+ // Note that indices are guaranteed to be less than IEngine::getNbBindings()
364
+ const int inputIndex = engine.getBindingIndex(INPUT_BLOB_NAME);
365
+
366
+ assert(engine.getBindingDataType(inputIndex) == nvinfer1::DataType::kFLOAT);
367
+ const int outputIndex = engine.getBindingIndex(OUTPUT_BLOB_NAME);
368
+ assert(engine.getBindingDataType(outputIndex) == nvinfer1::DataType::kFLOAT);
369
+ int mBatchSize = engine.getMaxBatchSize();
370
+
371
+ // Create GPU buffers on device
372
+ CHECK(cudaMalloc(&buffers[inputIndex], 3 * input_shape.height * input_shape.width * sizeof(float)));
373
+ CHECK(cudaMalloc(&buffers[outputIndex], output_size*sizeof(float)));
374
+
375
+ // Create stream
376
+ cudaStream_t stream;
377
+ CHECK(cudaStreamCreate(&stream));
378
+
379
+ // DMA input batch data to device, infer on the batch asynchronously, and DMA output back to host
380
+ CHECK(cudaMemcpyAsync(buffers[inputIndex], input, 3 * input_shape.height * input_shape.width * sizeof(float), cudaMemcpyHostToDevice, stream));
381
+ context.enqueue(1, buffers, stream, nullptr);
382
+ CHECK(cudaMemcpyAsync(output, buffers[outputIndex], output_size * sizeof(float), cudaMemcpyDeviceToHost, stream));
383
+ cudaStreamSynchronize(stream);
384
+
385
+ // Release stream and buffers
386
+ cudaStreamDestroy(stream);
387
+ CHECK(cudaFree(buffers[inputIndex]));
388
+ CHECK(cudaFree(buffers[outputIndex]));
389
+ }
390
+
391
+ int main(int argc, char** argv) {
392
+ cudaSetDevice(DEVICE);
393
+
394
+ // create a model using the API directly and serialize it to a stream
395
+ char *trtModelStream{nullptr};
396
+ size_t size{0};
397
+
398
+ if (argc == 4 && string(argv[2]) == "-i") {
399
+ const string engine_file_path {argv[1]};
400
+ ifstream file(engine_file_path, ios::binary);
401
+ if (file.good()) {
402
+ file.seekg(0, file.end);
403
+ size = file.tellg();
404
+ file.seekg(0, file.beg);
405
+ trtModelStream = new char[size];
406
+ assert(trtModelStream);
407
+ file.read(trtModelStream, size);
408
+ file.close();
409
+ }
410
+ } else {
411
+ cerr << "arguments not right!" << endl;
412
+ cerr << "run 'python3 tools/trt.py -f exps/example/mot/yolox_s_mix_det.py -c pretrained/bytetrack_s_mot17.pth.tar' to serialize model first!" << std::endl;
413
+ cerr << "Then use the following command:" << endl;
414
+ cerr << "cd demo/TensorRT/cpp/build" << endl;
415
+ cerr << "./bytetrack ../../../../YOLOX_outputs/yolox_s_mix_det/model_trt.engine -i ../../../../videos/palace.mp4 // deserialize file and run inference" << std::endl;
416
+ return -1;
417
+ }
418
+ const string input_video_path {argv[3]};
419
+
420
+ IRuntime* runtime = createInferRuntime(gLogger);
421
+ assert(runtime != nullptr);
422
+ ICudaEngine* engine = runtime->deserializeCudaEngine(trtModelStream, size);
423
+ assert(engine != nullptr);
424
+ IExecutionContext* context = engine->createExecutionContext();
425
+ assert(context != nullptr);
426
+ delete[] trtModelStream;
427
+ auto out_dims = engine->getBindingDimensions(1);
428
+ auto output_size = 1;
429
+ for(int j=0;j<out_dims.nbDims;j++) {
430
+ output_size *= out_dims.d[j];
431
+ }
432
+ static float* prob = new float[output_size];
433
+
434
+ VideoCapture cap(input_video_path);
435
+ if (!cap.isOpened())
436
+ return 0;
437
+
438
+ int img_w = cap.get(CV_CAP_PROP_FRAME_WIDTH);
439
+ int img_h = cap.get(CV_CAP_PROP_FRAME_HEIGHT);
440
+ int fps = cap.get(CV_CAP_PROP_FPS);
441
+ long nFrame = static_cast<long>(cap.get(CV_CAP_PROP_FRAME_COUNT));
442
+ cout << "Total frames: " << nFrame << endl;
443
+
444
+ VideoWriter writer("demo.mp4", CV_FOURCC('m', 'p', '4', 'v'), fps, Size(img_w, img_h));
445
+
446
+ Mat img;
447
+ BYTETracker tracker(fps, 30);
448
+ int num_frames = 0;
449
+ int total_ms = 0;
450
+ while (true)
451
+ {
452
+ if(!cap.read(img))
453
+ break;
454
+ num_frames ++;
455
+ if (num_frames % 20 == 0)
456
+ {
457
+ cout << "Processing frame " << num_frames << " (" << num_frames * 1000000 / total_ms << " fps)" << endl;
458
+ }
459
+ if (img.empty())
460
+ break;
461
+ Mat pr_img = static_resize(img);
462
+
463
+ float* blob;
464
+ blob = blobFromImage(pr_img);
465
+ float scale = min(INPUT_W / (img.cols*1.0), INPUT_H / (img.rows*1.0));
466
+
467
+ // run inference
468
+ auto start = chrono::system_clock::now();
469
+ doInference(*context, blob, prob, output_size, pr_img.size());
470
+ vector<Object> objects;
471
+ decode_outputs(prob, objects, scale, img_w, img_h);
472
+ vector<STrack> output_stracks = tracker.update(objects);
473
+ auto end = chrono::system_clock::now();
474
+ total_ms = total_ms + chrono::duration_cast<chrono::microseconds>(end - start).count();
475
+
476
+ for (int i = 0; i < output_stracks.size(); i++)
477
+ {
478
+ vector<float> tlwh = output_stracks[i].tlwh;
479
+ bool vertical = tlwh[2] / tlwh[3] > 1.6;
480
+ if (tlwh[2] * tlwh[3] > 20 && !vertical)
481
+ {
482
+ Scalar s = tracker.get_color(output_stracks[i].track_id);
483
+ putText(img, format("%d", output_stracks[i].track_id), Point(tlwh[0], tlwh[1] - 5),
484
+ 0, 0.6, Scalar(0, 0, 255), 2, LINE_AA);
485
+ rectangle(img, Rect(tlwh[0], tlwh[1], tlwh[2], tlwh[3]), s, 2);
486
+ }
487
+ }
488
+ putText(img, format("frame: %d fps: %d num: %d", num_frames, num_frames * 1000000 / total_ms, output_stracks.size()),
489
+ Point(0, 30), 0, 0.6, Scalar(0, 0, 255), 2, LINE_AA);
490
+ writer.write(img);
491
+
492
+ delete blob;
493
+ char c = waitKey(1);
494
+ if (c > 0)
495
+ {
496
+ break;
497
+ }
498
+ }
499
+ cap.release();
500
+ cout << "FPS: " << num_frames * 1000000 / total_ms << endl;
501
+ // destroy the engine
502
+ context->destroy();
503
+ engine->destroy();
504
+ runtime->destroy();
505
+ return 0;
506
+ }
deploy/TensorRT/cpp/src/kalmanFilter.cpp ADDED
@@ -0,0 +1,152 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #include "kalmanFilter.h"
2
+ #include <Eigen/Cholesky>
3
+
4
+ namespace byte_kalman
5
+ {
6
+ const double KalmanFilter::chi2inv95[10] = {
7
+ 0,
8
+ 3.8415,
9
+ 5.9915,
10
+ 7.8147,
11
+ 9.4877,
12
+ 11.070,
13
+ 12.592,
14
+ 14.067,
15
+ 15.507,
16
+ 16.919
17
+ };
18
+ KalmanFilter::KalmanFilter()
19
+ {
20
+ int ndim = 4;
21
+ double dt = 1.;
22
+
23
+ _motion_mat = Eigen::MatrixXf::Identity(8, 8);
24
+ for (int i = 0; i < ndim; i++) {
25
+ _motion_mat(i, ndim + i) = dt;
26
+ }
27
+ _update_mat = Eigen::MatrixXf::Identity(4, 8);
28
+
29
+ this->_std_weight_position = 1. / 20;
30
+ this->_std_weight_velocity = 1. / 160;
31
+ }
32
+
33
+ KAL_DATA KalmanFilter::initiate(const DETECTBOX &measurement)
34
+ {
35
+ DETECTBOX mean_pos = measurement;
36
+ DETECTBOX mean_vel;
37
+ for (int i = 0; i < 4; i++) mean_vel(i) = 0;
38
+
39
+ KAL_MEAN mean;
40
+ for (int i = 0; i < 8; i++) {
41
+ if (i < 4) mean(i) = mean_pos(i);
42
+ else mean(i) = mean_vel(i - 4);
43
+ }
44
+
45
+ KAL_MEAN std;
46
+ std(0) = 2 * _std_weight_position * measurement[3];
47
+ std(1) = 2 * _std_weight_position * measurement[3];
48
+ std(2) = 1e-2;
49
+ std(3) = 2 * _std_weight_position * measurement[3];
50
+ std(4) = 10 * _std_weight_velocity * measurement[3];
51
+ std(5) = 10 * _std_weight_velocity * measurement[3];
52
+ std(6) = 1e-5;
53
+ std(7) = 10 * _std_weight_velocity * measurement[3];
54
+
55
+ KAL_MEAN tmp = std.array().square();
56
+ KAL_COVA var = tmp.asDiagonal();
57
+ return std::make_pair(mean, var);
58
+ }
59
+
60
+ void KalmanFilter::predict(KAL_MEAN &mean, KAL_COVA &covariance)
61
+ {
62
+ //revise the data;
63
+ DETECTBOX std_pos;
64
+ std_pos << _std_weight_position * mean(3),
65
+ _std_weight_position * mean(3),
66
+ 1e-2,
67
+ _std_weight_position * mean(3);
68
+ DETECTBOX std_vel;
69
+ std_vel << _std_weight_velocity * mean(3),
70
+ _std_weight_velocity * mean(3),
71
+ 1e-5,
72
+ _std_weight_velocity * mean(3);
73
+ KAL_MEAN tmp;
74
+ tmp.block<1, 4>(0, 0) = std_pos;
75
+ tmp.block<1, 4>(0, 4) = std_vel;
76
+ tmp = tmp.array().square();
77
+ KAL_COVA motion_cov = tmp.asDiagonal();
78
+ KAL_MEAN mean1 = this->_motion_mat * mean.transpose();
79
+ KAL_COVA covariance1 = this->_motion_mat * covariance *(_motion_mat.transpose());
80
+ covariance1 += motion_cov;
81
+
82
+ mean = mean1;
83
+ covariance = covariance1;
84
+ }
85
+
86
+ KAL_HDATA KalmanFilter::project(const KAL_MEAN &mean, const KAL_COVA &covariance)
87
+ {
88
+ DETECTBOX std;
89
+ std << _std_weight_position * mean(3), _std_weight_position * mean(3),
90
+ 1e-1, _std_weight_position * mean(3);
91
+ KAL_HMEAN mean1 = _update_mat * mean.transpose();
92
+ KAL_HCOVA covariance1 = _update_mat * covariance * (_update_mat.transpose());
93
+ Eigen::Matrix<float, 4, 4> diag = std.asDiagonal();
94
+ diag = diag.array().square().matrix();
95
+ covariance1 += diag;
96
+ // covariance1.diagonal() << diag;
97
+ return std::make_pair(mean1, covariance1);
98
+ }
99
+
100
+ KAL_DATA
101
+ KalmanFilter::update(
102
+ const KAL_MEAN &mean,
103
+ const KAL_COVA &covariance,
104
+ const DETECTBOX &measurement)
105
+ {
106
+ KAL_HDATA pa = project(mean, covariance);
107
+ KAL_HMEAN projected_mean = pa.first;
108
+ KAL_HCOVA projected_cov = pa.second;
109
+
110
+ //chol_factor, lower =
111
+ //scipy.linalg.cho_factor(projected_cov, lower=True, check_finite=False)
112
+ //kalmain_gain =
113
+ //scipy.linalg.cho_solve((cho_factor, lower),
114
+ //np.dot(covariance, self._upadte_mat.T).T,
115
+ //check_finite=False).T
116
+ Eigen::Matrix<float, 4, 8> B = (covariance * (_update_mat.transpose())).transpose();
117
+ Eigen::Matrix<float, 8, 4> kalman_gain = (projected_cov.llt().solve(B)).transpose(); // eg.8x4
118
+ Eigen::Matrix<float, 1, 4> innovation = measurement - projected_mean; //eg.1x4
119
+ auto tmp = innovation * (kalman_gain.transpose());
120
+ KAL_MEAN new_mean = (mean.array() + tmp.array()).matrix();
121
+ KAL_COVA new_covariance = covariance - kalman_gain * projected_cov*(kalman_gain.transpose());
122
+ return std::make_pair(new_mean, new_covariance);
123
+ }
124
+
125
+ Eigen::Matrix<float, 1, -1>
126
+ KalmanFilter::gating_distance(
127
+ const KAL_MEAN &mean,
128
+ const KAL_COVA &covariance,
129
+ const std::vector<DETECTBOX> &measurements,
130
+ bool only_position)
131
+ {
132
+ KAL_HDATA pa = this->project(mean, covariance);
133
+ if (only_position) {
134
+ printf("not implement!");
135
+ exit(0);
136
+ }
137
+ KAL_HMEAN mean1 = pa.first;
138
+ KAL_HCOVA covariance1 = pa.second;
139
+
140
+ // Eigen::Matrix<float, -1, 4, Eigen::RowMajor> d(size, 4);
141
+ DETECTBOXSS d(measurements.size(), 4);
142
+ int pos = 0;
143
+ for (DETECTBOX box : measurements) {
144
+ d.row(pos++) = box - mean1;
145
+ }
146
+ Eigen::Matrix<float, -1, -1, Eigen::RowMajor> factor = covariance1.llt().matrixL();
147
+ Eigen::Matrix<float, -1, -1> z = factor.triangularView<Eigen::Lower>().solve<Eigen::OnTheRight>(d).transpose();
148
+ auto zz = ((z.array())*(z.array())).matrix();
149
+ auto square_maha = zz.colwise().sum();
150
+ return square_maha;
151
+ }
152
+ }
deploy/TensorRT/cpp/src/lapjv.cpp ADDED
@@ -0,0 +1,343 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #include <stdio.h>
2
+ #include <stdlib.h>
3
+ #include <string.h>
4
+
5
+ #include "lapjv.h"
6
+
7
+ /** Column-reduction and reduction transfer for a dense cost matrix.
8
+ */
9
+ int_t _ccrrt_dense(const uint_t n, cost_t *cost[],
10
+ int_t *free_rows, int_t *x, int_t *y, cost_t *v)
11
+ {
12
+ int_t n_free_rows;
13
+ boolean *unique;
14
+
15
+ for (uint_t i = 0; i < n; i++) {
16
+ x[i] = -1;
17
+ v[i] = LARGE;
18
+ y[i] = 0;
19
+ }
20
+ for (uint_t i = 0; i < n; i++) {
21
+ for (uint_t j = 0; j < n; j++) {
22
+ const cost_t c = cost[i][j];
23
+ if (c < v[j]) {
24
+ v[j] = c;
25
+ y[j] = i;
26
+ }
27
+ PRINTF("i=%d, j=%d, c[i,j]=%f, v[j]=%f y[j]=%d\n", i, j, c, v[j], y[j]);
28
+ }
29
+ }
30
+ PRINT_COST_ARRAY(v, n);
31
+ PRINT_INDEX_ARRAY(y, n);
32
+ NEW(unique, boolean, n);
33
+ memset(unique, TRUE, n);
34
+ {
35
+ int_t j = n;
36
+ do {
37
+ j--;
38
+ const int_t i = y[j];
39
+ if (x[i] < 0) {
40
+ x[i] = j;
41
+ }
42
+ else {
43
+ unique[i] = FALSE;
44
+ y[j] = -1;
45
+ }
46
+ } while (j > 0);
47
+ }
48
+ n_free_rows = 0;
49
+ for (uint_t i = 0; i < n; i++) {
50
+ if (x[i] < 0) {
51
+ free_rows[n_free_rows++] = i;
52
+ }
53
+ else if (unique[i]) {
54
+ const int_t j = x[i];
55
+ cost_t min = LARGE;
56
+ for (uint_t j2 = 0; j2 < n; j2++) {
57
+ if (j2 == (uint_t)j) {
58
+ continue;
59
+ }
60
+ const cost_t c = cost[i][j2] - v[j2];
61
+ if (c < min) {
62
+ min = c;
63
+ }
64
+ }
65
+ PRINTF("v[%d] = %f - %f\n", j, v[j], min);
66
+ v[j] -= min;
67
+ }
68
+ }
69
+ FREE(unique);
70
+ return n_free_rows;
71
+ }
72
+
73
+
74
+ /** Augmenting row reduction for a dense cost matrix.
75
+ */
76
+ int_t _carr_dense(
77
+ const uint_t n, cost_t *cost[],
78
+ const uint_t n_free_rows,
79
+ int_t *free_rows, int_t *x, int_t *y, cost_t *v)
80
+ {
81
+ uint_t current = 0;
82
+ int_t new_free_rows = 0;
83
+ uint_t rr_cnt = 0;
84
+ PRINT_INDEX_ARRAY(x, n);
85
+ PRINT_INDEX_ARRAY(y, n);
86
+ PRINT_COST_ARRAY(v, n);
87
+ PRINT_INDEX_ARRAY(free_rows, n_free_rows);
88
+ while (current < n_free_rows) {
89
+ int_t i0;
90
+ int_t j1, j2;
91
+ cost_t v1, v2, v1_new;
92
+ boolean v1_lowers;
93
+
94
+ rr_cnt++;
95
+ PRINTF("current = %d rr_cnt = %d\n", current, rr_cnt);
96
+ const int_t free_i = free_rows[current++];
97
+ j1 = 0;
98
+ v1 = cost[free_i][0] - v[0];
99
+ j2 = -1;
100
+ v2 = LARGE;
101
+ for (uint_t j = 1; j < n; j++) {
102
+ PRINTF("%d = %f %d = %f\n", j1, v1, j2, v2);
103
+ const cost_t c = cost[free_i][j] - v[j];
104
+ if (c < v2) {
105
+ if (c >= v1) {
106
+ v2 = c;
107
+ j2 = j;
108
+ }
109
+ else {
110
+ v2 = v1;
111
+ v1 = c;
112
+ j2 = j1;
113
+ j1 = j;
114
+ }
115
+ }
116
+ }
117
+ i0 = y[j1];
118
+ v1_new = v[j1] - (v2 - v1);
119
+ v1_lowers = v1_new < v[j1];
120
+ PRINTF("%d %d 1=%d,%f 2=%d,%f v1'=%f(%d,%g) \n", free_i, i0, j1, v1, j2, v2, v1_new, v1_lowers, v[j1] - v1_new);
121
+ if (rr_cnt < current * n) {
122
+ if (v1_lowers) {
123
+ v[j1] = v1_new;
124
+ }
125
+ else if (i0 >= 0 && j2 >= 0) {
126
+ j1 = j2;
127
+ i0 = y[j2];
128
+ }
129
+ if (i0 >= 0) {
130
+ if (v1_lowers) {
131
+ free_rows[--current] = i0;
132
+ }
133
+ else {
134
+ free_rows[new_free_rows++] = i0;
135
+ }
136
+ }
137
+ }
138
+ else {
139
+ PRINTF("rr_cnt=%d >= %d (current=%d * n=%d)\n", rr_cnt, current * n, current, n);
140
+ if (i0 >= 0) {
141
+ free_rows[new_free_rows++] = i0;
142
+ }
143
+ }
144
+ x[free_i] = j1;
145
+ y[j1] = free_i;
146
+ }
147
+ return new_free_rows;
148
+ }
149
+
150
+
151
+ /** Find columns with minimum d[j] and put them on the SCAN list.
152
+ */
153
+ uint_t _find_dense(const uint_t n, uint_t lo, cost_t *d, int_t *cols, int_t *y)
154
+ {
155
+ uint_t hi = lo + 1;
156
+ cost_t mind = d[cols[lo]];
157
+ for (uint_t k = hi; k < n; k++) {
158
+ int_t j = cols[k];
159
+ if (d[j] <= mind) {
160
+ if (d[j] < mind) {
161
+ hi = lo;
162
+ mind = d[j];
163
+ }
164
+ cols[k] = cols[hi];
165
+ cols[hi++] = j;
166
+ }
167
+ }
168
+ return hi;
169
+ }
170
+
171
+
172
+ // Scan all columns in TODO starting from arbitrary column in SCAN
173
+ // and try to decrease d of the TODO columns using the SCAN column.
174
+ int_t _scan_dense(const uint_t n, cost_t *cost[],
175
+ uint_t *plo, uint_t*phi,
176
+ cost_t *d, int_t *cols, int_t *pred,
177
+ int_t *y, cost_t *v)
178
+ {
179
+ uint_t lo = *plo;
180
+ uint_t hi = *phi;
181
+ cost_t h, cred_ij;
182
+
183
+ while (lo != hi) {
184
+ int_t j = cols[lo++];
185
+ const int_t i = y[j];
186
+ const cost_t mind = d[j];
187
+ h = cost[i][j] - v[j] - mind;
188
+ PRINTF("i=%d j=%d h=%f\n", i, j, h);
189
+ // For all columns in TODO
190
+ for (uint_t k = hi; k < n; k++) {
191
+ j = cols[k];
192
+ cred_ij = cost[i][j] - v[j] - h;
193
+ if (cred_ij < d[j]) {
194
+ d[j] = cred_ij;
195
+ pred[j] = i;
196
+ if (cred_ij == mind) {
197
+ if (y[j] < 0) {
198
+ return j;
199
+ }
200
+ cols[k] = cols[hi];
201
+ cols[hi++] = j;
202
+ }
203
+ }
204
+ }
205
+ }
206
+ *plo = lo;
207
+ *phi = hi;
208
+ return -1;
209
+ }
210
+
211
+
212
+ /** Single iteration of modified Dijkstra shortest path algorithm as explained in the JV paper.
213
+ *
214
+ * This is a dense matrix version.
215
+ *
216
+ * \return The closest free column index.
217
+ */
218
+ int_t find_path_dense(
219
+ const uint_t n, cost_t *cost[],
220
+ const int_t start_i,
221
+ int_t *y, cost_t *v,
222
+ int_t *pred)
223
+ {
224
+ uint_t lo = 0, hi = 0;
225
+ int_t final_j = -1;
226
+ uint_t n_ready = 0;
227
+ int_t *cols;
228
+ cost_t *d;
229
+
230
+ NEW(cols, int_t, n);
231
+ NEW(d, cost_t, n);
232
+
233
+ for (uint_t i = 0; i < n; i++) {
234
+ cols[i] = i;
235
+ pred[i] = start_i;
236
+ d[i] = cost[start_i][i] - v[i];
237
+ }
238
+ PRINT_COST_ARRAY(d, n);
239
+ while (final_j == -1) {
240
+ // No columns left on the SCAN list.
241
+ if (lo == hi) {
242
+ PRINTF("%d..%d -> find\n", lo, hi);
243
+ n_ready = lo;
244
+ hi = _find_dense(n, lo, d, cols, y);
245
+ PRINTF("check %d..%d\n", lo, hi);
246
+ PRINT_INDEX_ARRAY(cols, n);
247
+ for (uint_t k = lo; k < hi; k++) {
248
+ const int_t j = cols[k];
249
+ if (y[j] < 0) {
250
+ final_j = j;
251
+ }
252
+ }
253
+ }
254
+ if (final_j == -1) {
255
+ PRINTF("%d..%d -> scan\n", lo, hi);
256
+ final_j = _scan_dense(
257
+ n, cost, &lo, &hi, d, cols, pred, y, v);
258
+ PRINT_COST_ARRAY(d, n);
259
+ PRINT_INDEX_ARRAY(cols, n);
260
+ PRINT_INDEX_ARRAY(pred, n);
261
+ }
262
+ }
263
+
264
+ PRINTF("found final_j=%d\n", final_j);
265
+ PRINT_INDEX_ARRAY(cols, n);
266
+ {
267
+ const cost_t mind = d[cols[lo]];
268
+ for (uint_t k = 0; k < n_ready; k++) {
269
+ const int_t j = cols[k];
270
+ v[j] += d[j] - mind;
271
+ }
272
+ }
273
+
274
+ FREE(cols);
275
+ FREE(d);
276
+
277
+ return final_j;
278
+ }
279
+
280
+
281
+ /** Augment for a dense cost matrix.
282
+ */
283
+ int_t _ca_dense(
284
+ const uint_t n, cost_t *cost[],
285
+ const uint_t n_free_rows,
286
+ int_t *free_rows, int_t *x, int_t *y, cost_t *v)
287
+ {
288
+ int_t *pred;
289
+
290
+ NEW(pred, int_t, n);
291
+
292
+ for (int_t *pfree_i = free_rows; pfree_i < free_rows + n_free_rows; pfree_i++) {
293
+ int_t i = -1, j;
294
+ uint_t k = 0;
295
+
296
+ PRINTF("looking at free_i=%d\n", *pfree_i);
297
+ j = find_path_dense(n, cost, *pfree_i, y, v, pred);
298
+ ASSERT(j >= 0);
299
+ ASSERT(j < n);
300
+ while (i != *pfree_i) {
301
+ PRINTF("augment %d\n", j);
302
+ PRINT_INDEX_ARRAY(pred, n);
303
+ i = pred[j];
304
+ PRINTF("y[%d]=%d -> %d\n", j, y[j], i);
305
+ y[j] = i;
306
+ PRINT_INDEX_ARRAY(x, n);
307
+ SWAP_INDICES(j, x[i]);
308
+ k++;
309
+ if (k >= n) {
310
+ ASSERT(FALSE);
311
+ }
312
+ }
313
+ }
314
+ FREE(pred);
315
+ return 0;
316
+ }
317
+
318
+
319
+ /** Solve dense sparse LAP.
320
+ */
321
+ int lapjv_internal(
322
+ const uint_t n, cost_t *cost[],
323
+ int_t *x, int_t *y)
324
+ {
325
+ int ret;
326
+ int_t *free_rows;
327
+ cost_t *v;
328
+
329
+ NEW(free_rows, int_t, n);
330
+ NEW(v, cost_t, n);
331
+ ret = _ccrrt_dense(n, cost, free_rows, x, y, v);
332
+ int i = 0;
333
+ while (ret > 0 && i < 2) {
334
+ ret = _carr_dense(n, cost, ret, free_rows, x, y, v);
335
+ i++;
336
+ }
337
+ if (ret > 0) {
338
+ ret = _ca_dense(n, cost, ret, free_rows, x, y, v);
339
+ }
340
+ FREE(v);
341
+ FREE(free_rows);
342
+ return ret;
343
+ }
deploy/TensorRT/cpp/src/utils.cpp ADDED
@@ -0,0 +1,429 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #include "BYTETracker.h"
2
+ #include "lapjv.h"
3
+
4
+ vector<STrack*> BYTETracker::joint_stracks(vector<STrack*> &tlista, vector<STrack> &tlistb)
5
+ {
6
+ map<int, int> exists;
7
+ vector<STrack*> res;
8
+ for (int i = 0; i < tlista.size(); i++)
9
+ {
10
+ exists.insert(pair<int, int>(tlista[i]->track_id, 1));
11
+ res.push_back(tlista[i]);
12
+ }
13
+ for (int i = 0; i < tlistb.size(); i++)
14
+ {
15
+ int tid = tlistb[i].track_id;
16
+ if (!exists[tid] || exists.count(tid) == 0)
17
+ {
18
+ exists[tid] = 1;
19
+ res.push_back(&tlistb[i]);
20
+ }
21
+ }
22
+ return res;
23
+ }
24
+
25
+ vector<STrack> BYTETracker::joint_stracks(vector<STrack> &tlista, vector<STrack> &tlistb)
26
+ {
27
+ map<int, int> exists;
28
+ vector<STrack> res;
29
+ for (int i = 0; i < tlista.size(); i++)
30
+ {
31
+ exists.insert(pair<int, int>(tlista[i].track_id, 1));
32
+ res.push_back(tlista[i]);
33
+ }
34
+ for (int i = 0; i < tlistb.size(); i++)
35
+ {
36
+ int tid = tlistb[i].track_id;
37
+ if (!exists[tid] || exists.count(tid) == 0)
38
+ {
39
+ exists[tid] = 1;
40
+ res.push_back(tlistb[i]);
41
+ }
42
+ }
43
+ return res;
44
+ }
45
+
46
+ vector<STrack> BYTETracker::sub_stracks(vector<STrack> &tlista, vector<STrack> &tlistb)
47
+ {
48
+ map<int, STrack> stracks;
49
+ for (int i = 0; i < tlista.size(); i++)
50
+ {
51
+ stracks.insert(pair<int, STrack>(tlista[i].track_id, tlista[i]));
52
+ }
53
+ for (int i = 0; i < tlistb.size(); i++)
54
+ {
55
+ int tid = tlistb[i].track_id;
56
+ if (stracks.count(tid) != 0)
57
+ {
58
+ stracks.erase(tid);
59
+ }
60
+ }
61
+
62
+ vector<STrack> res;
63
+ std::map<int, STrack>::iterator it;
64
+ for (it = stracks.begin(); it != stracks.end(); ++it)
65
+ {
66
+ res.push_back(it->second);
67
+ }
68
+
69
+ return res;
70
+ }
71
+
72
+ void BYTETracker::remove_duplicate_stracks(vector<STrack> &resa, vector<STrack> &resb, vector<STrack> &stracksa, vector<STrack> &stracksb)
73
+ {
74
+ vector<vector<float> > pdist = iou_distance(stracksa, stracksb);
75
+ vector<pair<int, int> > pairs;
76
+ for (int i = 0; i < pdist.size(); i++)
77
+ {
78
+ for (int j = 0; j < pdist[i].size(); j++)
79
+ {
80
+ if (pdist[i][j] < 0.15)
81
+ {
82
+ pairs.push_back(pair<int, int>(i, j));
83
+ }
84
+ }
85
+ }
86
+
87
+ vector<int> dupa, dupb;
88
+ for (int i = 0; i < pairs.size(); i++)
89
+ {
90
+ int timep = stracksa[pairs[i].first].frame_id - stracksa[pairs[i].first].start_frame;
91
+ int timeq = stracksb[pairs[i].second].frame_id - stracksb[pairs[i].second].start_frame;
92
+ if (timep > timeq)
93
+ dupb.push_back(pairs[i].second);
94
+ else
95
+ dupa.push_back(pairs[i].first);
96
+ }
97
+
98
+ for (int i = 0; i < stracksa.size(); i++)
99
+ {
100
+ vector<int>::iterator iter = find(dupa.begin(), dupa.end(), i);
101
+ if (iter == dupa.end())
102
+ {
103
+ resa.push_back(stracksa[i]);
104
+ }
105
+ }
106
+
107
+ for (int i = 0; i < stracksb.size(); i++)
108
+ {
109
+ vector<int>::iterator iter = find(dupb.begin(), dupb.end(), i);
110
+ if (iter == dupb.end())
111
+ {
112
+ resb.push_back(stracksb[i]);
113
+ }
114
+ }
115
+ }
116
+
117
+ void BYTETracker::linear_assignment(vector<vector<float> > &cost_matrix, int cost_matrix_size, int cost_matrix_size_size, float thresh,
118
+ vector<vector<int> > &matches, vector<int> &unmatched_a, vector<int> &unmatched_b)
119
+ {
120
+ if (cost_matrix.size() == 0)
121
+ {
122
+ for (int i = 0; i < cost_matrix_size; i++)
123
+ {
124
+ unmatched_a.push_back(i);
125
+ }
126
+ for (int i = 0; i < cost_matrix_size_size; i++)
127
+ {
128
+ unmatched_b.push_back(i);
129
+ }
130
+ return;
131
+ }
132
+
133
+ vector<int> rowsol; vector<int> colsol;
134
+ float c = lapjv(cost_matrix, rowsol, colsol, true, thresh);
135
+ for (int i = 0; i < rowsol.size(); i++)
136
+ {
137
+ if (rowsol[i] >= 0)
138
+ {
139
+ vector<int> match;
140
+ match.push_back(i);
141
+ match.push_back(rowsol[i]);
142
+ matches.push_back(match);
143
+ }
144
+ else
145
+ {
146
+ unmatched_a.push_back(i);
147
+ }
148
+ }
149
+
150
+ for (int i = 0; i < colsol.size(); i++)
151
+ {
152
+ if (colsol[i] < 0)
153
+ {
154
+ unmatched_b.push_back(i);
155
+ }
156
+ }
157
+ }
158
+
159
+ vector<vector<float> > BYTETracker::ious(vector<vector<float> > &atlbrs, vector<vector<float> > &btlbrs)
160
+ {
161
+ vector<vector<float> > ious;
162
+ if (atlbrs.size()*btlbrs.size() == 0)
163
+ return ious;
164
+
165
+ ious.resize(atlbrs.size());
166
+ for (int i = 0; i < ious.size(); i++)
167
+ {
168
+ ious[i].resize(btlbrs.size());
169
+ }
170
+
171
+ //bbox_ious
172
+ for (int k = 0; k < btlbrs.size(); k++)
173
+ {
174
+ vector<float> ious_tmp;
175
+ float box_area = (btlbrs[k][2] - btlbrs[k][0] + 1)*(btlbrs[k][3] - btlbrs[k][1] + 1);
176
+ for (int n = 0; n < atlbrs.size(); n++)
177
+ {
178
+ float iw = min(atlbrs[n][2], btlbrs[k][2]) - max(atlbrs[n][0], btlbrs[k][0]) + 1;
179
+ if (iw > 0)
180
+ {
181
+ float ih = min(atlbrs[n][3], btlbrs[k][3]) - max(atlbrs[n][1], btlbrs[k][1]) + 1;
182
+ if(ih > 0)
183
+ {
184
+ float ua = (atlbrs[n][2] - atlbrs[n][0] + 1)*(atlbrs[n][3] - atlbrs[n][1] + 1) + box_area - iw * ih;
185
+ ious[n][k] = iw * ih / ua;
186
+ }
187
+ else
188
+ {
189
+ ious[n][k] = 0.0;
190
+ }
191
+ }
192
+ else
193
+ {
194
+ ious[n][k] = 0.0;
195
+ }
196
+ }
197
+ }
198
+
199
+ return ious;
200
+ }
201
+
202
+ vector<vector<float> > BYTETracker::iou_distance(vector<STrack*> &atracks, vector<STrack> &btracks, int &dist_size, int &dist_size_size)
203
+ {
204
+ vector<vector<float> > cost_matrix;
205
+ if (atracks.size() * btracks.size() == 0)
206
+ {
207
+ dist_size = atracks.size();
208
+ dist_size_size = btracks.size();
209
+ return cost_matrix;
210
+ }
211
+ vector<vector<float> > atlbrs, btlbrs;
212
+ for (int i = 0; i < atracks.size(); i++)
213
+ {
214
+ atlbrs.push_back(atracks[i]->tlbr);
215
+ }
216
+ for (int i = 0; i < btracks.size(); i++)
217
+ {
218
+ btlbrs.push_back(btracks[i].tlbr);
219
+ }
220
+
221
+ dist_size = atracks.size();
222
+ dist_size_size = btracks.size();
223
+
224
+ vector<vector<float> > _ious = ious(atlbrs, btlbrs);
225
+
226
+ for (int i = 0; i < _ious.size();i++)
227
+ {
228
+ vector<float> _iou;
229
+ for (int j = 0; j < _ious[i].size(); j++)
230
+ {
231
+ _iou.push_back(1 - _ious[i][j]);
232
+ }
233
+ cost_matrix.push_back(_iou);
234
+ }
235
+
236
+ return cost_matrix;
237
+ }
238
+
239
+ vector<vector<float> > BYTETracker::iou_distance(vector<STrack> &atracks, vector<STrack> &btracks)
240
+ {
241
+ vector<vector<float> > atlbrs, btlbrs;
242
+ for (int i = 0; i < atracks.size(); i++)
243
+ {
244
+ atlbrs.push_back(atracks[i].tlbr);
245
+ }
246
+ for (int i = 0; i < btracks.size(); i++)
247
+ {
248
+ btlbrs.push_back(btracks[i].tlbr);
249
+ }
250
+
251
+ vector<vector<float> > _ious = ious(atlbrs, btlbrs);
252
+ vector<vector<float> > cost_matrix;
253
+ for (int i = 0; i < _ious.size(); i++)
254
+ {
255
+ vector<float> _iou;
256
+ for (int j = 0; j < _ious[i].size(); j++)
257
+ {
258
+ _iou.push_back(1 - _ious[i][j]);
259
+ }
260
+ cost_matrix.push_back(_iou);
261
+ }
262
+
263
+ return cost_matrix;
264
+ }
265
+
266
+ double BYTETracker::lapjv(const vector<vector<float> > &cost, vector<int> &rowsol, vector<int> &colsol,
267
+ bool extend_cost, float cost_limit, bool return_cost)
268
+ {
269
+ vector<vector<float> > cost_c;
270
+ cost_c.assign(cost.begin(), cost.end());
271
+
272
+ vector<vector<float> > cost_c_extended;
273
+
274
+ int n_rows = cost.size();
275
+ int n_cols = cost[0].size();
276
+ rowsol.resize(n_rows);
277
+ colsol.resize(n_cols);
278
+
279
+ int n = 0;
280
+ if (n_rows == n_cols)
281
+ {
282
+ n = n_rows;
283
+ }
284
+ else
285
+ {
286
+ if (!extend_cost)
287
+ {
288
+ cout << "set extend_cost=True" << endl;
289
+ system("pause");
290
+ exit(0);
291
+ }
292
+ }
293
+
294
+ if (extend_cost || cost_limit < LONG_MAX)
295
+ {
296
+ n = n_rows + n_cols;
297
+ cost_c_extended.resize(n);
298
+ for (int i = 0; i < cost_c_extended.size(); i++)
299
+ cost_c_extended[i].resize(n);
300
+
301
+ if (cost_limit < LONG_MAX)
302
+ {
303
+ for (int i = 0; i < cost_c_extended.size(); i++)
304
+ {
305
+ for (int j = 0; j < cost_c_extended[i].size(); j++)
306
+ {
307
+ cost_c_extended[i][j] = cost_limit / 2.0;
308
+ }
309
+ }
310
+ }
311
+ else
312
+ {
313
+ float cost_max = -1;
314
+ for (int i = 0; i < cost_c.size(); i++)
315
+ {
316
+ for (int j = 0; j < cost_c[i].size(); j++)
317
+ {
318
+ if (cost_c[i][j] > cost_max)
319
+ cost_max = cost_c[i][j];
320
+ }
321
+ }
322
+ for (int i = 0; i < cost_c_extended.size(); i++)
323
+ {
324
+ for (int j = 0; j < cost_c_extended[i].size(); j++)
325
+ {
326
+ cost_c_extended[i][j] = cost_max + 1;
327
+ }
328
+ }
329
+ }
330
+
331
+ for (int i = n_rows; i < cost_c_extended.size(); i++)
332
+ {
333
+ for (int j = n_cols; j < cost_c_extended[i].size(); j++)
334
+ {
335
+ cost_c_extended[i][j] = 0;
336
+ }
337
+ }
338
+ for (int i = 0; i < n_rows; i++)
339
+ {
340
+ for (int j = 0; j < n_cols; j++)
341
+ {
342
+ cost_c_extended[i][j] = cost_c[i][j];
343
+ }
344
+ }
345
+
346
+ cost_c.clear();
347
+ cost_c.assign(cost_c_extended.begin(), cost_c_extended.end());
348
+ }
349
+
350
+ double **cost_ptr;
351
+ cost_ptr = new double *[sizeof(double *) * n];
352
+ for (int i = 0; i < n; i++)
353
+ cost_ptr[i] = new double[sizeof(double) * n];
354
+
355
+ for (int i = 0; i < n; i++)
356
+ {
357
+ for (int j = 0; j < n; j++)
358
+ {
359
+ cost_ptr[i][j] = cost_c[i][j];
360
+ }
361
+ }
362
+
363
+ int* x_c = new int[sizeof(int) * n];
364
+ int *y_c = new int[sizeof(int) * n];
365
+
366
+ int ret = lapjv_internal(n, cost_ptr, x_c, y_c);
367
+ if (ret != 0)
368
+ {
369
+ cout << "Calculate Wrong!" << endl;
370
+ system("pause");
371
+ exit(0);
372
+ }
373
+
374
+ double opt = 0.0;
375
+
376
+ if (n != n_rows)
377
+ {
378
+ for (int i = 0; i < n; i++)
379
+ {
380
+ if (x_c[i] >= n_cols)
381
+ x_c[i] = -1;
382
+ if (y_c[i] >= n_rows)
383
+ y_c[i] = -1;
384
+ }
385
+ for (int i = 0; i < n_rows; i++)
386
+ {
387
+ rowsol[i] = x_c[i];
388
+ }
389
+ for (int i = 0; i < n_cols; i++)
390
+ {
391
+ colsol[i] = y_c[i];
392
+ }
393
+
394
+ if (return_cost)
395
+ {
396
+ for (int i = 0; i < rowsol.size(); i++)
397
+ {
398
+ if (rowsol[i] != -1)
399
+ {
400
+ //cout << i << "\t" << rowsol[i] << "\t" << cost_ptr[i][rowsol[i]] << endl;
401
+ opt += cost_ptr[i][rowsol[i]];
402
+ }
403
+ }
404
+ }
405
+ }
406
+ else if (return_cost)
407
+ {
408
+ for (int i = 0; i < rowsol.size(); i++)
409
+ {
410
+ opt += cost_ptr[i][rowsol[i]];
411
+ }
412
+ }
413
+
414
+ for (int i = 0; i < n; i++)
415
+ {
416
+ delete[]cost_ptr[i];
417
+ }
418
+ delete[]cost_ptr;
419
+ delete[]x_c;
420
+ delete[]y_c;
421
+
422
+ return opt;
423
+ }
424
+
425
+ Scalar BYTETracker::get_color(int idx)
426
+ {
427
+ idx += 3;
428
+ return Scalar(37 * idx % 255, 17 * idx % 255, 29 * idx % 255);
429
+ }
deploy/TensorRT/python/README.md ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # ByteTrack-TensorRT in Python
2
+
3
+ ## Install TensorRT Toolkit
4
+ Please follow the [TensorRT Installation Guide](https://docs.nvidia.com/deeplearning/tensorrt/install-guide/index.html) and [torch2trt gitrepo](https://github.com/NVIDIA-AI-IOT/torch2trt) to install TensorRT (Version 7 recommended) and torch2trt.
5
+
6
+ ## Convert model
7
+
8
+ You can convert the Pytorch model “bytetrack_s_mot17” to TensorRT model by running:
9
+
10
+ ```shell
11
+ cd <ByteTrack_HOME>
12
+ python3 tools/trt.py -f exps/example/mot/yolox_s_mix_det.py -c pretrained/bytetrack_s_mot17.pth.tar
13
+ ```
14
+
15
+ ## Run TensorRT demo
16
+
17
+ You can use the converted model_trt.pth to run TensorRT demo with **130 FPS**:
18
+
19
+ ```shell
20
+ cd <ByteTrack_HOME>
21
+ python3 tools/demo_track.py video -f exps/example/mot/yolox_s_mix_det.py --trt --save_result
22
+ ```
deploy/ncnn/cpp/CMakeLists.txt ADDED
@@ -0,0 +1,84 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ macro(ncnn_add_example name)
2
+ add_executable(${name} ${name}.cpp)
3
+ if(OpenCV_FOUND)
4
+ target_include_directories(${name} PRIVATE ${OpenCV_INCLUDE_DIRS})
5
+ target_link_libraries(${name} PRIVATE ncnn ${OpenCV_LIBS})
6
+ elseif(NCNN_SIMPLEOCV)
7
+ target_compile_definitions(${name} PUBLIC USE_NCNN_SIMPLEOCV)
8
+ target_link_libraries(${name} PRIVATE ncnn)
9
+ endif()
10
+
11
+ # add test to a virtual project group
12
+ set_property(TARGET ${name} PROPERTY FOLDER "examples")
13
+ endmacro()
14
+
15
+ if(NCNN_PIXEL)
16
+ find_package(OpenCV QUIET COMPONENTS opencv_world)
17
+ # for opencv 2.4 on ubuntu 16.04, there is no opencv_world but OpenCV_FOUND will be TRUE
18
+ if("${OpenCV_LIBS}" STREQUAL "")
19
+ set(OpenCV_FOUND FALSE)
20
+ endif()
21
+ if(NOT OpenCV_FOUND)
22
+ find_package(OpenCV QUIET COMPONENTS core highgui imgproc imgcodecs videoio)
23
+ endif()
24
+ if(NOT OpenCV_FOUND)
25
+ find_package(OpenCV QUIET COMPONENTS core highgui imgproc)
26
+ endif()
27
+
28
+ if(OpenCV_FOUND OR NCNN_SIMPLEOCV)
29
+ if(OpenCV_FOUND)
30
+ message(STATUS "OpenCV library: ${OpenCV_INSTALL_PATH}")
31
+ message(STATUS " version: ${OpenCV_VERSION}")
32
+ message(STATUS " libraries: ${OpenCV_LIBS}")
33
+ message(STATUS " include path: ${OpenCV_INCLUDE_DIRS}")
34
+
35
+ if(${OpenCV_VERSION_MAJOR} GREATER 3)
36
+ set(CMAKE_CXX_STANDARD 11)
37
+ endif()
38
+ endif()
39
+
40
+ include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../src)
41
+ include_directories(${CMAKE_CURRENT_BINARY_DIR}/../src)
42
+ include_directories(include)
43
+ include_directories(/usr/local/include/eigen3)
44
+
45
+ ncnn_add_example(squeezenet)
46
+ ncnn_add_example(squeezenet_c_api)
47
+ ncnn_add_example(fasterrcnn)
48
+ ncnn_add_example(rfcn)
49
+ ncnn_add_example(yolov2)
50
+ ncnn_add_example(yolov3)
51
+ if(OpenCV_FOUND)
52
+ ncnn_add_example(yolov4)
53
+ endif()
54
+ ncnn_add_example(yolov5)
55
+ ncnn_add_example(yolox)
56
+ ncnn_add_example(mobilenetv2ssdlite)
57
+ ncnn_add_example(mobilenetssd)
58
+ ncnn_add_example(squeezenetssd)
59
+ ncnn_add_example(shufflenetv2)
60
+ ncnn_add_example(peleenetssd_seg)
61
+ ncnn_add_example(simplepose)
62
+ ncnn_add_example(retinaface)
63
+ ncnn_add_example(yolact)
64
+ ncnn_add_example(nanodet)
65
+ ncnn_add_example(scrfd)
66
+ ncnn_add_example(scrfd_crowdhuman)
67
+ ncnn_add_example(rvm)
68
+ file(GLOB My_Source_Files src/*.cpp)
69
+ add_executable(bytetrack ${My_Source_Files})
70
+ if(OpenCV_FOUND)
71
+ target_include_directories(bytetrack PRIVATE ${OpenCV_INCLUDE_DIRS})
72
+ target_link_libraries(bytetrack PRIVATE ncnn ${OpenCV_LIBS})
73
+ elseif(NCNN_SIMPLEOCV)
74
+ target_compile_definitions(bytetrack PUBLIC USE_NCNN_SIMPLEOCV)
75
+ target_link_libraries(bytetrack PRIVATE ncnn)
76
+ endif()
77
+ # add test to a virtual project group
78
+ set_property(TARGET bytetrack PROPERTY FOLDER "examples")
79
+ else()
80
+ message(WARNING "OpenCV not found and NCNN_SIMPLEOCV disabled, examples won't be built")
81
+ endif()
82
+ else()
83
+ message(WARNING "NCNN_PIXEL not enabled, examples won't be built")
84
+ endif()
deploy/ncnn/cpp/README.md ADDED
@@ -0,0 +1,103 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # ByteTrack-CPP-ncnn
2
+
3
+ ## Installation
4
+
5
+ Clone [ncnn](https://github.com/Tencent/ncnn) first, then please following [build tutorial of ncnn](https://github.com/Tencent/ncnn/wiki/how-to-build) to build on your own device.
6
+
7
+ Install eigen-3.3.9 [[google]](https://drive.google.com/file/d/1rqO74CYCNrmRAg8Rra0JP3yZtJ-rfket/view?usp=sharing), [[baidu(code:ueq4)]](https://pan.baidu.com/s/15kEfCxpy-T7tz60msxxExg).
8
+
9
+ ```shell
10
+ unzip eigen-3.3.9.zip
11
+ cd eigen-3.3.9
12
+ mkdir build
13
+ cd build
14
+ cmake ..
15
+ sudo make install
16
+ ```
17
+
18
+ ## Generate onnx file
19
+ Use provided tools to generate onnx file.
20
+ For example, if you want to generate onnx file of bytetrack_s_mot17.pth, please run the following command:
21
+ ```shell
22
+ cd <ByteTrack_HOME>
23
+ python3 tools/export_onnx.py -f exps/example/mot/yolox_s_mix_det.py -c pretrained/bytetrack_s_mot17.pth.tar
24
+ ```
25
+ Then, a bytetrack_s.onnx file is generated under <ByteTrack_HOME>.
26
+
27
+ ## Generate ncnn param and bin file
28
+ Put bytetrack_s.onnx under ncnn/build/tools/onnx and then run:
29
+
30
+ ```shell
31
+ cd ncnn/build/tools/onnx
32
+ ./onnx2ncnn bytetrack_s.onnx bytetrack_s.param bytetrack_s.bin
33
+ ```
34
+
35
+ Since Focus module is not supported in ncnn. Warnings like:
36
+ ```shell
37
+ Unsupported slice step !
38
+ ```
39
+ will be printed. However, don't worry! C++ version of Focus layer is already implemented in src/bytetrack.cpp.
40
+
41
+ ## Modify param file
42
+ Open **bytetrack_s.param**, and modify it.
43
+ Before (just an example):
44
+ ```
45
+ 235 268
46
+ Input images 0 1 images
47
+ Split splitncnn_input0 1 4 images images_splitncnn_0 images_splitncnn_1 images_splitncnn_2 images_splitncnn_3
48
+ Crop Slice_4 1 1 images_splitncnn_3 467 -23309=1,0 -23310=1,2147483647 -23311=1,1
49
+ Crop Slice_9 1 1 467 472 -23309=1,0 -23310=1,2147483647 -23311=1,2
50
+ Crop Slice_14 1 1 images_splitncnn_2 477 -23309=1,0 -23310=1,2147483647 -23311=1,1
51
+ Crop Slice_19 1 1 477 482 -23309=1,1 -23310=1,2147483647 -23311=1,2
52
+ Crop Slice_24 1 1 images_splitncnn_1 487 -23309=1,1 -23310=1,2147483647 -23311=1,1
53
+ Crop Slice_29 1 1 487 492 -23309=1,0 -23310=1,2147483647 -23311=1,2
54
+ Crop Slice_34 1 1 images_splitncnn_0 497 -23309=1,1 -23310=1,2147483647 -23311=1,1
55
+ Crop Slice_39 1 1 497 502 -23309=1,1 -23310=1,2147483647 -23311=1,2
56
+ Concat Concat_40 4 1 472 492 482 502 503 0=0
57
+ ...
58
+ ```
59
+ * Change first number for 235 to 235 - 9 = 226(since we will remove 10 layers and add 1 layers, total layers number should minus 9).
60
+ * Then remove 10 lines of code from Split to Concat, but remember the last but 2nd number: 503.
61
+ * Add YoloV5Focus layer After Input (using previous number 503):
62
+ ```
63
+ YoloV5Focus focus 1 1 images 503
64
+ ```
65
+ After(just an exmaple):
66
+ ```
67
+ 226 328
68
+ Input images 0 1 images
69
+ YoloV5Focus focus 1 1 images 503
70
+ ...
71
+ ```
72
+
73
+ ## Use ncnn_optimize to generate new param and bin
74
+ ```shell
75
+ # suppose you are still under ncnn/build/tools/onnx dir.
76
+ ../ncnnoptimize bytetrack_s.param bytetrack_s.bin bytetrack_s_op.param bytetrack_s_op.bin 65536
77
+ ```
78
+
79
+ ## Copy files and build ByteTrack
80
+ Copy or move 'src', 'include' folders and 'CMakeLists.txt' file into ncnn/examples. Copy bytetrack_s_op.param, bytetrack_s_op.bin and <ByteTrack_HOME>/videos/palace.mp4 into ncnn/build/examples. Then, build ByteTrack:
81
+
82
+ ```shell
83
+ cd ncnn/build/examples
84
+ cmake ..
85
+ make
86
+ ```
87
+
88
+ ## Run the demo
89
+ You can run the ncnn demo with **5 FPS** (96-core Intel(R) Xeon(R) Platinum 8163 CPU @ 2.50GHz):
90
+ ```shell
91
+ ./bytetrack palace.mp4
92
+ ```
93
+
94
+ You can modify 'num_threads' to optimize the running speed in [bytetrack.cpp](https://github.com/ifzhang/ByteTrack/blob/2e9a67895da6b47b948015f6861bba0bacd4e72f/deploy/ncnn/cpp/src/bytetrack.cpp#L309) according to the number of your CPU cores:
95
+
96
+ ```
97
+ yolox.opt.num_threads = 20;
98
+ ```
99
+
100
+
101
+ ## Acknowledgement
102
+
103
+ * [ncnn](https://github.com/Tencent/ncnn)
deploy/ncnn/cpp/include/BYTETracker.h ADDED
@@ -0,0 +1,49 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #pragma once
2
+
3
+ #include "STrack.h"
4
+
5
+ struct Object
6
+ {
7
+ cv::Rect_<float> rect;
8
+ int label;
9
+ float prob;
10
+ };
11
+
12
+ class BYTETracker
13
+ {
14
+ public:
15
+ BYTETracker(int frame_rate = 30, int track_buffer = 30);
16
+ ~BYTETracker();
17
+
18
+ vector<STrack> update(const vector<Object>& objects);
19
+ Scalar get_color(int idx);
20
+
21
+ private:
22
+ vector<STrack*> joint_stracks(vector<STrack*> &tlista, vector<STrack> &tlistb);
23
+ vector<STrack> joint_stracks(vector<STrack> &tlista, vector<STrack> &tlistb);
24
+
25
+ vector<STrack> sub_stracks(vector<STrack> &tlista, vector<STrack> &tlistb);
26
+ void remove_duplicate_stracks(vector<STrack> &resa, vector<STrack> &resb, vector<STrack> &stracksa, vector<STrack> &stracksb);
27
+
28
+ void linear_assignment(vector<vector<float> > &cost_matrix, int cost_matrix_size, int cost_matrix_size_size, float thresh,
29
+ vector<vector<int> > &matches, vector<int> &unmatched_a, vector<int> &unmatched_b);
30
+ vector<vector<float> > iou_distance(vector<STrack*> &atracks, vector<STrack> &btracks, int &dist_size, int &dist_size_size);
31
+ vector<vector<float> > iou_distance(vector<STrack> &atracks, vector<STrack> &btracks);
32
+ vector<vector<float> > ious(vector<vector<float> > &atlbrs, vector<vector<float> > &btlbrs);
33
+
34
+ double lapjv(const vector<vector<float> > &cost, vector<int> &rowsol, vector<int> &colsol,
35
+ bool extend_cost = false, float cost_limit = LONG_MAX, bool return_cost = true);
36
+
37
+ private:
38
+
39
+ float track_thresh;
40
+ float high_thresh;
41
+ float match_thresh;
42
+ int frame_id;
43
+ int max_time_lost;
44
+
45
+ vector<STrack> tracked_stracks;
46
+ vector<STrack> lost_stracks;
47
+ vector<STrack> removed_stracks;
48
+ byte_kalman::KalmanFilter kalman_filter;
49
+ };
deploy/ncnn/cpp/include/STrack.h ADDED
@@ -0,0 +1,50 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #pragma once
2
+
3
+ #include <opencv2/opencv.hpp>
4
+ #include "kalmanFilter.h"
5
+
6
+ using namespace cv;
7
+ using namespace std;
8
+
9
+ enum TrackState { New = 0, Tracked, Lost, Removed };
10
+
11
+ class STrack
12
+ {
13
+ public:
14
+ STrack(vector<float> tlwh_, float score);
15
+ ~STrack();
16
+
17
+ vector<float> static tlbr_to_tlwh(vector<float> &tlbr);
18
+ void static multi_predict(vector<STrack*> &stracks, byte_kalman::KalmanFilter &kalman_filter);
19
+ void static_tlwh();
20
+ void static_tlbr();
21
+ vector<float> tlwh_to_xyah(vector<float> tlwh_tmp);
22
+ vector<float> to_xyah();
23
+ void mark_lost();
24
+ void mark_removed();
25
+ int next_id();
26
+ int end_frame();
27
+
28
+ void activate(byte_kalman::KalmanFilter &kalman_filter, int frame_id);
29
+ void re_activate(STrack &new_track, int frame_id, bool new_id = false);
30
+ void update(STrack &new_track, int frame_id);
31
+
32
+ public:
33
+ bool is_activated;
34
+ int track_id;
35
+ int state;
36
+
37
+ vector<float> _tlwh;
38
+ vector<float> tlwh;
39
+ vector<float> tlbr;
40
+ int frame_id;
41
+ int tracklet_len;
42
+ int start_frame;
43
+
44
+ KAL_MEAN mean;
45
+ KAL_COVA covariance;
46
+ float score;
47
+
48
+ private:
49
+ byte_kalman::KalmanFilter kalman_filter;
50
+ };
deploy/ncnn/cpp/include/dataType.h ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #pragma once
2
+
3
+ #include <cstddef>
4
+ #include <vector>
5
+
6
+ #include <Eigen/Core>
7
+ #include <Eigen/Dense>
8
+ typedef Eigen::Matrix<float, 1, 4, Eigen::RowMajor> DETECTBOX;
9
+ typedef Eigen::Matrix<float, -1, 4, Eigen::RowMajor> DETECTBOXSS;
10
+ typedef Eigen::Matrix<float, 1, 128, Eigen::RowMajor> FEATURE;
11
+ typedef Eigen::Matrix<float, Eigen::Dynamic, 128, Eigen::RowMajor> FEATURESS;
12
+ //typedef std::vector<FEATURE> FEATURESS;
13
+
14
+ //Kalmanfilter
15
+ //typedef Eigen::Matrix<float, 8, 8, Eigen::RowMajor> KAL_FILTER;
16
+ typedef Eigen::Matrix<float, 1, 8, Eigen::RowMajor> KAL_MEAN;
17
+ typedef Eigen::Matrix<float, 8, 8, Eigen::RowMajor> KAL_COVA;
18
+ typedef Eigen::Matrix<float, 1, 4, Eigen::RowMajor> KAL_HMEAN;
19
+ typedef Eigen::Matrix<float, 4, 4, Eigen::RowMajor> KAL_HCOVA;
20
+ using KAL_DATA = std::pair<KAL_MEAN, KAL_COVA>;
21
+ using KAL_HDATA = std::pair<KAL_HMEAN, KAL_HCOVA>;
22
+
23
+ //main
24
+ using RESULT_DATA = std::pair<int, DETECTBOX>;
25
+
26
+ //tracker:
27
+ using TRACKER_DATA = std::pair<int, FEATURESS>;
28
+ using MATCH_DATA = std::pair<int, int>;
29
+ typedef struct t {
30
+ std::vector<MATCH_DATA> matches;
31
+ std::vector<int> unmatched_tracks;
32
+ std::vector<int> unmatched_detections;
33
+ }TRACHER_MATCHD;
34
+
35
+ //linear_assignment:
36
+ typedef Eigen::Matrix<float, -1, -1, Eigen::RowMajor> DYNAMICM;
deploy/ncnn/cpp/include/kalmanFilter.h ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #pragma once
2
+
3
+ #include "dataType.h"
4
+
5
+ namespace byte_kalman
6
+ {
7
+ class KalmanFilter
8
+ {
9
+ public:
10
+ static const double chi2inv95[10];
11
+ KalmanFilter();
12
+ KAL_DATA initiate(const DETECTBOX& measurement);
13
+ void predict(KAL_MEAN& mean, KAL_COVA& covariance);
14
+ KAL_HDATA project(const KAL_MEAN& mean, const KAL_COVA& covariance);
15
+ KAL_DATA update(const KAL_MEAN& mean,
16
+ const KAL_COVA& covariance,
17
+ const DETECTBOX& measurement);
18
+
19
+ Eigen::Matrix<float, 1, -1> gating_distance(
20
+ const KAL_MEAN& mean,
21
+ const KAL_COVA& covariance,
22
+ const std::vector<DETECTBOX>& measurements,
23
+ bool only_position = false);
24
+
25
+ private:
26
+ Eigen::Matrix<float, 8, 8, Eigen::RowMajor> _motion_mat;
27
+ Eigen::Matrix<float, 4, 8, Eigen::RowMajor> _update_mat;
28
+ float _std_weight_position;
29
+ float _std_weight_velocity;
30
+ };
31
+ }
deploy/ncnn/cpp/include/lapjv.h ADDED
@@ -0,0 +1,63 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #ifndef LAPJV_H
2
+ #define LAPJV_H
3
+
4
+ #define LARGE 1000000
5
+
6
+ #if !defined TRUE
7
+ #define TRUE 1
8
+ #endif
9
+ #if !defined FALSE
10
+ #define FALSE 0
11
+ #endif
12
+
13
+ #define NEW(x, t, n) if ((x = (t *)malloc(sizeof(t) * (n))) == 0) { return -1; }
14
+ #define FREE(x) if (x != 0) { free(x); x = 0; }
15
+ #define SWAP_INDICES(a, b) { int_t _temp_index = a; a = b; b = _temp_index; }
16
+
17
+ #if 0
18
+ #include <assert.h>
19
+ #define ASSERT(cond) assert(cond)
20
+ #define PRINTF(fmt, ...) printf(fmt, ##__VA_ARGS__)
21
+ #define PRINT_COST_ARRAY(a, n) \
22
+ while (1) { \
23
+ printf(#a" = ["); \
24
+ if ((n) > 0) { \
25
+ printf("%f", (a)[0]); \
26
+ for (uint_t j = 1; j < n; j++) { \
27
+ printf(", %f", (a)[j]); \
28
+ } \
29
+ } \
30
+ printf("]\n"); \
31
+ break; \
32
+ }
33
+ #define PRINT_INDEX_ARRAY(a, n) \
34
+ while (1) { \
35
+ printf(#a" = ["); \
36
+ if ((n) > 0) { \
37
+ printf("%d", (a)[0]); \
38
+ for (uint_t j = 1; j < n; j++) { \
39
+ printf(", %d", (a)[j]); \
40
+ } \
41
+ } \
42
+ printf("]\n"); \
43
+ break; \
44
+ }
45
+ #else
46
+ #define ASSERT(cond)
47
+ #define PRINTF(fmt, ...)
48
+ #define PRINT_COST_ARRAY(a, n)
49
+ #define PRINT_INDEX_ARRAY(a, n)
50
+ #endif
51
+
52
+
53
+ typedef signed int int_t;
54
+ typedef unsigned int uint_t;
55
+ typedef double cost_t;
56
+ typedef char boolean;
57
+ typedef enum fp_t { FP_1 = 1, FP_2 = 2, FP_DYNAMIC = 3 } fp_t;
58
+
59
+ extern int_t lapjv_internal(
60
+ const uint_t n, cost_t *cost[],
61
+ int_t *x, int_t *y);
62
+
63
+ #endif // LAPJV_H
deploy/ncnn/cpp/src/BYTETracker.cpp ADDED
@@ -0,0 +1,241 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #include "BYTETracker.h"
2
+ #include <fstream>
3
+
4
+ BYTETracker::BYTETracker(int frame_rate, int track_buffer)
5
+ {
6
+ track_thresh = 0.5;
7
+ high_thresh = 0.6;
8
+ match_thresh = 0.8;
9
+
10
+ frame_id = 0;
11
+ max_time_lost = int(frame_rate / 30.0 * track_buffer);
12
+ cout << "Init ByteTrack!" << endl;
13
+ }
14
+
15
+ BYTETracker::~BYTETracker()
16
+ {
17
+ }
18
+
19
+ vector<STrack> BYTETracker::update(const vector<Object>& objects)
20
+ {
21
+
22
+ ////////////////// Step 1: Get detections //////////////////
23
+ this->frame_id++;
24
+ vector<STrack> activated_stracks;
25
+ vector<STrack> refind_stracks;
26
+ vector<STrack> removed_stracks;
27
+ vector<STrack> lost_stracks;
28
+ vector<STrack> detections;
29
+ vector<STrack> detections_low;
30
+
31
+ vector<STrack> detections_cp;
32
+ vector<STrack> tracked_stracks_swap;
33
+ vector<STrack> resa, resb;
34
+ vector<STrack> output_stracks;
35
+
36
+ vector<STrack*> unconfirmed;
37
+ vector<STrack*> tracked_stracks;
38
+ vector<STrack*> strack_pool;
39
+ vector<STrack*> r_tracked_stracks;
40
+
41
+ if (objects.size() > 0)
42
+ {
43
+ for (int i = 0; i < objects.size(); i++)
44
+ {
45
+ vector<float> tlbr_;
46
+ tlbr_.resize(4);
47
+ tlbr_[0] = objects[i].rect.x;
48
+ tlbr_[1] = objects[i].rect.y;
49
+ tlbr_[2] = objects[i].rect.x + objects[i].rect.width;
50
+ tlbr_[3] = objects[i].rect.y + objects[i].rect.height;
51
+
52
+ float score = objects[i].prob;
53
+
54
+ STrack strack(STrack::tlbr_to_tlwh(tlbr_), score);
55
+ if (score >= track_thresh)
56
+ {
57
+ detections.push_back(strack);
58
+ }
59
+ else
60
+ {
61
+ detections_low.push_back(strack);
62
+ }
63
+
64
+ }
65
+ }
66
+
67
+ // Add newly detected tracklets to tracked_stracks
68
+ for (int i = 0; i < this->tracked_stracks.size(); i++)
69
+ {
70
+ if (!this->tracked_stracks[i].is_activated)
71
+ unconfirmed.push_back(&this->tracked_stracks[i]);
72
+ else
73
+ tracked_stracks.push_back(&this->tracked_stracks[i]);
74
+ }
75
+
76
+ ////////////////// Step 2: First association, with IoU //////////////////
77
+ strack_pool = joint_stracks(tracked_stracks, this->lost_stracks);
78
+ STrack::multi_predict(strack_pool, this->kalman_filter);
79
+
80
+ vector<vector<float> > dists;
81
+ int dist_size = 0, dist_size_size = 0;
82
+ dists = iou_distance(strack_pool, detections, dist_size, dist_size_size);
83
+
84
+ vector<vector<int> > matches;
85
+ vector<int> u_track, u_detection;
86
+ linear_assignment(dists, dist_size, dist_size_size, match_thresh, matches, u_track, u_detection);
87
+
88
+ for (int i = 0; i < matches.size(); i++)
89
+ {
90
+ STrack *track = strack_pool[matches[i][0]];
91
+ STrack *det = &detections[matches[i][1]];
92
+ if (track->state == TrackState::Tracked)
93
+ {
94
+ track->update(*det, this->frame_id);
95
+ activated_stracks.push_back(*track);
96
+ }
97
+ else
98
+ {
99
+ track->re_activate(*det, this->frame_id, false);
100
+ refind_stracks.push_back(*track);
101
+ }
102
+ }
103
+
104
+ ////////////////// Step 3: Second association, using low score dets //////////////////
105
+ for (int i = 0; i < u_detection.size(); i++)
106
+ {
107
+ detections_cp.push_back(detections[u_detection[i]]);
108
+ }
109
+ detections.clear();
110
+ detections.assign(detections_low.begin(), detections_low.end());
111
+
112
+ for (int i = 0; i < u_track.size(); i++)
113
+ {
114
+ if (strack_pool[u_track[i]]->state == TrackState::Tracked)
115
+ {
116
+ r_tracked_stracks.push_back(strack_pool[u_track[i]]);
117
+ }
118
+ }
119
+
120
+ dists.clear();
121
+ dists = iou_distance(r_tracked_stracks, detections, dist_size, dist_size_size);
122
+
123
+ matches.clear();
124
+ u_track.clear();
125
+ u_detection.clear();
126
+ linear_assignment(dists, dist_size, dist_size_size, 0.5, matches, u_track, u_detection);
127
+
128
+ for (int i = 0; i < matches.size(); i++)
129
+ {
130
+ STrack *track = r_tracked_stracks[matches[i][0]];
131
+ STrack *det = &detections[matches[i][1]];
132
+ if (track->state == TrackState::Tracked)
133
+ {
134
+ track->update(*det, this->frame_id);
135
+ activated_stracks.push_back(*track);
136
+ }
137
+ else
138
+ {
139
+ track->re_activate(*det, this->frame_id, false);
140
+ refind_stracks.push_back(*track);
141
+ }
142
+ }
143
+
144
+ for (int i = 0; i < u_track.size(); i++)
145
+ {
146
+ STrack *track = r_tracked_stracks[u_track[i]];
147
+ if (track->state != TrackState::Lost)
148
+ {
149
+ track->mark_lost();
150
+ lost_stracks.push_back(*track);
151
+ }
152
+ }
153
+
154
+ // Deal with unconfirmed tracks, usually tracks with only one beginning frame
155
+ detections.clear();
156
+ detections.assign(detections_cp.begin(), detections_cp.end());
157
+
158
+ dists.clear();
159
+ dists = iou_distance(unconfirmed, detections, dist_size, dist_size_size);
160
+
161
+ matches.clear();
162
+ vector<int> u_unconfirmed;
163
+ u_detection.clear();
164
+ linear_assignment(dists, dist_size, dist_size_size, 0.7, matches, u_unconfirmed, u_detection);
165
+
166
+ for (int i = 0; i < matches.size(); i++)
167
+ {
168
+ unconfirmed[matches[i][0]]->update(detections[matches[i][1]], this->frame_id);
169
+ activated_stracks.push_back(*unconfirmed[matches[i][0]]);
170
+ }
171
+
172
+ for (int i = 0; i < u_unconfirmed.size(); i++)
173
+ {
174
+ STrack *track = unconfirmed[u_unconfirmed[i]];
175
+ track->mark_removed();
176
+ removed_stracks.push_back(*track);
177
+ }
178
+
179
+ ////////////////// Step 4: Init new stracks //////////////////
180
+ for (int i = 0; i < u_detection.size(); i++)
181
+ {
182
+ STrack *track = &detections[u_detection[i]];
183
+ if (track->score < this->high_thresh)
184
+ continue;
185
+ track->activate(this->kalman_filter, this->frame_id);
186
+ activated_stracks.push_back(*track);
187
+ }
188
+
189
+ ////////////////// Step 5: Update state //////////////////
190
+ for (int i = 0; i < this->lost_stracks.size(); i++)
191
+ {
192
+ if (this->frame_id - this->lost_stracks[i].end_frame() > this->max_time_lost)
193
+ {
194
+ this->lost_stracks[i].mark_removed();
195
+ removed_stracks.push_back(this->lost_stracks[i]);
196
+ }
197
+ }
198
+
199
+ for (int i = 0; i < this->tracked_stracks.size(); i++)
200
+ {
201
+ if (this->tracked_stracks[i].state == TrackState::Tracked)
202
+ {
203
+ tracked_stracks_swap.push_back(this->tracked_stracks[i]);
204
+ }
205
+ }
206
+ this->tracked_stracks.clear();
207
+ this->tracked_stracks.assign(tracked_stracks_swap.begin(), tracked_stracks_swap.end());
208
+
209
+ this->tracked_stracks = joint_stracks(this->tracked_stracks, activated_stracks);
210
+ this->tracked_stracks = joint_stracks(this->tracked_stracks, refind_stracks);
211
+
212
+ //std::cout << activated_stracks.size() << std::endl;
213
+
214
+ this->lost_stracks = sub_stracks(this->lost_stracks, this->tracked_stracks);
215
+ for (int i = 0; i < lost_stracks.size(); i++)
216
+ {
217
+ this->lost_stracks.push_back(lost_stracks[i]);
218
+ }
219
+
220
+ this->lost_stracks = sub_stracks(this->lost_stracks, this->removed_stracks);
221
+ for (int i = 0; i < removed_stracks.size(); i++)
222
+ {
223
+ this->removed_stracks.push_back(removed_stracks[i]);
224
+ }
225
+
226
+ remove_duplicate_stracks(resa, resb, this->tracked_stracks, this->lost_stracks);
227
+
228
+ this->tracked_stracks.clear();
229
+ this->tracked_stracks.assign(resa.begin(), resa.end());
230
+ this->lost_stracks.clear();
231
+ this->lost_stracks.assign(resb.begin(), resb.end());
232
+
233
+ for (int i = 0; i < this->tracked_stracks.size(); i++)
234
+ {
235
+ if (this->tracked_stracks[i].is_activated)
236
+ {
237
+ output_stracks.push_back(this->tracked_stracks[i]);
238
+ }
239
+ }
240
+ return output_stracks;
241
+ }
deploy/ncnn/cpp/src/STrack.cpp ADDED
@@ -0,0 +1,192 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #include "STrack.h"
2
+
3
+ STrack::STrack(vector<float> tlwh_, float score)
4
+ {
5
+ _tlwh.resize(4);
6
+ _tlwh.assign(tlwh_.begin(), tlwh_.end());
7
+
8
+ is_activated = false;
9
+ track_id = 0;
10
+ state = TrackState::New;
11
+
12
+ tlwh.resize(4);
13
+ tlbr.resize(4);
14
+
15
+ static_tlwh();
16
+ static_tlbr();
17
+ frame_id = 0;
18
+ tracklet_len = 0;
19
+ this->score = score;
20
+ start_frame = 0;
21
+ }
22
+
23
+ STrack::~STrack()
24
+ {
25
+ }
26
+
27
+ void STrack::activate(byte_kalman::KalmanFilter &kalman_filter, int frame_id)
28
+ {
29
+ this->kalman_filter = kalman_filter;
30
+ this->track_id = this->next_id();
31
+
32
+ vector<float> _tlwh_tmp(4);
33
+ _tlwh_tmp[0] = this->_tlwh[0];
34
+ _tlwh_tmp[1] = this->_tlwh[1];
35
+ _tlwh_tmp[2] = this->_tlwh[2];
36
+ _tlwh_tmp[3] = this->_tlwh[3];
37
+ vector<float> xyah = tlwh_to_xyah(_tlwh_tmp);
38
+ DETECTBOX xyah_box;
39
+ xyah_box[0] = xyah[0];
40
+ xyah_box[1] = xyah[1];
41
+ xyah_box[2] = xyah[2];
42
+ xyah_box[3] = xyah[3];
43
+ auto mc = this->kalman_filter.initiate(xyah_box);
44
+ this->mean = mc.first;
45
+ this->covariance = mc.second;
46
+
47
+ static_tlwh();
48
+ static_tlbr();
49
+
50
+ this->tracklet_len = 0;
51
+ this->state = TrackState::Tracked;
52
+ if (frame_id == 1)
53
+ {
54
+ this->is_activated = true;
55
+ }
56
+ //this->is_activated = true;
57
+ this->frame_id = frame_id;
58
+ this->start_frame = frame_id;
59
+ }
60
+
61
+ void STrack::re_activate(STrack &new_track, int frame_id, bool new_id)
62
+ {
63
+ vector<float> xyah = tlwh_to_xyah(new_track.tlwh);
64
+ DETECTBOX xyah_box;
65
+ xyah_box[0] = xyah[0];
66
+ xyah_box[1] = xyah[1];
67
+ xyah_box[2] = xyah[2];
68
+ xyah_box[3] = xyah[3];
69
+ auto mc = this->kalman_filter.update(this->mean, this->covariance, xyah_box);
70
+ this->mean = mc.first;
71
+ this->covariance = mc.second;
72
+
73
+ static_tlwh();
74
+ static_tlbr();
75
+
76
+ this->tracklet_len = 0;
77
+ this->state = TrackState::Tracked;
78
+ this->is_activated = true;
79
+ this->frame_id = frame_id;
80
+ this->score = new_track.score;
81
+ if (new_id)
82
+ this->track_id = next_id();
83
+ }
84
+
85
+ void STrack::update(STrack &new_track, int frame_id)
86
+ {
87
+ this->frame_id = frame_id;
88
+ this->tracklet_len++;
89
+
90
+ vector<float> xyah = tlwh_to_xyah(new_track.tlwh);
91
+ DETECTBOX xyah_box;
92
+ xyah_box[0] = xyah[0];
93
+ xyah_box[1] = xyah[1];
94
+ xyah_box[2] = xyah[2];
95
+ xyah_box[3] = xyah[3];
96
+
97
+ auto mc = this->kalman_filter.update(this->mean, this->covariance, xyah_box);
98
+ this->mean = mc.first;
99
+ this->covariance = mc.second;
100
+
101
+ static_tlwh();
102
+ static_tlbr();
103
+
104
+ this->state = TrackState::Tracked;
105
+ this->is_activated = true;
106
+
107
+ this->score = new_track.score;
108
+ }
109
+
110
+ void STrack::static_tlwh()
111
+ {
112
+ if (this->state == TrackState::New)
113
+ {
114
+ tlwh[0] = _tlwh[0];
115
+ tlwh[1] = _tlwh[1];
116
+ tlwh[2] = _tlwh[2];
117
+ tlwh[3] = _tlwh[3];
118
+ return;
119
+ }
120
+
121
+ tlwh[0] = mean[0];
122
+ tlwh[1] = mean[1];
123
+ tlwh[2] = mean[2];
124
+ tlwh[3] = mean[3];
125
+
126
+ tlwh[2] *= tlwh[3];
127
+ tlwh[0] -= tlwh[2] / 2;
128
+ tlwh[1] -= tlwh[3] / 2;
129
+ }
130
+
131
+ void STrack::static_tlbr()
132
+ {
133
+ tlbr.clear();
134
+ tlbr.assign(tlwh.begin(), tlwh.end());
135
+ tlbr[2] += tlbr[0];
136
+ tlbr[3] += tlbr[1];
137
+ }
138
+
139
+ vector<float> STrack::tlwh_to_xyah(vector<float> tlwh_tmp)
140
+ {
141
+ vector<float> tlwh_output = tlwh_tmp;
142
+ tlwh_output[0] += tlwh_output[2] / 2;
143
+ tlwh_output[1] += tlwh_output[3] / 2;
144
+ tlwh_output[2] /= tlwh_output[3];
145
+ return tlwh_output;
146
+ }
147
+
148
+ vector<float> STrack::to_xyah()
149
+ {
150
+ return tlwh_to_xyah(tlwh);
151
+ }
152
+
153
+ vector<float> STrack::tlbr_to_tlwh(vector<float> &tlbr)
154
+ {
155
+ tlbr[2] -= tlbr[0];
156
+ tlbr[3] -= tlbr[1];
157
+ return tlbr;
158
+ }
159
+
160
+ void STrack::mark_lost()
161
+ {
162
+ state = TrackState::Lost;
163
+ }
164
+
165
+ void STrack::mark_removed()
166
+ {
167
+ state = TrackState::Removed;
168
+ }
169
+
170
+ int STrack::next_id()
171
+ {
172
+ static int _count = 0;
173
+ _count++;
174
+ return _count;
175
+ }
176
+
177
+ int STrack::end_frame()
178
+ {
179
+ return this->frame_id;
180
+ }
181
+
182
+ void STrack::multi_predict(vector<STrack*> &stracks, byte_kalman::KalmanFilter &kalman_filter)
183
+ {
184
+ for (int i = 0; i < stracks.size(); i++)
185
+ {
186
+ if (stracks[i]->state != TrackState::Tracked)
187
+ {
188
+ stracks[i]->mean[7] = 0;
189
+ }
190
+ kalman_filter.predict(stracks[i]->mean, stracks[i]->covariance);
191
+ }
192
+ }
deploy/ncnn/cpp/src/bytetrack.cpp ADDED
@@ -0,0 +1,396 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #include "layer.h"
2
+ #include "net.h"
3
+
4
+ #if defined(USE_NCNN_SIMPLEOCV)
5
+ #include "simpleocv.h"
6
+ #include <opencv2/opencv.hpp>
7
+ #else
8
+ #include <opencv2/core/core.hpp>
9
+ #include <opencv2/highgui/highgui.hpp>
10
+ #include <opencv2/imgproc/imgproc.hpp>
11
+ #include <opencv2/opencv.hpp>
12
+ #endif
13
+ #include <float.h>
14
+ #include <stdio.h>
15
+ #include <vector>
16
+ #include <chrono>
17
+ #include "BYTETracker.h"
18
+
19
+ #define YOLOX_NMS_THRESH 0.7 // nms threshold
20
+ #define YOLOX_CONF_THRESH 0.1 // threshold of bounding box prob
21
+ #define INPUT_W 1088 // target image size w after resize
22
+ #define INPUT_H 608 // target image size h after resize
23
+
24
+ Mat static_resize(Mat& img) {
25
+ float r = min(INPUT_W / (img.cols*1.0), INPUT_H / (img.rows*1.0));
26
+ // r = std::min(r, 1.0f);
27
+ int unpad_w = r * img.cols;
28
+ int unpad_h = r * img.rows;
29
+ Mat re(unpad_h, unpad_w, CV_8UC3);
30
+ resize(img, re, re.size());
31
+ Mat out(INPUT_H, INPUT_W, CV_8UC3, Scalar(114, 114, 114));
32
+ re.copyTo(out(Rect(0, 0, re.cols, re.rows)));
33
+ return out;
34
+ }
35
+
36
+ // YOLOX use the same focus in yolov5
37
+ class YoloV5Focus : public ncnn::Layer
38
+ {
39
+ public:
40
+ YoloV5Focus()
41
+ {
42
+ one_blob_only = true;
43
+ }
44
+
45
+ virtual int forward(const ncnn::Mat& bottom_blob, ncnn::Mat& top_blob, const ncnn::Option& opt) const
46
+ {
47
+ int w = bottom_blob.w;
48
+ int h = bottom_blob.h;
49
+ int channels = bottom_blob.c;
50
+
51
+ int outw = w / 2;
52
+ int outh = h / 2;
53
+ int outc = channels * 4;
54
+
55
+ top_blob.create(outw, outh, outc, 4u, 1, opt.blob_allocator);
56
+ if (top_blob.empty())
57
+ return -100;
58
+
59
+ #pragma omp parallel for num_threads(opt.num_threads)
60
+ for (int p = 0; p < outc; p++)
61
+ {
62
+ const float* ptr = bottom_blob.channel(p % channels).row((p / channels) % 2) + ((p / channels) / 2);
63
+ float* outptr = top_blob.channel(p);
64
+
65
+ for (int i = 0; i < outh; i++)
66
+ {
67
+ for (int j = 0; j < outw; j++)
68
+ {
69
+ *outptr = *ptr;
70
+
71
+ outptr += 1;
72
+ ptr += 2;
73
+ }
74
+
75
+ ptr += w;
76
+ }
77
+ }
78
+
79
+ return 0;
80
+ }
81
+ };
82
+
83
+ DEFINE_LAYER_CREATOR(YoloV5Focus)
84
+
85
+ struct GridAndStride
86
+ {
87
+ int grid0;
88
+ int grid1;
89
+ int stride;
90
+ };
91
+
92
+ static inline float intersection_area(const Object& a, const Object& b)
93
+ {
94
+ cv::Rect_<float> inter = a.rect & b.rect;
95
+ return inter.area();
96
+ }
97
+
98
+ static void qsort_descent_inplace(std::vector<Object>& faceobjects, int left, int right)
99
+ {
100
+ int i = left;
101
+ int j = right;
102
+ float p = faceobjects[(left + right) / 2].prob;
103
+
104
+ while (i <= j)
105
+ {
106
+ while (faceobjects[i].prob > p)
107
+ i++;
108
+
109
+ while (faceobjects[j].prob < p)
110
+ j--;
111
+
112
+ if (i <= j)
113
+ {
114
+ // swap
115
+ std::swap(faceobjects[i], faceobjects[j]);
116
+
117
+ i++;
118
+ j--;
119
+ }
120
+ }
121
+
122
+ #pragma omp parallel sections
123
+ {
124
+ #pragma omp section
125
+ {
126
+ if (left < j) qsort_descent_inplace(faceobjects, left, j);
127
+ }
128
+ #pragma omp section
129
+ {
130
+ if (i < right) qsort_descent_inplace(faceobjects, i, right);
131
+ }
132
+ }
133
+ }
134
+
135
+ static void qsort_descent_inplace(std::vector<Object>& objects)
136
+ {
137
+ if (objects.empty())
138
+ return;
139
+
140
+ qsort_descent_inplace(objects, 0, objects.size() - 1);
141
+ }
142
+
143
+ static void nms_sorted_bboxes(const std::vector<Object>& faceobjects, std::vector<int>& picked, float nms_threshold)
144
+ {
145
+ picked.clear();
146
+
147
+ const int n = faceobjects.size();
148
+
149
+ std::vector<float> areas(n);
150
+ for (int i = 0; i < n; i++)
151
+ {
152
+ areas[i] = faceobjects[i].rect.area();
153
+ }
154
+
155
+ for (int i = 0; i < n; i++)
156
+ {
157
+ const Object& a = faceobjects[i];
158
+
159
+ int keep = 1;
160
+ for (int j = 0; j < (int)picked.size(); j++)
161
+ {
162
+ const Object& b = faceobjects[picked[j]];
163
+
164
+ // intersection over union
165
+ float inter_area = intersection_area(a, b);
166
+ float union_area = areas[i] + areas[picked[j]] - inter_area;
167
+ // float IoU = inter_area / union_area
168
+ if (inter_area / union_area > nms_threshold)
169
+ keep = 0;
170
+ }
171
+
172
+ if (keep)
173
+ picked.push_back(i);
174
+ }
175
+ }
176
+
177
+ static void generate_grids_and_stride(const int target_w, const int target_h, std::vector<int>& strides, std::vector<GridAndStride>& grid_strides)
178
+ {
179
+ for (int i = 0; i < (int)strides.size(); i++)
180
+ {
181
+ int stride = strides[i];
182
+ int num_grid_w = target_w / stride;
183
+ int num_grid_h = target_h / stride;
184
+ for (int g1 = 0; g1 < num_grid_h; g1++)
185
+ {
186
+ for (int g0 = 0; g0 < num_grid_w; g0++)
187
+ {
188
+ GridAndStride gs;
189
+ gs.grid0 = g0;
190
+ gs.grid1 = g1;
191
+ gs.stride = stride;
192
+ grid_strides.push_back(gs);
193
+ }
194
+ }
195
+ }
196
+ }
197
+
198
+ static void generate_yolox_proposals(std::vector<GridAndStride> grid_strides, const ncnn::Mat& feat_blob, float prob_threshold, std::vector<Object>& objects)
199
+ {
200
+ const int num_grid = feat_blob.h;
201
+ const int num_class = feat_blob.w - 5;
202
+ const int num_anchors = grid_strides.size();
203
+
204
+ const float* feat_ptr = feat_blob.channel(0);
205
+ for (int anchor_idx = 0; anchor_idx < num_anchors; anchor_idx++)
206
+ {
207
+ const int grid0 = grid_strides[anchor_idx].grid0;
208
+ const int grid1 = grid_strides[anchor_idx].grid1;
209
+ const int stride = grid_strides[anchor_idx].stride;
210
+
211
+ // yolox/models/yolo_head.py decode logic
212
+ // outputs[..., :2] = (outputs[..., :2] + grids) * strides
213
+ // outputs[..., 2:4] = torch.exp(outputs[..., 2:4]) * strides
214
+ float x_center = (feat_ptr[0] + grid0) * stride;
215
+ float y_center = (feat_ptr[1] + grid1) * stride;
216
+ float w = exp(feat_ptr[2]) * stride;
217
+ float h = exp(feat_ptr[3]) * stride;
218
+ float x0 = x_center - w * 0.5f;
219
+ float y0 = y_center - h * 0.5f;
220
+
221
+ float box_objectness = feat_ptr[4];
222
+ for (int class_idx = 0; class_idx < num_class; class_idx++)
223
+ {
224
+ float box_cls_score = feat_ptr[5 + class_idx];
225
+ float box_prob = box_objectness * box_cls_score;
226
+ if (box_prob > prob_threshold)
227
+ {
228
+ Object obj;
229
+ obj.rect.x = x0;
230
+ obj.rect.y = y0;
231
+ obj.rect.width = w;
232
+ obj.rect.height = h;
233
+ obj.label = class_idx;
234
+ obj.prob = box_prob;
235
+
236
+ objects.push_back(obj);
237
+ }
238
+
239
+ } // class loop
240
+ feat_ptr += feat_blob.w;
241
+
242
+ } // point anchor loop
243
+ }
244
+
245
+ static int detect_yolox(ncnn::Mat& in_pad, std::vector<Object>& objects, ncnn::Extractor ex, float scale)
246
+ {
247
+
248
+ ex.input("images", in_pad);
249
+
250
+ std::vector<Object> proposals;
251
+
252
+ {
253
+ ncnn::Mat out;
254
+ ex.extract("output", out);
255
+
256
+ static const int stride_arr[] = {8, 16, 32}; // might have stride=64 in YOLOX
257
+ std::vector<int> strides(stride_arr, stride_arr + sizeof(stride_arr) / sizeof(stride_arr[0]));
258
+ std::vector<GridAndStride> grid_strides;
259
+ generate_grids_and_stride(INPUT_W, INPUT_H, strides, grid_strides);
260
+ generate_yolox_proposals(grid_strides, out, YOLOX_CONF_THRESH, proposals);
261
+ }
262
+ // sort all proposals by score from highest to lowest
263
+ qsort_descent_inplace(proposals);
264
+
265
+ // apply nms with nms_threshold
266
+ std::vector<int> picked;
267
+ nms_sorted_bboxes(proposals, picked, YOLOX_NMS_THRESH);
268
+
269
+ int count = picked.size();
270
+
271
+ objects.resize(count);
272
+ for (int i = 0; i < count; i++)
273
+ {
274
+ objects[i] = proposals[picked[i]];
275
+
276
+ // adjust offset to original unpadded
277
+ float x0 = (objects[i].rect.x) / scale;
278
+ float y0 = (objects[i].rect.y) / scale;
279
+ float x1 = (objects[i].rect.x + objects[i].rect.width) / scale;
280
+ float y1 = (objects[i].rect.y + objects[i].rect.height) / scale;
281
+
282
+ // clip
283
+ // x0 = std::max(std::min(x0, (float)(img_w - 1)), 0.f);
284
+ // y0 = std::max(std::min(y0, (float)(img_h - 1)), 0.f);
285
+ // x1 = std::max(std::min(x1, (float)(img_w - 1)), 0.f);
286
+ // y1 = std::max(std::min(y1, (float)(img_h - 1)), 0.f);
287
+
288
+ objects[i].rect.x = x0;
289
+ objects[i].rect.y = y0;
290
+ objects[i].rect.width = x1 - x0;
291
+ objects[i].rect.height = y1 - y0;
292
+ }
293
+
294
+ return 0;
295
+ }
296
+
297
+ int main(int argc, char** argv)
298
+ {
299
+ if (argc != 2)
300
+ {
301
+ fprintf(stderr, "Usage: %s [videopath]\n", argv[0]);
302
+ return -1;
303
+ }
304
+
305
+ ncnn::Net yolox;
306
+
307
+ //yolox.opt.use_vulkan_compute = true;
308
+ //yolox.opt.use_bf16_storage = true;
309
+ yolox.opt.num_threads = 20;
310
+ //ncnn::set_cpu_powersave(0);
311
+
312
+ //ncnn::set_omp_dynamic(0);
313
+ //ncnn::set_omp_num_threads(20);
314
+
315
+ // Focus in yolov5
316
+ yolox.register_custom_layer("YoloV5Focus", YoloV5Focus_layer_creator);
317
+
318
+ yolox.load_param("bytetrack_s_op.param");
319
+ yolox.load_model("bytetrack_s_op.bin");
320
+
321
+ ncnn::Extractor ex = yolox.create_extractor();
322
+
323
+ const char* videopath = argv[1];
324
+
325
+ VideoCapture cap(videopath);
326
+ if (!cap.isOpened())
327
+ return 0;
328
+
329
+ int img_w = cap.get(CV_CAP_PROP_FRAME_WIDTH);
330
+ int img_h = cap.get(CV_CAP_PROP_FRAME_HEIGHT);
331
+ int fps = cap.get(CV_CAP_PROP_FPS);
332
+ long nFrame = static_cast<long>(cap.get(CV_CAP_PROP_FRAME_COUNT));
333
+ cout << "Total frames: " << nFrame << endl;
334
+
335
+ VideoWriter writer("demo.mp4", CV_FOURCC('m', 'p', '4', 'v'), fps, Size(img_w, img_h));
336
+
337
+ Mat img;
338
+ BYTETracker tracker(fps, 30);
339
+ int num_frames = 0;
340
+ int total_ms = 1;
341
+ for (;;)
342
+ {
343
+ if(!cap.read(img))
344
+ break;
345
+ num_frames ++;
346
+ if (num_frames % 20 == 0)
347
+ {
348
+ cout << "Processing frame " << num_frames << " (" << num_frames * 1000000 / total_ms << " fps)" << endl;
349
+ }
350
+ if (img.empty())
351
+ break;
352
+
353
+ float scale = min(INPUT_W / (img.cols*1.0), INPUT_H / (img.rows*1.0));
354
+ Mat pr_img = static_resize(img);
355
+ ncnn::Mat in_pad = ncnn::Mat::from_pixels_resize(pr_img.data, ncnn::Mat::PIXEL_BGR2RGB, INPUT_W, INPUT_H, INPUT_W, INPUT_H);
356
+
357
+ // python 0-1 input tensor with rgb_means = (0.485, 0.456, 0.406), std = (0.229, 0.224, 0.225)
358
+ // so for 0-255 input image, rgb_mean should multiply 255 and norm should div by std.
359
+ const float mean_vals[3] = {255.f * 0.485f, 255.f * 0.456, 255.f * 0.406f};
360
+ const float norm_vals[3] = {1 / (255.f * 0.229f), 1 / (255.f * 0.224f), 1 / (255.f * 0.225f)};
361
+
362
+ in_pad.substract_mean_normalize(mean_vals, norm_vals);
363
+
364
+ std::vector<Object> objects;
365
+ auto start = chrono::system_clock::now();
366
+ //detect_yolox(img, objects);
367
+ detect_yolox(in_pad, objects, ex, scale);
368
+ vector<STrack> output_stracks = tracker.update(objects);
369
+ auto end = chrono::system_clock::now();
370
+ total_ms = total_ms + chrono::duration_cast<chrono::microseconds>(end - start).count();
371
+ for (int i = 0; i < output_stracks.size(); i++)
372
+ {
373
+ vector<float> tlwh = output_stracks[i].tlwh;
374
+ bool vertical = tlwh[2] / tlwh[3] > 1.6;
375
+ if (tlwh[2] * tlwh[3] > 20 && !vertical)
376
+ {
377
+ Scalar s = tracker.get_color(output_stracks[i].track_id);
378
+ putText(img, format("%d", output_stracks[i].track_id), Point(tlwh[0], tlwh[1] - 5),
379
+ 0, 0.6, Scalar(0, 0, 255), 2, LINE_AA);
380
+ rectangle(img, Rect(tlwh[0], tlwh[1], tlwh[2], tlwh[3]), s, 2);
381
+ }
382
+ }
383
+ putText(img, format("frame: %d fps: %d num: %d", num_frames, num_frames * 1000000 / total_ms, output_stracks.size()),
384
+ Point(0, 30), 0, 0.6, Scalar(0, 0, 255), 2, LINE_AA);
385
+ writer.write(img);
386
+ char c = waitKey(1);
387
+ if (c > 0)
388
+ {
389
+ break;
390
+ }
391
+ }
392
+ cap.release();
393
+ cout << "FPS: " << num_frames * 1000000 / total_ms << endl;
394
+
395
+ return 0;
396
+ }
deploy/ncnn/cpp/src/kalmanFilter.cpp ADDED
@@ -0,0 +1,152 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #include "kalmanFilter.h"
2
+ #include <Eigen/Cholesky>
3
+
4
+ namespace byte_kalman
5
+ {
6
+ const double KalmanFilter::chi2inv95[10] = {
7
+ 0,
8
+ 3.8415,
9
+ 5.9915,
10
+ 7.8147,
11
+ 9.4877,
12
+ 11.070,
13
+ 12.592,
14
+ 14.067,
15
+ 15.507,
16
+ 16.919
17
+ };
18
+ KalmanFilter::KalmanFilter()
19
+ {
20
+ int ndim = 4;
21
+ double dt = 1.;
22
+
23
+ _motion_mat = Eigen::MatrixXf::Identity(8, 8);
24
+ for (int i = 0; i < ndim; i++) {
25
+ _motion_mat(i, ndim + i) = dt;
26
+ }
27
+ _update_mat = Eigen::MatrixXf::Identity(4, 8);
28
+
29
+ this->_std_weight_position = 1. / 20;
30
+ this->_std_weight_velocity = 1. / 160;
31
+ }
32
+
33
+ KAL_DATA KalmanFilter::initiate(const DETECTBOX &measurement)
34
+ {
35
+ DETECTBOX mean_pos = measurement;
36
+ DETECTBOX mean_vel;
37
+ for (int i = 0; i < 4; i++) mean_vel(i) = 0;
38
+
39
+ KAL_MEAN mean;
40
+ for (int i = 0; i < 8; i++) {
41
+ if (i < 4) mean(i) = mean_pos(i);
42
+ else mean(i) = mean_vel(i - 4);
43
+ }
44
+
45
+ KAL_MEAN std;
46
+ std(0) = 2 * _std_weight_position * measurement[3];
47
+ std(1) = 2 * _std_weight_position * measurement[3];
48
+ std(2) = 1e-2;
49
+ std(3) = 2 * _std_weight_position * measurement[3];
50
+ std(4) = 10 * _std_weight_velocity * measurement[3];
51
+ std(5) = 10 * _std_weight_velocity * measurement[3];
52
+ std(6) = 1e-5;
53
+ std(7) = 10 * _std_weight_velocity * measurement[3];
54
+
55
+ KAL_MEAN tmp = std.array().square();
56
+ KAL_COVA var = tmp.asDiagonal();
57
+ return std::make_pair(mean, var);
58
+ }
59
+
60
+ void KalmanFilter::predict(KAL_MEAN &mean, KAL_COVA &covariance)
61
+ {
62
+ //revise the data;
63
+ DETECTBOX std_pos;
64
+ std_pos << _std_weight_position * mean(3),
65
+ _std_weight_position * mean(3),
66
+ 1e-2,
67
+ _std_weight_position * mean(3);
68
+ DETECTBOX std_vel;
69
+ std_vel << _std_weight_velocity * mean(3),
70
+ _std_weight_velocity * mean(3),
71
+ 1e-5,
72
+ _std_weight_velocity * mean(3);
73
+ KAL_MEAN tmp;
74
+ tmp.block<1, 4>(0, 0) = std_pos;
75
+ tmp.block<1, 4>(0, 4) = std_vel;
76
+ tmp = tmp.array().square();
77
+ KAL_COVA motion_cov = tmp.asDiagonal();
78
+ KAL_MEAN mean1 = this->_motion_mat * mean.transpose();
79
+ KAL_COVA covariance1 = this->_motion_mat * covariance *(_motion_mat.transpose());
80
+ covariance1 += motion_cov;
81
+
82
+ mean = mean1;
83
+ covariance = covariance1;
84
+ }
85
+
86
+ KAL_HDATA KalmanFilter::project(const KAL_MEAN &mean, const KAL_COVA &covariance)
87
+ {
88
+ DETECTBOX std;
89
+ std << _std_weight_position * mean(3), _std_weight_position * mean(3),
90
+ 1e-1, _std_weight_position * mean(3);
91
+ KAL_HMEAN mean1 = _update_mat * mean.transpose();
92
+ KAL_HCOVA covariance1 = _update_mat * covariance * (_update_mat.transpose());
93
+ Eigen::Matrix<float, 4, 4> diag = std.asDiagonal();
94
+ diag = diag.array().square().matrix();
95
+ covariance1 += diag;
96
+ // covariance1.diagonal() << diag;
97
+ return std::make_pair(mean1, covariance1);
98
+ }
99
+
100
+ KAL_DATA
101
+ KalmanFilter::update(
102
+ const KAL_MEAN &mean,
103
+ const KAL_COVA &covariance,
104
+ const DETECTBOX &measurement)
105
+ {
106
+ KAL_HDATA pa = project(mean, covariance);
107
+ KAL_HMEAN projected_mean = pa.first;
108
+ KAL_HCOVA projected_cov = pa.second;
109
+
110
+ //chol_factor, lower =
111
+ //scipy.linalg.cho_factor(projected_cov, lower=True, check_finite=False)
112
+ //kalmain_gain =
113
+ //scipy.linalg.cho_solve((cho_factor, lower),
114
+ //np.dot(covariance, self._upadte_mat.T).T,
115
+ //check_finite=False).T
116
+ Eigen::Matrix<float, 4, 8> B = (covariance * (_update_mat.transpose())).transpose();
117
+ Eigen::Matrix<float, 8, 4> kalman_gain = (projected_cov.llt().solve(B)).transpose(); // eg.8x4
118
+ Eigen::Matrix<float, 1, 4> innovation = measurement - projected_mean; //eg.1x4
119
+ auto tmp = innovation * (kalman_gain.transpose());
120
+ KAL_MEAN new_mean = (mean.array() + tmp.array()).matrix();
121
+ KAL_COVA new_covariance = covariance - kalman_gain * projected_cov*(kalman_gain.transpose());
122
+ return std::make_pair(new_mean, new_covariance);
123
+ }
124
+
125
+ Eigen::Matrix<float, 1, -1>
126
+ KalmanFilter::gating_distance(
127
+ const KAL_MEAN &mean,
128
+ const KAL_COVA &covariance,
129
+ const std::vector<DETECTBOX> &measurements,
130
+ bool only_position)
131
+ {
132
+ KAL_HDATA pa = this->project(mean, covariance);
133
+ if (only_position) {
134
+ printf("not implement!");
135
+ exit(0);
136
+ }
137
+ KAL_HMEAN mean1 = pa.first;
138
+ KAL_HCOVA covariance1 = pa.second;
139
+
140
+ // Eigen::Matrix<float, -1, 4, Eigen::RowMajor> d(size, 4);
141
+ DETECTBOXSS d(measurements.size(), 4);
142
+ int pos = 0;
143
+ for (DETECTBOX box : measurements) {
144
+ d.row(pos++) = box - mean1;
145
+ }
146
+ Eigen::Matrix<float, -1, -1, Eigen::RowMajor> factor = covariance1.llt().matrixL();
147
+ Eigen::Matrix<float, -1, -1> z = factor.triangularView<Eigen::Lower>().solve<Eigen::OnTheRight>(d).transpose();
148
+ auto zz = ((z.array())*(z.array())).matrix();
149
+ auto square_maha = zz.colwise().sum();
150
+ return square_maha;
151
+ }
152
+ }
deploy/ncnn/cpp/src/lapjv.cpp ADDED
@@ -0,0 +1,343 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #include <stdio.h>
2
+ #include <stdlib.h>
3
+ #include <string.h>
4
+
5
+ #include "lapjv.h"
6
+
7
+ /** Column-reduction and reduction transfer for a dense cost matrix.
8
+ */
9
+ int_t _ccrrt_dense(const uint_t n, cost_t *cost[],
10
+ int_t *free_rows, int_t *x, int_t *y, cost_t *v)
11
+ {
12
+ int_t n_free_rows;
13
+ boolean *unique;
14
+
15
+ for (uint_t i = 0; i < n; i++) {
16
+ x[i] = -1;
17
+ v[i] = LARGE;
18
+ y[i] = 0;
19
+ }
20
+ for (uint_t i = 0; i < n; i++) {
21
+ for (uint_t j = 0; j < n; j++) {
22
+ const cost_t c = cost[i][j];
23
+ if (c < v[j]) {
24
+ v[j] = c;
25
+ y[j] = i;
26
+ }
27
+ PRINTF("i=%d, j=%d, c[i,j]=%f, v[j]=%f y[j]=%d\n", i, j, c, v[j], y[j]);
28
+ }
29
+ }
30
+ PRINT_COST_ARRAY(v, n);
31
+ PRINT_INDEX_ARRAY(y, n);
32
+ NEW(unique, boolean, n);
33
+ memset(unique, TRUE, n);
34
+ {
35
+ int_t j = n;
36
+ do {
37
+ j--;
38
+ const int_t i = y[j];
39
+ if (x[i] < 0) {
40
+ x[i] = j;
41
+ }
42
+ else {
43
+ unique[i] = FALSE;
44
+ y[j] = -1;
45
+ }
46
+ } while (j > 0);
47
+ }
48
+ n_free_rows = 0;
49
+ for (uint_t i = 0; i < n; i++) {
50
+ if (x[i] < 0) {
51
+ free_rows[n_free_rows++] = i;
52
+ }
53
+ else if (unique[i]) {
54
+ const int_t j = x[i];
55
+ cost_t min = LARGE;
56
+ for (uint_t j2 = 0; j2 < n; j2++) {
57
+ if (j2 == (uint_t)j) {
58
+ continue;
59
+ }
60
+ const cost_t c = cost[i][j2] - v[j2];
61
+ if (c < min) {
62
+ min = c;
63
+ }
64
+ }
65
+ PRINTF("v[%d] = %f - %f\n", j, v[j], min);
66
+ v[j] -= min;
67
+ }
68
+ }
69
+ FREE(unique);
70
+ return n_free_rows;
71
+ }
72
+
73
+
74
+ /** Augmenting row reduction for a dense cost matrix.
75
+ */
76
+ int_t _carr_dense(
77
+ const uint_t n, cost_t *cost[],
78
+ const uint_t n_free_rows,
79
+ int_t *free_rows, int_t *x, int_t *y, cost_t *v)
80
+ {
81
+ uint_t current = 0;
82
+ int_t new_free_rows = 0;
83
+ uint_t rr_cnt = 0;
84
+ PRINT_INDEX_ARRAY(x, n);
85
+ PRINT_INDEX_ARRAY(y, n);
86
+ PRINT_COST_ARRAY(v, n);
87
+ PRINT_INDEX_ARRAY(free_rows, n_free_rows);
88
+ while (current < n_free_rows) {
89
+ int_t i0;
90
+ int_t j1, j2;
91
+ cost_t v1, v2, v1_new;
92
+ boolean v1_lowers;
93
+
94
+ rr_cnt++;
95
+ PRINTF("current = %d rr_cnt = %d\n", current, rr_cnt);
96
+ const int_t free_i = free_rows[current++];
97
+ j1 = 0;
98
+ v1 = cost[free_i][0] - v[0];
99
+ j2 = -1;
100
+ v2 = LARGE;
101
+ for (uint_t j = 1; j < n; j++) {
102
+ PRINTF("%d = %f %d = %f\n", j1, v1, j2, v2);
103
+ const cost_t c = cost[free_i][j] - v[j];
104
+ if (c < v2) {
105
+ if (c >= v1) {
106
+ v2 = c;
107
+ j2 = j;
108
+ }
109
+ else {
110
+ v2 = v1;
111
+ v1 = c;
112
+ j2 = j1;
113
+ j1 = j;
114
+ }
115
+ }
116
+ }
117
+ i0 = y[j1];
118
+ v1_new = v[j1] - (v2 - v1);
119
+ v1_lowers = v1_new < v[j1];
120
+ PRINTF("%d %d 1=%d,%f 2=%d,%f v1'=%f(%d,%g) \n", free_i, i0, j1, v1, j2, v2, v1_new, v1_lowers, v[j1] - v1_new);
121
+ if (rr_cnt < current * n) {
122
+ if (v1_lowers) {
123
+ v[j1] = v1_new;
124
+ }
125
+ else if (i0 >= 0 && j2 >= 0) {
126
+ j1 = j2;
127
+ i0 = y[j2];
128
+ }
129
+ if (i0 >= 0) {
130
+ if (v1_lowers) {
131
+ free_rows[--current] = i0;
132
+ }
133
+ else {
134
+ free_rows[new_free_rows++] = i0;
135
+ }
136
+ }
137
+ }
138
+ else {
139
+ PRINTF("rr_cnt=%d >= %d (current=%d * n=%d)\n", rr_cnt, current * n, current, n);
140
+ if (i0 >= 0) {
141
+ free_rows[new_free_rows++] = i0;
142
+ }
143
+ }
144
+ x[free_i] = j1;
145
+ y[j1] = free_i;
146
+ }
147
+ return new_free_rows;
148
+ }
149
+
150
+
151
+ /** Find columns with minimum d[j] and put them on the SCAN list.
152
+ */
153
+ uint_t _find_dense(const uint_t n, uint_t lo, cost_t *d, int_t *cols, int_t *y)
154
+ {
155
+ uint_t hi = lo + 1;
156
+ cost_t mind = d[cols[lo]];
157
+ for (uint_t k = hi; k < n; k++) {
158
+ int_t j = cols[k];
159
+ if (d[j] <= mind) {
160
+ if (d[j] < mind) {
161
+ hi = lo;
162
+ mind = d[j];
163
+ }
164
+ cols[k] = cols[hi];
165
+ cols[hi++] = j;
166
+ }
167
+ }
168
+ return hi;
169
+ }
170
+
171
+
172
+ // Scan all columns in TODO starting from arbitrary column in SCAN
173
+ // and try to decrease d of the TODO columns using the SCAN column.
174
+ int_t _scan_dense(const uint_t n, cost_t *cost[],
175
+ uint_t *plo, uint_t*phi,
176
+ cost_t *d, int_t *cols, int_t *pred,
177
+ int_t *y, cost_t *v)
178
+ {
179
+ uint_t lo = *plo;
180
+ uint_t hi = *phi;
181
+ cost_t h, cred_ij;
182
+
183
+ while (lo != hi) {
184
+ int_t j = cols[lo++];
185
+ const int_t i = y[j];
186
+ const cost_t mind = d[j];
187
+ h = cost[i][j] - v[j] - mind;
188
+ PRINTF("i=%d j=%d h=%f\n", i, j, h);
189
+ // For all columns in TODO
190
+ for (uint_t k = hi; k < n; k++) {
191
+ j = cols[k];
192
+ cred_ij = cost[i][j] - v[j] - h;
193
+ if (cred_ij < d[j]) {
194
+ d[j] = cred_ij;
195
+ pred[j] = i;
196
+ if (cred_ij == mind) {
197
+ if (y[j] < 0) {
198
+ return j;
199
+ }
200
+ cols[k] = cols[hi];
201
+ cols[hi++] = j;
202
+ }
203
+ }
204
+ }
205
+ }
206
+ *plo = lo;
207
+ *phi = hi;
208
+ return -1;
209
+ }
210
+
211
+
212
+ /** Single iteration of modified Dijkstra shortest path algorithm as explained in the JV paper.
213
+ *
214
+ * This is a dense matrix version.
215
+ *
216
+ * \return The closest free column index.
217
+ */
218
+ int_t find_path_dense(
219
+ const uint_t n, cost_t *cost[],
220
+ const int_t start_i,
221
+ int_t *y, cost_t *v,
222
+ int_t *pred)
223
+ {
224
+ uint_t lo = 0, hi = 0;
225
+ int_t final_j = -1;
226
+ uint_t n_ready = 0;
227
+ int_t *cols;
228
+ cost_t *d;
229
+
230
+ NEW(cols, int_t, n);
231
+ NEW(d, cost_t, n);
232
+
233
+ for (uint_t i = 0; i < n; i++) {
234
+ cols[i] = i;
235
+ pred[i] = start_i;
236
+ d[i] = cost[start_i][i] - v[i];
237
+ }
238
+ PRINT_COST_ARRAY(d, n);
239
+ while (final_j == -1) {
240
+ // No columns left on the SCAN list.
241
+ if (lo == hi) {
242
+ PRINTF("%d..%d -> find\n", lo, hi);
243
+ n_ready = lo;
244
+ hi = _find_dense(n, lo, d, cols, y);
245
+ PRINTF("check %d..%d\n", lo, hi);
246
+ PRINT_INDEX_ARRAY(cols, n);
247
+ for (uint_t k = lo; k < hi; k++) {
248
+ const int_t j = cols[k];
249
+ if (y[j] < 0) {
250
+ final_j = j;
251
+ }
252
+ }
253
+ }
254
+ if (final_j == -1) {
255
+ PRINTF("%d..%d -> scan\n", lo, hi);
256
+ final_j = _scan_dense(
257
+ n, cost, &lo, &hi, d, cols, pred, y, v);
258
+ PRINT_COST_ARRAY(d, n);
259
+ PRINT_INDEX_ARRAY(cols, n);
260
+ PRINT_INDEX_ARRAY(pred, n);
261
+ }
262
+ }
263
+
264
+ PRINTF("found final_j=%d\n", final_j);
265
+ PRINT_INDEX_ARRAY(cols, n);
266
+ {
267
+ const cost_t mind = d[cols[lo]];
268
+ for (uint_t k = 0; k < n_ready; k++) {
269
+ const int_t j = cols[k];
270
+ v[j] += d[j] - mind;
271
+ }
272
+ }
273
+
274
+ FREE(cols);
275
+ FREE(d);
276
+
277
+ return final_j;
278
+ }
279
+
280
+
281
+ /** Augment for a dense cost matrix.
282
+ */
283
+ int_t _ca_dense(
284
+ const uint_t n, cost_t *cost[],
285
+ const uint_t n_free_rows,
286
+ int_t *free_rows, int_t *x, int_t *y, cost_t *v)
287
+ {
288
+ int_t *pred;
289
+
290
+ NEW(pred, int_t, n);
291
+
292
+ for (int_t *pfree_i = free_rows; pfree_i < free_rows + n_free_rows; pfree_i++) {
293
+ int_t i = -1, j;
294
+ uint_t k = 0;
295
+
296
+ PRINTF("looking at free_i=%d\n", *pfree_i);
297
+ j = find_path_dense(n, cost, *pfree_i, y, v, pred);
298
+ ASSERT(j >= 0);
299
+ ASSERT(j < n);
300
+ while (i != *pfree_i) {
301
+ PRINTF("augment %d\n", j);
302
+ PRINT_INDEX_ARRAY(pred, n);
303
+ i = pred[j];
304
+ PRINTF("y[%d]=%d -> %d\n", j, y[j], i);
305
+ y[j] = i;
306
+ PRINT_INDEX_ARRAY(x, n);
307
+ SWAP_INDICES(j, x[i]);
308
+ k++;
309
+ if (k >= n) {
310
+ ASSERT(FALSE);
311
+ }
312
+ }
313
+ }
314
+ FREE(pred);
315
+ return 0;
316
+ }
317
+
318
+
319
+ /** Solve dense sparse LAP.
320
+ */
321
+ int lapjv_internal(
322
+ const uint_t n, cost_t *cost[],
323
+ int_t *x, int_t *y)
324
+ {
325
+ int ret;
326
+ int_t *free_rows;
327
+ cost_t *v;
328
+
329
+ NEW(free_rows, int_t, n);
330
+ NEW(v, cost_t, n);
331
+ ret = _ccrrt_dense(n, cost, free_rows, x, y, v);
332
+ int i = 0;
333
+ while (ret > 0 && i < 2) {
334
+ ret = _carr_dense(n, cost, ret, free_rows, x, y, v);
335
+ i++;
336
+ }
337
+ if (ret > 0) {
338
+ ret = _ca_dense(n, cost, ret, free_rows, x, y, v);
339
+ }
340
+ FREE(v);
341
+ FREE(free_rows);
342
+ return ret;
343
+ }
deploy/ncnn/cpp/src/utils.cpp ADDED
@@ -0,0 +1,429 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #include "BYTETracker.h"
2
+ #include "lapjv.h"
3
+
4
+ vector<STrack*> BYTETracker::joint_stracks(vector<STrack*> &tlista, vector<STrack> &tlistb)
5
+ {
6
+ map<int, int> exists;
7
+ vector<STrack*> res;
8
+ for (int i = 0; i < tlista.size(); i++)
9
+ {
10
+ exists.insert(pair<int, int>(tlista[i]->track_id, 1));
11
+ res.push_back(tlista[i]);
12
+ }
13
+ for (int i = 0; i < tlistb.size(); i++)
14
+ {
15
+ int tid = tlistb[i].track_id;
16
+ if (!exists[tid] || exists.count(tid) == 0)
17
+ {
18
+ exists[tid] = 1;
19
+ res.push_back(&tlistb[i]);
20
+ }
21
+ }
22
+ return res;
23
+ }
24
+
25
+ vector<STrack> BYTETracker::joint_stracks(vector<STrack> &tlista, vector<STrack> &tlistb)
26
+ {
27
+ map<int, int> exists;
28
+ vector<STrack> res;
29
+ for (int i = 0; i < tlista.size(); i++)
30
+ {
31
+ exists.insert(pair<int, int>(tlista[i].track_id, 1));
32
+ res.push_back(tlista[i]);
33
+ }
34
+ for (int i = 0; i < tlistb.size(); i++)
35
+ {
36
+ int tid = tlistb[i].track_id;
37
+ if (!exists[tid] || exists.count(tid) == 0)
38
+ {
39
+ exists[tid] = 1;
40
+ res.push_back(tlistb[i]);
41
+ }
42
+ }
43
+ return res;
44
+ }
45
+
46
+ vector<STrack> BYTETracker::sub_stracks(vector<STrack> &tlista, vector<STrack> &tlistb)
47
+ {
48
+ map<int, STrack> stracks;
49
+ for (int i = 0; i < tlista.size(); i++)
50
+ {
51
+ stracks.insert(pair<int, STrack>(tlista[i].track_id, tlista[i]));
52
+ }
53
+ for (int i = 0; i < tlistb.size(); i++)
54
+ {
55
+ int tid = tlistb[i].track_id;
56
+ if (stracks.count(tid) != 0)
57
+ {
58
+ stracks.erase(tid);
59
+ }
60
+ }
61
+
62
+ vector<STrack> res;
63
+ std::map<int, STrack>::iterator it;
64
+ for (it = stracks.begin(); it != stracks.end(); ++it)
65
+ {
66
+ res.push_back(it->second);
67
+ }
68
+
69
+ return res;
70
+ }
71
+
72
+ void BYTETracker::remove_duplicate_stracks(vector<STrack> &resa, vector<STrack> &resb, vector<STrack> &stracksa, vector<STrack> &stracksb)
73
+ {
74
+ vector<vector<float> > pdist = iou_distance(stracksa, stracksb);
75
+ vector<pair<int, int> > pairs;
76
+ for (int i = 0; i < pdist.size(); i++)
77
+ {
78
+ for (int j = 0; j < pdist[i].size(); j++)
79
+ {
80
+ if (pdist[i][j] < 0.15)
81
+ {
82
+ pairs.push_back(pair<int, int>(i, j));
83
+ }
84
+ }
85
+ }
86
+
87
+ vector<int> dupa, dupb;
88
+ for (int i = 0; i < pairs.size(); i++)
89
+ {
90
+ int timep = stracksa[pairs[i].first].frame_id - stracksa[pairs[i].first].start_frame;
91
+ int timeq = stracksb[pairs[i].second].frame_id - stracksb[pairs[i].second].start_frame;
92
+ if (timep > timeq)
93
+ dupb.push_back(pairs[i].second);
94
+ else
95
+ dupa.push_back(pairs[i].first);
96
+ }
97
+
98
+ for (int i = 0; i < stracksa.size(); i++)
99
+ {
100
+ vector<int>::iterator iter = find(dupa.begin(), dupa.end(), i);
101
+ if (iter == dupa.end())
102
+ {
103
+ resa.push_back(stracksa[i]);
104
+ }
105
+ }
106
+
107
+ for (int i = 0; i < stracksb.size(); i++)
108
+ {
109
+ vector<int>::iterator iter = find(dupb.begin(), dupb.end(), i);
110
+ if (iter == dupb.end())
111
+ {
112
+ resb.push_back(stracksb[i]);
113
+ }
114
+ }
115
+ }
116
+
117
+ void BYTETracker::linear_assignment(vector<vector<float> > &cost_matrix, int cost_matrix_size, int cost_matrix_size_size, float thresh,
118
+ vector<vector<int> > &matches, vector<int> &unmatched_a, vector<int> &unmatched_b)
119
+ {
120
+ if (cost_matrix.size() == 0)
121
+ {
122
+ for (int i = 0; i < cost_matrix_size; i++)
123
+ {
124
+ unmatched_a.push_back(i);
125
+ }
126
+ for (int i = 0; i < cost_matrix_size_size; i++)
127
+ {
128
+ unmatched_b.push_back(i);
129
+ }
130
+ return;
131
+ }
132
+
133
+ vector<int> rowsol; vector<int> colsol;
134
+ float c = lapjv(cost_matrix, rowsol, colsol, true, thresh);
135
+ for (int i = 0; i < rowsol.size(); i++)
136
+ {
137
+ if (rowsol[i] >= 0)
138
+ {
139
+ vector<int> match;
140
+ match.push_back(i);
141
+ match.push_back(rowsol[i]);
142
+ matches.push_back(match);
143
+ }
144
+ else
145
+ {
146
+ unmatched_a.push_back(i);
147
+ }
148
+ }
149
+
150
+ for (int i = 0; i < colsol.size(); i++)
151
+ {
152
+ if (colsol[i] < 0)
153
+ {
154
+ unmatched_b.push_back(i);
155
+ }
156
+ }
157
+ }
158
+
159
+ vector<vector<float> > BYTETracker::ious(vector<vector<float> > &atlbrs, vector<vector<float> > &btlbrs)
160
+ {
161
+ vector<vector<float> > ious;
162
+ if (atlbrs.size()*btlbrs.size() == 0)
163
+ return ious;
164
+
165
+ ious.resize(atlbrs.size());
166
+ for (int i = 0; i < ious.size(); i++)
167
+ {
168
+ ious[i].resize(btlbrs.size());
169
+ }
170
+
171
+ //bbox_ious
172
+ for (int k = 0; k < btlbrs.size(); k++)
173
+ {
174
+ vector<float> ious_tmp;
175
+ float box_area = (btlbrs[k][2] - btlbrs[k][0] + 1)*(btlbrs[k][3] - btlbrs[k][1] + 1);
176
+ for (int n = 0; n < atlbrs.size(); n++)
177
+ {
178
+ float iw = min(atlbrs[n][2], btlbrs[k][2]) - max(atlbrs[n][0], btlbrs[k][0]) + 1;
179
+ if (iw > 0)
180
+ {
181
+ float ih = min(atlbrs[n][3], btlbrs[k][3]) - max(atlbrs[n][1], btlbrs[k][1]) + 1;
182
+ if(ih > 0)
183
+ {
184
+ float ua = (atlbrs[n][2] - atlbrs[n][0] + 1)*(atlbrs[n][3] - atlbrs[n][1] + 1) + box_area - iw * ih;
185
+ ious[n][k] = iw * ih / ua;
186
+ }
187
+ else
188
+ {
189
+ ious[n][k] = 0.0;
190
+ }
191
+ }
192
+ else
193
+ {
194
+ ious[n][k] = 0.0;
195
+ }
196
+ }
197
+ }
198
+
199
+ return ious;
200
+ }
201
+
202
+ vector<vector<float> > BYTETracker::iou_distance(vector<STrack*> &atracks, vector<STrack> &btracks, int &dist_size, int &dist_size_size)
203
+ {
204
+ vector<vector<float> > cost_matrix;
205
+ if (atracks.size() * btracks.size() == 0)
206
+ {
207
+ dist_size = atracks.size();
208
+ dist_size_size = btracks.size();
209
+ return cost_matrix;
210
+ }
211
+ vector<vector<float> > atlbrs, btlbrs;
212
+ for (int i = 0; i < atracks.size(); i++)
213
+ {
214
+ atlbrs.push_back(atracks[i]->tlbr);
215
+ }
216
+ for (int i = 0; i < btracks.size(); i++)
217
+ {
218
+ btlbrs.push_back(btracks[i].tlbr);
219
+ }
220
+
221
+ dist_size = atracks.size();
222
+ dist_size_size = btracks.size();
223
+
224
+ vector<vector<float> > _ious = ious(atlbrs, btlbrs);
225
+
226
+ for (int i = 0; i < _ious.size();i++)
227
+ {
228
+ vector<float> _iou;
229
+ for (int j = 0; j < _ious[i].size(); j++)
230
+ {
231
+ _iou.push_back(1 - _ious[i][j]);
232
+ }
233
+ cost_matrix.push_back(_iou);
234
+ }
235
+
236
+ return cost_matrix;
237
+ }
238
+
239
+ vector<vector<float> > BYTETracker::iou_distance(vector<STrack> &atracks, vector<STrack> &btracks)
240
+ {
241
+ vector<vector<float> > atlbrs, btlbrs;
242
+ for (int i = 0; i < atracks.size(); i++)
243
+ {
244
+ atlbrs.push_back(atracks[i].tlbr);
245
+ }
246
+ for (int i = 0; i < btracks.size(); i++)
247
+ {
248
+ btlbrs.push_back(btracks[i].tlbr);
249
+ }
250
+
251
+ vector<vector<float> > _ious = ious(atlbrs, btlbrs);
252
+ vector<vector<float> > cost_matrix;
253
+ for (int i = 0; i < _ious.size(); i++)
254
+ {
255
+ vector<float> _iou;
256
+ for (int j = 0; j < _ious[i].size(); j++)
257
+ {
258
+ _iou.push_back(1 - _ious[i][j]);
259
+ }
260
+ cost_matrix.push_back(_iou);
261
+ }
262
+
263
+ return cost_matrix;
264
+ }
265
+
266
+ double BYTETracker::lapjv(const vector<vector<float> > &cost, vector<int> &rowsol, vector<int> &colsol,
267
+ bool extend_cost, float cost_limit, bool return_cost)
268
+ {
269
+ vector<vector<float> > cost_c;
270
+ cost_c.assign(cost.begin(), cost.end());
271
+
272
+ vector<vector<float> > cost_c_extended;
273
+
274
+ int n_rows = cost.size();
275
+ int n_cols = cost[0].size();
276
+ rowsol.resize(n_rows);
277
+ colsol.resize(n_cols);
278
+
279
+ int n = 0;
280
+ if (n_rows == n_cols)
281
+ {
282
+ n = n_rows;
283
+ }
284
+ else
285
+ {
286
+ if (!extend_cost)
287
+ {
288
+ cout << "set extend_cost=True" << endl;
289
+ system("pause");
290
+ exit(0);
291
+ }
292
+ }
293
+
294
+ if (extend_cost || cost_limit < LONG_MAX)
295
+ {
296
+ n = n_rows + n_cols;
297
+ cost_c_extended.resize(n);
298
+ for (int i = 0; i < cost_c_extended.size(); i++)
299
+ cost_c_extended[i].resize(n);
300
+
301
+ if (cost_limit < LONG_MAX)
302
+ {
303
+ for (int i = 0; i < cost_c_extended.size(); i++)
304
+ {
305
+ for (int j = 0; j < cost_c_extended[i].size(); j++)
306
+ {
307
+ cost_c_extended[i][j] = cost_limit / 2.0;
308
+ }
309
+ }
310
+ }
311
+ else
312
+ {
313
+ float cost_max = -1;
314
+ for (int i = 0; i < cost_c.size(); i++)
315
+ {
316
+ for (int j = 0; j < cost_c[i].size(); j++)
317
+ {
318
+ if (cost_c[i][j] > cost_max)
319
+ cost_max = cost_c[i][j];
320
+ }
321
+ }
322
+ for (int i = 0; i < cost_c_extended.size(); i++)
323
+ {
324
+ for (int j = 0; j < cost_c_extended[i].size(); j++)
325
+ {
326
+ cost_c_extended[i][j] = cost_max + 1;
327
+ }
328
+ }
329
+ }
330
+
331
+ for (int i = n_rows; i < cost_c_extended.size(); i++)
332
+ {
333
+ for (int j = n_cols; j < cost_c_extended[i].size(); j++)
334
+ {
335
+ cost_c_extended[i][j] = 0;
336
+ }
337
+ }
338
+ for (int i = 0; i < n_rows; i++)
339
+ {
340
+ for (int j = 0; j < n_cols; j++)
341
+ {
342
+ cost_c_extended[i][j] = cost_c[i][j];
343
+ }
344
+ }
345
+
346
+ cost_c.clear();
347
+ cost_c.assign(cost_c_extended.begin(), cost_c_extended.end());
348
+ }
349
+
350
+ double **cost_ptr;
351
+ cost_ptr = new double *[sizeof(double *) * n];
352
+ for (int i = 0; i < n; i++)
353
+ cost_ptr[i] = new double[sizeof(double) * n];
354
+
355
+ for (int i = 0; i < n; i++)
356
+ {
357
+ for (int j = 0; j < n; j++)
358
+ {
359
+ cost_ptr[i][j] = cost_c[i][j];
360
+ }
361
+ }
362
+
363
+ int* x_c = new int[sizeof(int) * n];
364
+ int *y_c = new int[sizeof(int) * n];
365
+
366
+ int ret = lapjv_internal(n, cost_ptr, x_c, y_c);
367
+ if (ret != 0)
368
+ {
369
+ cout << "Calculate Wrong!" << endl;
370
+ system("pause");
371
+ exit(0);
372
+ }
373
+
374
+ double opt = 0.0;
375
+
376
+ if (n != n_rows)
377
+ {
378
+ for (int i = 0; i < n; i++)
379
+ {
380
+ if (x_c[i] >= n_cols)
381
+ x_c[i] = -1;
382
+ if (y_c[i] >= n_rows)
383
+ y_c[i] = -1;
384
+ }
385
+ for (int i = 0; i < n_rows; i++)
386
+ {
387
+ rowsol[i] = x_c[i];
388
+ }
389
+ for (int i = 0; i < n_cols; i++)
390
+ {
391
+ colsol[i] = y_c[i];
392
+ }
393
+
394
+ if (return_cost)
395
+ {
396
+ for (int i = 0; i < rowsol.size(); i++)
397
+ {
398
+ if (rowsol[i] != -1)
399
+ {
400
+ //cout << i << "\t" << rowsol[i] << "\t" << cost_ptr[i][rowsol[i]] << endl;
401
+ opt += cost_ptr[i][rowsol[i]];
402
+ }
403
+ }
404
+ }
405
+ }
406
+ else if (return_cost)
407
+ {
408
+ for (int i = 0; i < rowsol.size(); i++)
409
+ {
410
+ opt += cost_ptr[i][rowsol[i]];
411
+ }
412
+ }
413
+
414
+ for (int i = 0; i < n; i++)
415
+ {
416
+ delete[]cost_ptr[i];
417
+ }
418
+ delete[]cost_ptr;
419
+ delete[]x_c;
420
+ delete[]y_c;
421
+
422
+ return opt;
423
+ }
424
+
425
+ Scalar BYTETracker::get_color(int idx)
426
+ {
427
+ idx += 3;
428
+ return Scalar(37 * idx % 255, 17 * idx % 255, 29 * idx % 255);
429
+ }
exps/default/nano.py ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ # -*- coding:utf-8 -*-
3
+ # Copyright (c) Megvii, Inc. and its affiliates.
4
+
5
+ import os
6
+ import torch.nn as nn
7
+
8
+ from yolox.exp import Exp as MyExp
9
+
10
+
11
+ class Exp(MyExp):
12
+ def __init__(self):
13
+ super(Exp, self).__init__()
14
+ self.depth = 0.33
15
+ self.width = 0.25
16
+ self.scale = (0.5, 1.5)
17
+ self.random_size = (10, 20)
18
+ self.test_size = (416, 416)
19
+ self.exp_name = os.path.split(os.path.realpath(__file__))[1].split(".")[0]
20
+ self.enable_mixup = False
21
+
22
+ def get_model(self, sublinear=False):
23
+
24
+ def init_yolo(M):
25
+ for m in M.modules():
26
+ if isinstance(m, nn.BatchNorm2d):
27
+ m.eps = 1e-3
28
+ m.momentum = 0.03
29
+ if "model" not in self.__dict__:
30
+ from yolox.models import YOLOX, YOLOPAFPN, YOLOXHead
31
+ in_channels = [256, 512, 1024]
32
+ # NANO model use depthwise = True, which is main difference.
33
+ backbone = YOLOPAFPN(self.depth, self.width, in_channels=in_channels, depthwise=True)
34
+ head = YOLOXHead(self.num_classes, self.width, in_channels=in_channels, depthwise=True)
35
+ self.model = YOLOX(backbone, head)
36
+
37
+ self.model.apply(init_yolo)
38
+ self.model.head.initialize_biases(1e-2)
39
+ return self.model
exps/default/yolov3.py ADDED
@@ -0,0 +1,89 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ # -*- coding:utf-8 -*-
3
+ # Copyright (c) Megvii, Inc. and its affiliates.
4
+
5
+ import os
6
+ import torch
7
+ import torch.nn as nn
8
+
9
+ from yolox.exp import Exp as MyExp
10
+
11
+
12
+ class Exp(MyExp):
13
+ def __init__(self):
14
+ super(Exp, self).__init__()
15
+ self.depth = 1.0
16
+ self.width = 1.0
17
+ self.exp_name = os.path.split(os.path.realpath(__file__))[1].split(".")[0]
18
+
19
+ def get_model(self, sublinear=False):
20
+ def init_yolo(M):
21
+ for m in M.modules():
22
+ if isinstance(m, nn.BatchNorm2d):
23
+ m.eps = 1e-3
24
+ m.momentum = 0.03
25
+ if "model" not in self.__dict__:
26
+ from yolox.models import YOLOX, YOLOFPN, YOLOXHead
27
+ backbone = YOLOFPN()
28
+ head = YOLOXHead(self.num_classes, self.width, in_channels=[128, 256, 512], act="lrelu")
29
+ self.model = YOLOX(backbone, head)
30
+ self.model.apply(init_yolo)
31
+ self.model.head.initialize_biases(1e-2)
32
+
33
+ return self.model
34
+
35
+ def get_data_loader(self, batch_size, is_distributed, no_aug=False):
36
+ from data.datasets.cocodataset import COCODataset
37
+ from data.datasets.mosaicdetection import MosaicDetection
38
+ from data.datasets.data_augment import TrainTransform
39
+ from data.datasets.dataloading import YoloBatchSampler, DataLoader, InfiniteSampler
40
+ import torch.distributed as dist
41
+
42
+ dataset = COCODataset(
43
+ data_dir='data/COCO/',
44
+ json_file=self.train_ann,
45
+ img_size=self.input_size,
46
+ preproc=TrainTransform(
47
+ rgb_means=(0.485, 0.456, 0.406),
48
+ std=(0.229, 0.224, 0.225),
49
+ max_labels=50
50
+ ),
51
+ )
52
+
53
+ dataset = MosaicDetection(
54
+ dataset,
55
+ mosaic=not no_aug,
56
+ img_size=self.input_size,
57
+ preproc=TrainTransform(
58
+ rgb_means=(0.485, 0.456, 0.406),
59
+ std=(0.229, 0.224, 0.225),
60
+ max_labels=120
61
+ ),
62
+ degrees=self.degrees,
63
+ translate=self.translate,
64
+ scale=self.scale,
65
+ shear=self.shear,
66
+ perspective=self.perspective,
67
+ )
68
+
69
+ self.dataset = dataset
70
+
71
+ if is_distributed:
72
+ batch_size = batch_size // dist.get_world_size()
73
+ sampler = InfiniteSampler(len(self.dataset), seed=self.seed if self.seed else 0)
74
+ else:
75
+ sampler = torch.utils.data.RandomSampler(self.dataset)
76
+
77
+ batch_sampler = YoloBatchSampler(
78
+ sampler=sampler,
79
+ batch_size=batch_size,
80
+ drop_last=False,
81
+ input_dimension=self.input_size,
82
+ mosaic=not no_aug
83
+ )
84
+
85
+ dataloader_kwargs = {"num_workers": self.data_num_workers, "pin_memory": True}
86
+ dataloader_kwargs["batch_sampler"] = batch_sampler
87
+ train_loader = DataLoader(self.dataset, **dataloader_kwargs)
88
+
89
+ return train_loader
exps/default/yolox_l.py ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ # -*- coding:utf-8 -*-
3
+ # Copyright (c) Megvii, Inc. and its affiliates.
4
+
5
+ import os
6
+
7
+ from yolox.exp import Exp as MyExp
8
+
9
+
10
+ class Exp(MyExp):
11
+ def __init__(self):
12
+ super(Exp, self).__init__()
13
+ self.depth = 1.0
14
+ self.width = 1.0
15
+ self.exp_name = os.path.split(os.path.realpath(__file__))[1].split(".")[0]
exps/default/yolox_m.py ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ # -*- coding:utf-8 -*-
3
+ # Copyright (c) Megvii, Inc. and its affiliates.
4
+
5
+ import os
6
+
7
+ from yolox.exp import Exp as MyExp
8
+
9
+
10
+ class Exp(MyExp):
11
+ def __init__(self):
12
+ super(Exp, self).__init__()
13
+ self.depth = 0.67
14
+ self.width = 0.75
15
+ self.exp_name = os.path.split(os.path.realpath(__file__))[1].split(".")[0]
exps/default/yolox_s.py ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ # -*- coding:utf-8 -*-
3
+ # Copyright (c) Megvii, Inc. and its affiliates.
4
+
5
+ import os
6
+
7
+ from yolox.exp import Exp as MyExp
8
+
9
+
10
+ class Exp(MyExp):
11
+ def __init__(self):
12
+ super(Exp, self).__init__()
13
+ self.depth = 0.33
14
+ self.width = 0.50
15
+ self.exp_name = os.path.split(os.path.realpath(__file__))[1].split(".")[0]
exps/default/yolox_tiny.py ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ # -*- coding:utf-8 -*-
3
+ # Copyright (c) Megvii, Inc. and its affiliates.
4
+
5
+ import os
6
+
7
+ from yolox.exp import Exp as MyExp
8
+
9
+
10
+ class Exp(MyExp):
11
+ def __init__(self):
12
+ super(Exp, self).__init__()
13
+ self.depth = 0.33
14
+ self.width = 0.375
15
+ self.scale = (0.5, 1.5)
16
+ self.random_size = (10, 20)
17
+ self.test_size = (416, 416)
18
+ self.exp_name = os.path.split(os.path.realpath(__file__))[1].split(".")[0]
19
+ self.enable_mixup = False
exps/default/yolox_x.py ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ # -*- coding:utf-8 -*-
3
+ # Copyright (c) Megvii, Inc. and its affiliates.
4
+
5
+ import os
6
+
7
+ from yolox.exp import Exp as MyExp
8
+
9
+
10
+ class Exp(MyExp):
11
+ def __init__(self):
12
+ super(Exp, self).__init__()
13
+ self.depth = 1.33
14
+ self.width = 1.25
15
+ self.exp_name = os.path.split(os.path.realpath(__file__))[1].split(".")[0]
exps/example/mot/yolox_l_mix_det.py ADDED
@@ -0,0 +1,138 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # encoding: utf-8
2
+ import os
3
+ import random
4
+ import torch
5
+ import torch.nn as nn
6
+ import torch.distributed as dist
7
+
8
+ from yolox.exp import Exp as MyExp
9
+ from yolox.data import get_yolox_datadir
10
+
11
+ class Exp(MyExp):
12
+ def __init__(self):
13
+ super(Exp, self).__init__()
14
+ self.num_classes = 1
15
+ self.depth = 1.0
16
+ self.width = 1.0
17
+ self.exp_name = os.path.split(os.path.realpath(__file__))[1].split(".")[0]
18
+ self.train_ann = "train.json"
19
+ self.val_ann = "train.json"
20
+ self.input_size = (800, 1440)
21
+ self.test_size = (800, 1440)
22
+ self.random_size = (18, 32)
23
+ self.max_epoch = 80
24
+ self.print_interval = 20
25
+ self.eval_interval = 5
26
+ self.test_conf = 0.001
27
+ self.nmsthre = 0.7
28
+ self.no_aug_epochs = 10
29
+ self.basic_lr_per_img = 0.001 / 64.0
30
+ self.warmup_epochs = 1
31
+
32
+ def get_data_loader(self, batch_size, is_distributed, no_aug=False):
33
+ from yolox.data import (
34
+ MOTDataset,
35
+ TrainTransform,
36
+ YoloBatchSampler,
37
+ DataLoader,
38
+ InfiniteSampler,
39
+ MosaicDetection,
40
+ )
41
+
42
+ dataset = MOTDataset(
43
+ data_dir=os.path.join(get_yolox_datadir(), "mix_det"),
44
+ json_file=self.train_ann,
45
+ name='',
46
+ img_size=self.input_size,
47
+ preproc=TrainTransform(
48
+ rgb_means=(0.485, 0.456, 0.406),
49
+ std=(0.229, 0.224, 0.225),
50
+ max_labels=500,
51
+ ),
52
+ )
53
+
54
+ dataset = MosaicDetection(
55
+ dataset,
56
+ mosaic=not no_aug,
57
+ img_size=self.input_size,
58
+ preproc=TrainTransform(
59
+ rgb_means=(0.485, 0.456, 0.406),
60
+ std=(0.229, 0.224, 0.225),
61
+ max_labels=1000,
62
+ ),
63
+ degrees=self.degrees,
64
+ translate=self.translate,
65
+ scale=self.scale,
66
+ shear=self.shear,
67
+ perspective=self.perspective,
68
+ enable_mixup=self.enable_mixup,
69
+ )
70
+
71
+ self.dataset = dataset
72
+
73
+ if is_distributed:
74
+ batch_size = batch_size // dist.get_world_size()
75
+
76
+ sampler = InfiniteSampler(
77
+ len(self.dataset), seed=self.seed if self.seed else 0
78
+ )
79
+
80
+ batch_sampler = YoloBatchSampler(
81
+ sampler=sampler,
82
+ batch_size=batch_size,
83
+ drop_last=False,
84
+ input_dimension=self.input_size,
85
+ mosaic=not no_aug,
86
+ )
87
+
88
+ dataloader_kwargs = {"num_workers": self.data_num_workers, "pin_memory": True}
89
+ dataloader_kwargs["batch_sampler"] = batch_sampler
90
+ train_loader = DataLoader(self.dataset, **dataloader_kwargs)
91
+
92
+ return train_loader
93
+
94
+ def get_eval_loader(self, batch_size, is_distributed, testdev=False):
95
+ from yolox.data import MOTDataset, ValTransform
96
+
97
+ valdataset = MOTDataset(
98
+ data_dir=os.path.join(get_yolox_datadir(), "mot"),
99
+ json_file=self.val_ann,
100
+ img_size=self.test_size,
101
+ name='train',
102
+ preproc=ValTransform(
103
+ rgb_means=(0.485, 0.456, 0.406),
104
+ std=(0.229, 0.224, 0.225),
105
+ ),
106
+ )
107
+
108
+ if is_distributed:
109
+ batch_size = batch_size // dist.get_world_size()
110
+ sampler = torch.utils.data.distributed.DistributedSampler(
111
+ valdataset, shuffle=False
112
+ )
113
+ else:
114
+ sampler = torch.utils.data.SequentialSampler(valdataset)
115
+
116
+ dataloader_kwargs = {
117
+ "num_workers": self.data_num_workers,
118
+ "pin_memory": True,
119
+ "sampler": sampler,
120
+ }
121
+ dataloader_kwargs["batch_size"] = batch_size
122
+ val_loader = torch.utils.data.DataLoader(valdataset, **dataloader_kwargs)
123
+
124
+ return val_loader
125
+
126
+ def get_evaluator(self, batch_size, is_distributed, testdev=False):
127
+ from yolox.evaluators import COCOEvaluator
128
+
129
+ val_loader = self.get_eval_loader(batch_size, is_distributed, testdev=testdev)
130
+ evaluator = COCOEvaluator(
131
+ dataloader=val_loader,
132
+ img_size=self.test_size,
133
+ confthre=self.test_conf,
134
+ nmsthre=self.nmsthre,
135
+ num_classes=self.num_classes,
136
+ testdev=testdev,
137
+ )
138
+ return evaluator
exps/example/mot/yolox_m_mix_det.py ADDED
@@ -0,0 +1,138 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # encoding: utf-8
2
+ import os
3
+ import random
4
+ import torch
5
+ import torch.nn as nn
6
+ import torch.distributed as dist
7
+
8
+ from yolox.exp import Exp as MyExp
9
+ from yolox.data import get_yolox_datadir
10
+
11
+ class Exp(MyExp):
12
+ def __init__(self):
13
+ super(Exp, self).__init__()
14
+ self.num_classes = 1
15
+ self.depth = 0.67
16
+ self.width = 0.75
17
+ self.exp_name = os.path.split(os.path.realpath(__file__))[1].split(".")[0]
18
+ self.train_ann = "train.json"
19
+ self.val_ann = "train.json"
20
+ self.input_size = (800, 1440)
21
+ self.test_size = (800, 1440)
22
+ self.random_size = (18, 32)
23
+ self.max_epoch = 80
24
+ self.print_interval = 20
25
+ self.eval_interval = 5
26
+ self.test_conf = 0.001
27
+ self.nmsthre = 0.7
28
+ self.no_aug_epochs = 10
29
+ self.basic_lr_per_img = 0.001 / 64.0
30
+ self.warmup_epochs = 1
31
+
32
+ def get_data_loader(self, batch_size, is_distributed, no_aug=False):
33
+ from yolox.data import (
34
+ MOTDataset,
35
+ TrainTransform,
36
+ YoloBatchSampler,
37
+ DataLoader,
38
+ InfiniteSampler,
39
+ MosaicDetection,
40
+ )
41
+
42
+ dataset = MOTDataset(
43
+ data_dir=os.path.join(get_yolox_datadir(), "mix_det"),
44
+ json_file=self.train_ann,
45
+ name='',
46
+ img_size=self.input_size,
47
+ preproc=TrainTransform(
48
+ rgb_means=(0.485, 0.456, 0.406),
49
+ std=(0.229, 0.224, 0.225),
50
+ max_labels=500,
51
+ ),
52
+ )
53
+
54
+ dataset = MosaicDetection(
55
+ dataset,
56
+ mosaic=not no_aug,
57
+ img_size=self.input_size,
58
+ preproc=TrainTransform(
59
+ rgb_means=(0.485, 0.456, 0.406),
60
+ std=(0.229, 0.224, 0.225),
61
+ max_labels=1000,
62
+ ),
63
+ degrees=self.degrees,
64
+ translate=self.translate,
65
+ scale=self.scale,
66
+ shear=self.shear,
67
+ perspective=self.perspective,
68
+ enable_mixup=self.enable_mixup,
69
+ )
70
+
71
+ self.dataset = dataset
72
+
73
+ if is_distributed:
74
+ batch_size = batch_size // dist.get_world_size()
75
+
76
+ sampler = InfiniteSampler(
77
+ len(self.dataset), seed=self.seed if self.seed else 0
78
+ )
79
+
80
+ batch_sampler = YoloBatchSampler(
81
+ sampler=sampler,
82
+ batch_size=batch_size,
83
+ drop_last=False,
84
+ input_dimension=self.input_size,
85
+ mosaic=not no_aug,
86
+ )
87
+
88
+ dataloader_kwargs = {"num_workers": self.data_num_workers, "pin_memory": True}
89
+ dataloader_kwargs["batch_sampler"] = batch_sampler
90
+ train_loader = DataLoader(self.dataset, **dataloader_kwargs)
91
+
92
+ return train_loader
93
+
94
+ def get_eval_loader(self, batch_size, is_distributed, testdev=False):
95
+ from yolox.data import MOTDataset, ValTransform
96
+
97
+ valdataset = MOTDataset(
98
+ data_dir=os.path.join(get_yolox_datadir(), "mot"),
99
+ json_file=self.val_ann,
100
+ img_size=self.test_size,
101
+ name='train',
102
+ preproc=ValTransform(
103
+ rgb_means=(0.485, 0.456, 0.406),
104
+ std=(0.229, 0.224, 0.225),
105
+ ),
106
+ )
107
+
108
+ if is_distributed:
109
+ batch_size = batch_size // dist.get_world_size()
110
+ sampler = torch.utils.data.distributed.DistributedSampler(
111
+ valdataset, shuffle=False
112
+ )
113
+ else:
114
+ sampler = torch.utils.data.SequentialSampler(valdataset)
115
+
116
+ dataloader_kwargs = {
117
+ "num_workers": self.data_num_workers,
118
+ "pin_memory": True,
119
+ "sampler": sampler,
120
+ }
121
+ dataloader_kwargs["batch_size"] = batch_size
122
+ val_loader = torch.utils.data.DataLoader(valdataset, **dataloader_kwargs)
123
+
124
+ return val_loader
125
+
126
+ def get_evaluator(self, batch_size, is_distributed, testdev=False):
127
+ from yolox.evaluators import COCOEvaluator
128
+
129
+ val_loader = self.get_eval_loader(batch_size, is_distributed, testdev=testdev)
130
+ evaluator = COCOEvaluator(
131
+ dataloader=val_loader,
132
+ img_size=self.test_size,
133
+ confthre=self.test_conf,
134
+ nmsthre=self.nmsthre,
135
+ num_classes=self.num_classes,
136
+ testdev=testdev,
137
+ )
138
+ return evaluator
exps/example/mot/yolox_s_mix_det.py ADDED
@@ -0,0 +1,138 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # encoding: utf-8
2
+ import os
3
+ import random
4
+ import torch
5
+ import torch.nn as nn
6
+ import torch.distributed as dist
7
+
8
+ from yolox.exp import Exp as MyExp
9
+ from yolox.data import get_yolox_datadir
10
+
11
+ class Exp(MyExp):
12
+ def __init__(self):
13
+ super(Exp, self).__init__()
14
+ self.num_classes = 1
15
+ self.depth = 0.33
16
+ self.width = 0.50
17
+ self.exp_name = os.path.split(os.path.realpath(__file__))[1].split(".")[0]
18
+ self.train_ann = "train.json"
19
+ self.val_ann = "train.json"
20
+ self.input_size = (608, 1088)
21
+ self.test_size = (608, 1088)
22
+ self.random_size = (12, 26)
23
+ self.max_epoch = 80
24
+ self.print_interval = 20
25
+ self.eval_interval = 5
26
+ self.test_conf = 0.001
27
+ self.nmsthre = 0.7
28
+ self.no_aug_epochs = 10
29
+ self.basic_lr_per_img = 0.001 / 64.0
30
+ self.warmup_epochs = 1
31
+
32
+ def get_data_loader(self, batch_size, is_distributed, no_aug=False):
33
+ from yolox.data import (
34
+ MOTDataset,
35
+ TrainTransform,
36
+ YoloBatchSampler,
37
+ DataLoader,
38
+ InfiniteSampler,
39
+ MosaicDetection,
40
+ )
41
+
42
+ dataset = MOTDataset(
43
+ data_dir=os.path.join(get_yolox_datadir(), "mix_det"),
44
+ json_file=self.train_ann,
45
+ name='',
46
+ img_size=self.input_size,
47
+ preproc=TrainTransform(
48
+ rgb_means=(0.485, 0.456, 0.406),
49
+ std=(0.229, 0.224, 0.225),
50
+ max_labels=500,
51
+ ),
52
+ )
53
+
54
+ dataset = MosaicDetection(
55
+ dataset,
56
+ mosaic=not no_aug,
57
+ img_size=self.input_size,
58
+ preproc=TrainTransform(
59
+ rgb_means=(0.485, 0.456, 0.406),
60
+ std=(0.229, 0.224, 0.225),
61
+ max_labels=1000,
62
+ ),
63
+ degrees=self.degrees,
64
+ translate=self.translate,
65
+ scale=self.scale,
66
+ shear=self.shear,
67
+ perspective=self.perspective,
68
+ enable_mixup=self.enable_mixup,
69
+ )
70
+
71
+ self.dataset = dataset
72
+
73
+ if is_distributed:
74
+ batch_size = batch_size // dist.get_world_size()
75
+
76
+ sampler = InfiniteSampler(
77
+ len(self.dataset), seed=self.seed if self.seed else 0
78
+ )
79
+
80
+ batch_sampler = YoloBatchSampler(
81
+ sampler=sampler,
82
+ batch_size=batch_size,
83
+ drop_last=False,
84
+ input_dimension=self.input_size,
85
+ mosaic=not no_aug,
86
+ )
87
+
88
+ dataloader_kwargs = {"num_workers": self.data_num_workers, "pin_memory": True}
89
+ dataloader_kwargs["batch_sampler"] = batch_sampler
90
+ train_loader = DataLoader(self.dataset, **dataloader_kwargs)
91
+
92
+ return train_loader
93
+
94
+ def get_eval_loader(self, batch_size, is_distributed, testdev=False):
95
+ from yolox.data import MOTDataset, ValTransform
96
+
97
+ valdataset = MOTDataset(
98
+ data_dir=os.path.join(get_yolox_datadir(), "mot"),
99
+ json_file=self.val_ann,
100
+ img_size=self.test_size,
101
+ name='train',
102
+ preproc=ValTransform(
103
+ rgb_means=(0.485, 0.456, 0.406),
104
+ std=(0.229, 0.224, 0.225),
105
+ ),
106
+ )
107
+
108
+ if is_distributed:
109
+ batch_size = batch_size // dist.get_world_size()
110
+ sampler = torch.utils.data.distributed.DistributedSampler(
111
+ valdataset, shuffle=False
112
+ )
113
+ else:
114
+ sampler = torch.utils.data.SequentialSampler(valdataset)
115
+
116
+ dataloader_kwargs = {
117
+ "num_workers": self.data_num_workers,
118
+ "pin_memory": True,
119
+ "sampler": sampler,
120
+ }
121
+ dataloader_kwargs["batch_size"] = batch_size
122
+ val_loader = torch.utils.data.DataLoader(valdataset, **dataloader_kwargs)
123
+
124
+ return val_loader
125
+
126
+ def get_evaluator(self, batch_size, is_distributed, testdev=False):
127
+ from yolox.evaluators import COCOEvaluator
128
+
129
+ val_loader = self.get_eval_loader(batch_size, is_distributed, testdev=testdev)
130
+ evaluator = COCOEvaluator(
131
+ dataloader=val_loader,
132
+ img_size=self.test_size,
133
+ confthre=self.test_conf,
134
+ nmsthre=self.nmsthre,
135
+ num_classes=self.num_classes,
136
+ testdev=testdev,
137
+ )
138
+ return evaluator
exps/example/mot/yolox_x_ablation.py ADDED
@@ -0,0 +1,138 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # encoding: utf-8
2
+ import os
3
+ import random
4
+ import torch
5
+ import torch.nn as nn
6
+ import torch.distributed as dist
7
+
8
+ from yolox.exp import Exp as MyExp
9
+ from yolox.data import get_yolox_datadir
10
+
11
+ class Exp(MyExp):
12
+ def __init__(self):
13
+ super(Exp, self).__init__()
14
+ self.num_classes = 1
15
+ self.depth = 1.33
16
+ self.width = 1.25
17
+ self.exp_name = os.path.split(os.path.realpath(__file__))[1].split(".")[0]
18
+ self.train_ann = "train.json"
19
+ self.val_ann = "val_half.json"
20
+ self.input_size = (800, 1440)
21
+ self.test_size = (800, 1440)
22
+ self.random_size = (18, 32)
23
+ self.max_epoch = 80
24
+ self.print_interval = 20
25
+ self.eval_interval = 5
26
+ self.test_conf = 0.1
27
+ self.nmsthre = 0.7
28
+ self.no_aug_epochs = 10
29
+ self.basic_lr_per_img = 0.001 / 64.0
30
+ self.warmup_epochs = 1
31
+
32
+ def get_data_loader(self, batch_size, is_distributed, no_aug=False):
33
+ from yolox.data import (
34
+ MOTDataset,
35
+ TrainTransform,
36
+ YoloBatchSampler,
37
+ DataLoader,
38
+ InfiniteSampler,
39
+ MosaicDetection,
40
+ )
41
+
42
+ dataset = MOTDataset(
43
+ data_dir=os.path.join(get_yolox_datadir(), "mix_mot_ch"),
44
+ json_file=self.train_ann,
45
+ name='',
46
+ img_size=self.input_size,
47
+ preproc=TrainTransform(
48
+ rgb_means=(0.485, 0.456, 0.406),
49
+ std=(0.229, 0.224, 0.225),
50
+ max_labels=500,
51
+ ),
52
+ )
53
+
54
+ dataset = MosaicDetection(
55
+ dataset,
56
+ mosaic=not no_aug,
57
+ img_size=self.input_size,
58
+ preproc=TrainTransform(
59
+ rgb_means=(0.485, 0.456, 0.406),
60
+ std=(0.229, 0.224, 0.225),
61
+ max_labels=1000,
62
+ ),
63
+ degrees=self.degrees,
64
+ translate=self.translate,
65
+ scale=self.scale,
66
+ shear=self.shear,
67
+ perspective=self.perspective,
68
+ enable_mixup=self.enable_mixup,
69
+ )
70
+
71
+ self.dataset = dataset
72
+
73
+ if is_distributed:
74
+ batch_size = batch_size // dist.get_world_size()
75
+
76
+ sampler = InfiniteSampler(
77
+ len(self.dataset), seed=self.seed if self.seed else 0
78
+ )
79
+
80
+ batch_sampler = YoloBatchSampler(
81
+ sampler=sampler,
82
+ batch_size=batch_size,
83
+ drop_last=False,
84
+ input_dimension=self.input_size,
85
+ mosaic=not no_aug,
86
+ )
87
+
88
+ dataloader_kwargs = {"num_workers": self.data_num_workers, "pin_memory": True}
89
+ dataloader_kwargs["batch_sampler"] = batch_sampler
90
+ train_loader = DataLoader(self.dataset, **dataloader_kwargs)
91
+
92
+ return train_loader
93
+
94
+ def get_eval_loader(self, batch_size, is_distributed, testdev=False):
95
+ from yolox.data import MOTDataset, ValTransform
96
+
97
+ valdataset = MOTDataset(
98
+ data_dir=os.path.join(get_yolox_datadir(), "mot"),
99
+ json_file=self.val_ann,
100
+ img_size=self.test_size,
101
+ name='train',
102
+ preproc=ValTransform(
103
+ rgb_means=(0.485, 0.456, 0.406),
104
+ std=(0.229, 0.224, 0.225),
105
+ ),
106
+ )
107
+
108
+ if is_distributed:
109
+ batch_size = batch_size // dist.get_world_size()
110
+ sampler = torch.utils.data.distributed.DistributedSampler(
111
+ valdataset, shuffle=False
112
+ )
113
+ else:
114
+ sampler = torch.utils.data.SequentialSampler(valdataset)
115
+
116
+ dataloader_kwargs = {
117
+ "num_workers": self.data_num_workers,
118
+ "pin_memory": True,
119
+ "sampler": sampler,
120
+ }
121
+ dataloader_kwargs["batch_size"] = batch_size
122
+ val_loader = torch.utils.data.DataLoader(valdataset, **dataloader_kwargs)
123
+
124
+ return val_loader
125
+
126
+ def get_evaluator(self, batch_size, is_distributed, testdev=False):
127
+ from yolox.evaluators import COCOEvaluator
128
+
129
+ val_loader = self.get_eval_loader(batch_size, is_distributed, testdev=testdev)
130
+ evaluator = COCOEvaluator(
131
+ dataloader=val_loader,
132
+ img_size=self.test_size,
133
+ confthre=self.test_conf,
134
+ nmsthre=self.nmsthre,
135
+ num_classes=self.num_classes,
136
+ testdev=testdev,
137
+ )
138
+ return evaluator
exps/example/mot/yolox_x_ch.py ADDED
@@ -0,0 +1,138 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # encoding: utf-8
2
+ import os
3
+ import random
4
+ import torch
5
+ import torch.nn as nn
6
+ import torch.distributed as dist
7
+
8
+ from yolox.exp import Exp as MyExp
9
+ from yolox.data import get_yolox_datadir
10
+
11
+ class Exp(MyExp):
12
+ def __init__(self):
13
+ super(Exp, self).__init__()
14
+ self.num_classes = 1
15
+ self.depth = 1.33
16
+ self.width = 1.25
17
+ self.exp_name = os.path.split(os.path.realpath(__file__))[1].split(".")[0]
18
+ self.train_ann = "train.json"
19
+ self.val_ann = "val_half.json"
20
+ self.input_size = (800, 1440)
21
+ self.test_size = (800, 1440)
22
+ self.random_size = (18, 32)
23
+ self.max_epoch = 80
24
+ self.print_interval = 20
25
+ self.eval_interval = 5
26
+ self.test_conf = 0.1
27
+ self.nmsthre = 0.7
28
+ self.no_aug_epochs = 10
29
+ self.basic_lr_per_img = 0.001 / 64.0
30
+ self.warmup_epochs = 1
31
+
32
+ def get_data_loader(self, batch_size, is_distributed, no_aug=False):
33
+ from yolox.data import (
34
+ MOTDataset,
35
+ TrainTransform,
36
+ YoloBatchSampler,
37
+ DataLoader,
38
+ InfiniteSampler,
39
+ MosaicDetection,
40
+ )
41
+
42
+ dataset = MOTDataset(
43
+ data_dir=os.path.join(get_yolox_datadir(), "ch_all"),
44
+ json_file=self.train_ann,
45
+ name='',
46
+ img_size=self.input_size,
47
+ preproc=TrainTransform(
48
+ rgb_means=(0.485, 0.456, 0.406),
49
+ std=(0.229, 0.224, 0.225),
50
+ max_labels=500,
51
+ ),
52
+ )
53
+
54
+ dataset = MosaicDetection(
55
+ dataset,
56
+ mosaic=not no_aug,
57
+ img_size=self.input_size,
58
+ preproc=TrainTransform(
59
+ rgb_means=(0.485, 0.456, 0.406),
60
+ std=(0.229, 0.224, 0.225),
61
+ max_labels=1000,
62
+ ),
63
+ degrees=self.degrees,
64
+ translate=self.translate,
65
+ scale=self.scale,
66
+ shear=self.shear,
67
+ perspective=self.perspective,
68
+ enable_mixup=self.enable_mixup,
69
+ )
70
+
71
+ self.dataset = dataset
72
+
73
+ if is_distributed:
74
+ batch_size = batch_size // dist.get_world_size()
75
+
76
+ sampler = InfiniteSampler(
77
+ len(self.dataset), seed=self.seed if self.seed else 0
78
+ )
79
+
80
+ batch_sampler = YoloBatchSampler(
81
+ sampler=sampler,
82
+ batch_size=batch_size,
83
+ drop_last=False,
84
+ input_dimension=self.input_size,
85
+ mosaic=not no_aug,
86
+ )
87
+
88
+ dataloader_kwargs = {"num_workers": self.data_num_workers, "pin_memory": True}
89
+ dataloader_kwargs["batch_sampler"] = batch_sampler
90
+ train_loader = DataLoader(self.dataset, **dataloader_kwargs)
91
+
92
+ return train_loader
93
+
94
+ def get_eval_loader(self, batch_size, is_distributed, testdev=False):
95
+ from yolox.data import MOTDataset, ValTransform
96
+
97
+ valdataset = MOTDataset(
98
+ data_dir=os.path.join(get_yolox_datadir(), "mot"),
99
+ json_file=self.val_ann,
100
+ img_size=self.test_size,
101
+ name='train',
102
+ preproc=ValTransform(
103
+ rgb_means=(0.485, 0.456, 0.406),
104
+ std=(0.229, 0.224, 0.225),
105
+ ),
106
+ )
107
+
108
+ if is_distributed:
109
+ batch_size = batch_size // dist.get_world_size()
110
+ sampler = torch.utils.data.distributed.DistributedSampler(
111
+ valdataset, shuffle=False
112
+ )
113
+ else:
114
+ sampler = torch.utils.data.SequentialSampler(valdataset)
115
+
116
+ dataloader_kwargs = {
117
+ "num_workers": self.data_num_workers,
118
+ "pin_memory": True,
119
+ "sampler": sampler,
120
+ }
121
+ dataloader_kwargs["batch_size"] = batch_size
122
+ val_loader = torch.utils.data.DataLoader(valdataset, **dataloader_kwargs)
123
+
124
+ return val_loader
125
+
126
+ def get_evaluator(self, batch_size, is_distributed, testdev=False):
127
+ from yolox.evaluators import COCOEvaluator
128
+
129
+ val_loader = self.get_eval_loader(batch_size, is_distributed, testdev=testdev)
130
+ evaluator = COCOEvaluator(
131
+ dataloader=val_loader,
132
+ img_size=self.test_size,
133
+ confthre=self.test_conf,
134
+ nmsthre=self.nmsthre,
135
+ num_classes=self.num_classes,
136
+ testdev=testdev,
137
+ )
138
+ return evaluator
exps/example/mot/yolox_x_mix_det.py ADDED
@@ -0,0 +1,138 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # encoding: utf-8
2
+ import os
3
+ import random
4
+ import torch
5
+ import torch.nn as nn
6
+ import torch.distributed as dist
7
+
8
+ from yolox.exp import Exp as MyExp
9
+ from yolox.data import get_yolox_datadir
10
+
11
+ class Exp(MyExp):
12
+ def __init__(self):
13
+ super(Exp, self).__init__()
14
+ self.num_classes = 1
15
+ self.depth = 1.33
16
+ self.width = 1.25
17
+ self.exp_name = os.path.split(os.path.realpath(__file__))[1].split(".")[0]
18
+ self.train_ann = "train.json"
19
+ self.val_ann = "test.json" # change to train.json when running on training set
20
+ self.input_size = (800, 1440)
21
+ self.test_size = (800, 1440)
22
+ self.random_size = (18, 32)
23
+ self.max_epoch = 80
24
+ self.print_interval = 20
25
+ self.eval_interval = 5
26
+ self.test_conf = 0.001
27
+ self.nmsthre = 0.7
28
+ self.no_aug_epochs = 10
29
+ self.basic_lr_per_img = 0.001 / 64.0
30
+ self.warmup_epochs = 1
31
+
32
+ def get_data_loader(self, batch_size, is_distributed, no_aug=False):
33
+ from yolox.data import (
34
+ MOTDataset,
35
+ TrainTransform,
36
+ YoloBatchSampler,
37
+ DataLoader,
38
+ InfiniteSampler,
39
+ MosaicDetection,
40
+ )
41
+
42
+ dataset = MOTDataset(
43
+ data_dir=os.path.join(get_yolox_datadir(), "mix_det"),
44
+ json_file=self.train_ann,
45
+ name='',
46
+ img_size=self.input_size,
47
+ preproc=TrainTransform(
48
+ rgb_means=(0.485, 0.456, 0.406),
49
+ std=(0.229, 0.224, 0.225),
50
+ max_labels=500,
51
+ ),
52
+ )
53
+
54
+ dataset = MosaicDetection(
55
+ dataset,
56
+ mosaic=not no_aug,
57
+ img_size=self.input_size,
58
+ preproc=TrainTransform(
59
+ rgb_means=(0.485, 0.456, 0.406),
60
+ std=(0.229, 0.224, 0.225),
61
+ max_labels=1000,
62
+ ),
63
+ degrees=self.degrees,
64
+ translate=self.translate,
65
+ scale=self.scale,
66
+ shear=self.shear,
67
+ perspective=self.perspective,
68
+ enable_mixup=self.enable_mixup,
69
+ )
70
+
71
+ self.dataset = dataset
72
+
73
+ if is_distributed:
74
+ batch_size = batch_size // dist.get_world_size()
75
+
76
+ sampler = InfiniteSampler(
77
+ len(self.dataset), seed=self.seed if self.seed else 0
78
+ )
79
+
80
+ batch_sampler = YoloBatchSampler(
81
+ sampler=sampler,
82
+ batch_size=batch_size,
83
+ drop_last=False,
84
+ input_dimension=self.input_size,
85
+ mosaic=not no_aug,
86
+ )
87
+
88
+ dataloader_kwargs = {"num_workers": self.data_num_workers, "pin_memory": True}
89
+ dataloader_kwargs["batch_sampler"] = batch_sampler
90
+ train_loader = DataLoader(self.dataset, **dataloader_kwargs)
91
+
92
+ return train_loader
93
+
94
+ def get_eval_loader(self, batch_size, is_distributed, testdev=False):
95
+ from yolox.data import MOTDataset, ValTransform
96
+
97
+ valdataset = MOTDataset(
98
+ data_dir=os.path.join(get_yolox_datadir(), "mot"),
99
+ json_file=self.val_ann,
100
+ img_size=self.test_size,
101
+ name='test', # change to train when running on training set
102
+ preproc=ValTransform(
103
+ rgb_means=(0.485, 0.456, 0.406),
104
+ std=(0.229, 0.224, 0.225),
105
+ ),
106
+ )
107
+
108
+ if is_distributed:
109
+ batch_size = batch_size // dist.get_world_size()
110
+ sampler = torch.utils.data.distributed.DistributedSampler(
111
+ valdataset, shuffle=False
112
+ )
113
+ else:
114
+ sampler = torch.utils.data.SequentialSampler(valdataset)
115
+
116
+ dataloader_kwargs = {
117
+ "num_workers": self.data_num_workers,
118
+ "pin_memory": True,
119
+ "sampler": sampler,
120
+ }
121
+ dataloader_kwargs["batch_size"] = batch_size
122
+ val_loader = torch.utils.data.DataLoader(valdataset, **dataloader_kwargs)
123
+
124
+ return val_loader
125
+
126
+ def get_evaluator(self, batch_size, is_distributed, testdev=False):
127
+ from yolox.evaluators import COCOEvaluator
128
+
129
+ val_loader = self.get_eval_loader(batch_size, is_distributed, testdev=testdev)
130
+ evaluator = COCOEvaluator(
131
+ dataloader=val_loader,
132
+ img_size=self.test_size,
133
+ confthre=self.test_conf,
134
+ nmsthre=self.nmsthre,
135
+ num_classes=self.num_classes,
136
+ testdev=testdev,
137
+ )
138
+ return evaluator
exps/example/mot/yolox_x_mix_mot20_ch.py ADDED
@@ -0,0 +1,139 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # encoding: utf-8
2
+ import os
3
+ import random
4
+ import torch
5
+ import torch.nn as nn
6
+ import torch.distributed as dist
7
+
8
+ from yolox.exp import Exp as MyExp
9
+ from yolox.data import get_yolox_datadir
10
+
11
+ class Exp(MyExp):
12
+ def __init__(self):
13
+ super(Exp, self).__init__()
14
+ self.num_classes = 1
15
+ self.depth = 1.33
16
+ self.width = 1.25
17
+ self.exp_name = os.path.split(os.path.realpath(__file__))[1].split(".")[0]
18
+ self.train_ann = "train.json"
19
+ self.val_ann = "test.json" # change to train.json when running on training set
20
+ self.input_size = (896, 1600)
21
+ self.test_size = (896, 1600)
22
+ #self.test_size = (736, 1920)
23
+ self.random_size = (20, 36)
24
+ self.max_epoch = 80
25
+ self.print_interval = 20
26
+ self.eval_interval = 5
27
+ self.test_conf = 0.001
28
+ self.nmsthre = 0.7
29
+ self.no_aug_epochs = 10
30
+ self.basic_lr_per_img = 0.001 / 64.0
31
+ self.warmup_epochs = 1
32
+
33
+ def get_data_loader(self, batch_size, is_distributed, no_aug=False):
34
+ from yolox.data import (
35
+ MOTDataset,
36
+ TrainTransform,
37
+ YoloBatchSampler,
38
+ DataLoader,
39
+ InfiniteSampler,
40
+ MosaicDetection,
41
+ )
42
+
43
+ dataset = MOTDataset(
44
+ data_dir=os.path.join(get_yolox_datadir(), "mix_mot20_ch"),
45
+ json_file=self.train_ann,
46
+ name='',
47
+ img_size=self.input_size,
48
+ preproc=TrainTransform(
49
+ rgb_means=(0.485, 0.456, 0.406),
50
+ std=(0.229, 0.224, 0.225),
51
+ max_labels=600,
52
+ ),
53
+ )
54
+
55
+ dataset = MosaicDetection(
56
+ dataset,
57
+ mosaic=not no_aug,
58
+ img_size=self.input_size,
59
+ preproc=TrainTransform(
60
+ rgb_means=(0.485, 0.456, 0.406),
61
+ std=(0.229, 0.224, 0.225),
62
+ max_labels=1200,
63
+ ),
64
+ degrees=self.degrees,
65
+ translate=self.translate,
66
+ scale=self.scale,
67
+ shear=self.shear,
68
+ perspective=self.perspective,
69
+ enable_mixup=self.enable_mixup,
70
+ )
71
+
72
+ self.dataset = dataset
73
+
74
+ if is_distributed:
75
+ batch_size = batch_size // dist.get_world_size()
76
+
77
+ sampler = InfiniteSampler(
78
+ len(self.dataset), seed=self.seed if self.seed else 0
79
+ )
80
+
81
+ batch_sampler = YoloBatchSampler(
82
+ sampler=sampler,
83
+ batch_size=batch_size,
84
+ drop_last=False,
85
+ input_dimension=self.input_size,
86
+ mosaic=not no_aug,
87
+ )
88
+
89
+ dataloader_kwargs = {"num_workers": self.data_num_workers, "pin_memory": True}
90
+ dataloader_kwargs["batch_sampler"] = batch_sampler
91
+ train_loader = DataLoader(self.dataset, **dataloader_kwargs)
92
+
93
+ return train_loader
94
+
95
+ def get_eval_loader(self, batch_size, is_distributed, testdev=False):
96
+ from yolox.data import MOTDataset, ValTransform
97
+
98
+ valdataset = MOTDataset(
99
+ data_dir=os.path.join(get_yolox_datadir(), "MOT20"),
100
+ json_file=self.val_ann,
101
+ img_size=self.test_size,
102
+ name='test', # change to train when running on training set
103
+ preproc=ValTransform(
104
+ rgb_means=(0.485, 0.456, 0.406),
105
+ std=(0.229, 0.224, 0.225),
106
+ ),
107
+ )
108
+
109
+ if is_distributed:
110
+ batch_size = batch_size // dist.get_world_size()
111
+ sampler = torch.utils.data.distributed.DistributedSampler(
112
+ valdataset, shuffle=False
113
+ )
114
+ else:
115
+ sampler = torch.utils.data.SequentialSampler(valdataset)
116
+
117
+ dataloader_kwargs = {
118
+ "num_workers": self.data_num_workers,
119
+ "pin_memory": True,
120
+ "sampler": sampler,
121
+ }
122
+ dataloader_kwargs["batch_size"] = batch_size
123
+ val_loader = torch.utils.data.DataLoader(valdataset, **dataloader_kwargs)
124
+
125
+ return val_loader
126
+
127
+ def get_evaluator(self, batch_size, is_distributed, testdev=False):
128
+ from yolox.evaluators import COCOEvaluator
129
+
130
+ val_loader = self.get_eval_loader(batch_size, is_distributed, testdev=testdev)
131
+ evaluator = COCOEvaluator(
132
+ dataloader=val_loader,
133
+ img_size=self.test_size,
134
+ confthre=self.test_conf,
135
+ nmsthre=self.nmsthre,
136
+ num_classes=self.num_classes,
137
+ testdev=testdev,
138
+ )
139
+ return evaluator
exps/example/mot/yolox_x_mot17_half.py ADDED
@@ -0,0 +1,138 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # encoding: utf-8
2
+ import os
3
+ import random
4
+ import torch
5
+ import torch.nn as nn
6
+ import torch.distributed as dist
7
+
8
+ from yolox.exp import Exp as MyExp
9
+ from yolox.data import get_yolox_datadir
10
+
11
+ class Exp(MyExp):
12
+ def __init__(self):
13
+ super(Exp, self).__init__()
14
+ self.num_classes = 1
15
+ self.depth = 1.33
16
+ self.width = 1.25
17
+ self.exp_name = os.path.split(os.path.realpath(__file__))[1].split(".")[0]
18
+ self.train_ann = "train.json"
19
+ self.val_ann = "val_half.json"
20
+ self.input_size = (800, 1440)
21
+ self.test_size = (800, 1440)
22
+ self.random_size = (18, 32)
23
+ self.max_epoch = 80
24
+ self.print_interval = 20
25
+ self.eval_interval = 5
26
+ self.test_conf = 0.1
27
+ self.nmsthre = 0.7
28
+ self.no_aug_epochs = 10
29
+ self.basic_lr_per_img = 0.001 / 64.0
30
+ self.warmup_epochs = 1
31
+
32
+ def get_data_loader(self, batch_size, is_distributed, no_aug=False):
33
+ from yolox.data import (
34
+ MOTDataset,
35
+ TrainTransform,
36
+ YoloBatchSampler,
37
+ DataLoader,
38
+ InfiniteSampler,
39
+ MosaicDetection,
40
+ )
41
+
42
+ dataset = MOTDataset(
43
+ data_dir=os.path.join(get_yolox_datadir(), "mot"),
44
+ json_file=self.train_ann,
45
+ name='train',
46
+ img_size=self.input_size,
47
+ preproc=TrainTransform(
48
+ rgb_means=(0.485, 0.456, 0.406),
49
+ std=(0.229, 0.224, 0.225),
50
+ max_labels=500,
51
+ ),
52
+ )
53
+
54
+ dataset = MosaicDetection(
55
+ dataset,
56
+ mosaic=not no_aug,
57
+ img_size=self.input_size,
58
+ preproc=TrainTransform(
59
+ rgb_means=(0.485, 0.456, 0.406),
60
+ std=(0.229, 0.224, 0.225),
61
+ max_labels=1000,
62
+ ),
63
+ degrees=self.degrees,
64
+ translate=self.translate,
65
+ scale=self.scale,
66
+ shear=self.shear,
67
+ perspective=self.perspective,
68
+ enable_mixup=self.enable_mixup,
69
+ )
70
+
71
+ self.dataset = dataset
72
+
73
+ if is_distributed:
74
+ batch_size = batch_size // dist.get_world_size()
75
+
76
+ sampler = InfiniteSampler(
77
+ len(self.dataset), seed=self.seed if self.seed else 0
78
+ )
79
+
80
+ batch_sampler = YoloBatchSampler(
81
+ sampler=sampler,
82
+ batch_size=batch_size,
83
+ drop_last=False,
84
+ input_dimension=self.input_size,
85
+ mosaic=not no_aug,
86
+ )
87
+
88
+ dataloader_kwargs = {"num_workers": self.data_num_workers, "pin_memory": True}
89
+ dataloader_kwargs["batch_sampler"] = batch_sampler
90
+ train_loader = DataLoader(self.dataset, **dataloader_kwargs)
91
+
92
+ return train_loader
93
+
94
+ def get_eval_loader(self, batch_size, is_distributed, testdev=False):
95
+ from yolox.data import MOTDataset, ValTransform
96
+
97
+ valdataset = MOTDataset(
98
+ data_dir=os.path.join(get_yolox_datadir(), "mot"),
99
+ json_file=self.val_ann,
100
+ img_size=self.test_size,
101
+ name='train',
102
+ preproc=ValTransform(
103
+ rgb_means=(0.485, 0.456, 0.406),
104
+ std=(0.229, 0.224, 0.225),
105
+ ),
106
+ )
107
+
108
+ if is_distributed:
109
+ batch_size = batch_size // dist.get_world_size()
110
+ sampler = torch.utils.data.distributed.DistributedSampler(
111
+ valdataset, shuffle=False
112
+ )
113
+ else:
114
+ sampler = torch.utils.data.SequentialSampler(valdataset)
115
+
116
+ dataloader_kwargs = {
117
+ "num_workers": self.data_num_workers,
118
+ "pin_memory": True,
119
+ "sampler": sampler,
120
+ }
121
+ dataloader_kwargs["batch_size"] = batch_size
122
+ val_loader = torch.utils.data.DataLoader(valdataset, **dataloader_kwargs)
123
+
124
+ return val_loader
125
+
126
+ def get_evaluator(self, batch_size, is_distributed, testdev=False):
127
+ from yolox.evaluators import COCOEvaluator
128
+
129
+ val_loader = self.get_eval_loader(batch_size, is_distributed, testdev=testdev)
130
+ evaluator = COCOEvaluator(
131
+ dataloader=val_loader,
132
+ img_size=self.test_size,
133
+ confthre=self.test_conf,
134
+ nmsthre=self.nmsthre,
135
+ num_classes=self.num_classes,
136
+ testdev=testdev,
137
+ )
138
+ return evaluator
requirements.txt ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # TODO: Update with exact module version
2
+ numpy
3
+ torch>=1.7
4
+ opencv_python
5
+ loguru
6
+ scikit-image
7
+ tqdm
8
+ torchvision==0.10.0
9
+ Pillow
10
+ thop
11
+ ninja
12
+ tabulate
13
+ tensorboard
14
+ lap
15
+ motmetrics
16
+ filterpy
17
+ h5py
18
+
19
+ # verified versions
20
+ onnx==1.8.1
21
+ onnxruntime==1.8.0
22
+ onnx-simplifier==0.3.5
setup.cfg ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [isort]
2
+ line_length = 100
3
+ multi_line_output = 3
4
+ balanced_wrapping = True
5
+ known_standard_library = setuptools
6
+ known_third_party = tqdm,loguru
7
+ known_data_processing = cv2,numpy,scipy,PIL,matplotlib,scikit_image
8
+ known_datasets = pycocotools
9
+ known_deeplearning = torch,torchvision,caffe2,onnx,apex,timm,thop,torch2trt,tensorrt,openvino,onnxruntime
10
+ known_myself = yolox
11
+ sections = FUTURE,STDLIB,THIRDPARTY,data_processing,datasets,deeplearning,myself,FIRSTPARTY,LOCALFOLDER
12
+ no_lines_before=STDLIB,THIRDPARTY,datasets
13
+ default_section = FIRSTPARTY
14
+
15
+ [flake8]
16
+ max-line-length = 100
17
+ max-complexity = 18
18
+ exclude = __init__.py