OpenCVコンパイルと Python Darknet - JETSON NANO 開発者キット その4
Darknet の Python スクリプトを、WEBカメラで試したい。
OpenCV
Jetson pack には、opencv 3.3 が有効化されているけれども、Pythonから呼び出す方法がわからなかったので、コンパイルしました。
準備
デフォルトの設定のままだと、RAMが不足するらしい。
スワップを作っておきます。
JETSON NANO 開発者キット を試す その3 - 機械学習備忘録
で、起動時に 6G のスワップメモリを確保しています。
自動コンパイル&インストールスクリプト
JEP/script at master · AastaNV/JEP · GitHub
こちから、 install_opencv4.0.0_Nano.sh
を取得します。
改変
Version 4.0 から 4.1へ変更し、PKGCONFIG
を吐き出すようにします。
改変作業
version の 4.0 の文字列を全て 4.1 に変更。
make の引数に、
-D OPENCV_GENERATE_PKGCONFIG=ON
を追加。
そして、
$ mkdir opencv $ sh install_opencv4.0.0_Nano.sh opencv ... $ python3 -c "import cv2; print (cv2.__version__)" 4.1.0
4時間ほどかかりました。
Darknet
インストール
通常パッケージではなく、こっちを使う。
こことの関連は、調査中
https://github.com/pjreddie/darknet
pkg-config --modversion opencv
ldd darknet
などすると、見当たらないので、.bashrc
に path を追加し、
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib
ファイル名を合わせる。(シンボリックリンクの方が良いかも)
$ cd /usr/local/lib/pkgconfig/ $ sudo cp opencv4.pc opencv.pc
Python から Darknet を使用する
めも (要整理)
疑問
cap.set(cv2.CAP_PROP_FRAME_WIDTH, 1280)
しても、
cap.get(cap.set(cv2.CAP_PROP_FRAME_WIDTH) すると、デフォルト値から変わっていない。
だが、
ret, frame = cap.read() print( frame.shape )
すると、ちゃんと変わっている。なんだろうか。
Raspberry pi 4 model B を試す
RPI4 なら、いろいろできるかもしれない?
試してみます。
Tensorflow を動かす
$ sudo apt install libatlas-base-dev
$ pip3 install tensorflow --user
動作確認まで
$ python3 Python 3.7.3 (default, Apr 3 2019, 05:39:12) [GCC 8.2.0] on linux Type "help", "copyright", "credits" or "license" for more information. >>> import tensorflow as tf WARNING: Logging before flag parsing goes to stderr. W0711 11:25:13.680072 3069655760 deprecation_wrapper.py:118] From /home/kiyo/.local/lib/python3.7/site-packages/tensorflow/__init__.py:98: The name tf.AUTO_REUSE is deprecated. Please use tf.compat.v1.AUTO_REUSE instead. W0711 11:25:13.680785 3069655760 deprecation_wrapper.py:118] From /home/kiyo/.local/lib/python3.7/site-packages/tensorflow/__init__.py:98: The name tf.AttrValue is deprecated. Please use tf.compat.v1.AttrValue instead. W0711 11:25:13.681129 3069655760 deprecation_wrapper.py:118] From /home/kiyo/.local/lib/python3.7/site-packages/tensorflow/__init__.py:98: The name tf.COMPILER_VERSION is deprecated. Please use tf.version.COMPILER_VERSION instead. W0711 11:25:13.681412 3069655760 deprecation_wrapper.py:118] From /home/kiyo/.local/lib/python3.7/site-packages/tensorflow/__init__.py:98: The name tf.CXX11_ABI_FLAG is deprecated. Please use tf.sysconfig.CXX11_ABI_FLAG instead. W0711 11:25:13.681687 3069655760 deprecation_wrapper.py:118] From /home/kiyo/.local/lib/python3.7/site-packages/tensorflow/__init__.py:98: The name tf.ConditionalAccumulator is deprecated. Please use tf.compat.v1.ConditionalAccumulator instead. >>> hello = tf.constant('Hello, TensorFlow!') >>> sess = tf.Session() >>> print(sess.run(hello)) b'Hello, TensorFlow!' >>>
Keras Mnist Fashion を試す
試しました。 動きました。
Darknet
$ git clone https://github.com/pjreddie/darknet $ cd darknet $ make $ ./darknet detector test cfg/coco.data cfg/yolov2.cfg yolov2.weights data/person.jpg layer filters size input output 0 conv 32 3 x 3 / 1 608 x 608 x 3 -> 608 x 608 x 32 0.639 BFLOPs 1 max 2 x 2 / 2 608 x 608 x 32 -> 304 x 304 x 32 2 conv 64 3 x 3 / 1 304 x 304 x 32 -> 304 x 304 x 64 3.407 BFLOPs 3 max 2 x 2 / 2 304 x 304 x 64 -> 152 x 152 x 64 4 conv 128 3 x 3 / 1 152 x 152 x 64 -> 152 x 152 x 128 3.407 BFLOPs 5 conv 64 1 x 1 / 1 152 x 152 x 128 -> 152 x 152 x 64 0.379 BFLOPs 6 conv 128 3 x 3 / 1 152 x 152 x 64 -> 152 x 152 x 128 3.407 BFLOPs 7 max 2 x 2 / 2 152 x 152 x 128 -> 76 x 76 x 128 8 conv 256 3 x 3 / 1 76 x 76 x 128 -> 76 x 76 x 256 3.407 BFLOPs 9 conv 128 1 x 1 / 1 76 x 76 x 256 -> 76 x 76 x 128 0.379 BFLOPs 10 conv 256 3 x 3 / 1 76 x 76 x 128 -> 76 x 76 x 256 3.407 BFLOPs 11 max 2 x 2 / 2 76 x 76 x 256 -> 38 x 38 x 256 12 conv 512 3 x 3 / 1 38 x 38 x 256 -> 38 x 38 x 512 3.407 BFLOPs 13 conv 256 1 x 1 / 1 38 x 38 x 512 -> 38 x 38 x 256 0.379 BFLOPs 14 conv 512 3 x 3 / 1 38 x 38 x 256 -> 38 x 38 x 512 3.407 BFLOPs 15 conv 256 1 x 1 / 1 38 x 38 x 512 -> 38 x 38 x 256 0.379 BFLOPs 16 conv 512 3 x 3 / 1 38 x 38 x 256 -> 38 x 38 x 512 3.407 BFLOPs 17 max 2 x 2 / 2 38 x 38 x 512 -> 19 x 19 x 512 18 conv 1024 3 x 3 / 1 19 x 19 x 512 -> 19 x 19 x1024 3.407 BFLOPs 19 conv 512 1 x 1 / 1 19 x 19 x1024 -> 19 x 19 x 512 0.379 BFLOPs 20 conv 1024 3 x 3 / 1 19 x 19 x 512 -> 19 x 19 x1024 3.407 BFLOPs 21 conv 512 1 x 1 / 1 19 x 19 x1024 -> 19 x 19 x 512 0.379 BFLOPs 22 conv 1024 3 x 3 / 1 19 x 19 x 512 -> 19 x 19 x1024 3.407 BFLOPs 23 conv 1024 3 x 3 / 1 19 x 19 x1024 -> 19 x 19 x1024 6.814 BFLOPs 24 conv 1024 3 x 3 / 1 19 x 19 x1024 -> 19 x 19 x1024 6.814 BFLOPs 25 route 16 26 conv 64 1 x 1 / 1 38 x 38 x 512 -> 38 x 38 x 64 0.095 BFLOPs 27 reorg / 2 38 x 38 x 64 -> 19 x 19 x 256 28 route 27 24 29 conv 1024 3 x 3 / 1 19 x 19 x1280 -> 19 x 19 x1024 8.517 BFLOPs 30 conv 425 1 x 1 / 1 19 x 19 x1024 -> 19 x 19 x 425 0.314 BFLOPs 31 detection mask_scale: Using default '1.000000' Loading weights from yolov2.weights...Done! data/person.jpg: Predicted in 71.214195 seconds. horse: 82% dog: 86% person: 86% $ wget https://pjreddie.com/media/files/yolov2-tiny-voc.weights $ ./darknet detector test cfg/voc.data cfg/yolov2-tiny-voc.cfg yolov2-tiny-voc.weights data/dog.jpg
なかなか遅いですね。
Darknet nnpack
python3 に書き換えて実行するのだが、先に、
sudo apt-get -y install re2c
しておく。
コンパイルまで
$ sudo pip3 install --upgrade git+https://github.com/Maratyszcza/PeachPy $ sudo pip3 install --upgrade git+https://github.com/Maratyszcza/confu $ cd $ git clone https://github.com/ninja-build/ninja.git $ cd ninja $ git checkout release $ ./configure.py --bootstrap $ export NINJA_PATH=$PWD $ sudo apt-get install clang $ Install NNPACK-darknet $ cd $ git clone https://github.com/digitalbrain79/NNPACK-darknet.git $ cd NNPACK-darknet $ confu setup $ python3 ./configure.py --backend auto $ $NINJA_PATH/ninja $sudo cp -a lib/* /usr/lib/ $sudo cp include/nnpack.h /usr/include/ $sudo cp deps/pthreadpool/include/pthreadpool.h /usr/include/ $Build darknet-nnpack $ cd $ git clone https://github.com/digitalbrain79/darknet-nnpack.git $ cd darknet-nnpack $ make
weight ファイル
weight ファイルを取得する。
yolov3 はここ。
yolov2 はここ。
実行
$ ./darknet detector test cfg/coco.data cfg/yolov2.cfg yolov2.weights data/person.j pg layer filters size input output 0 conv 32 3 x 3 / 1 608 x 608 x 3 -> 608 x 608 x 32 0.639 BFLOPs 1 max 2 x 2 / 2 608 x 608 x 32 -> 304 x 304 x 32 2 conv 64 3 x 3 / 1 304 x 304 x 32 -> 304 x 304 x 64 3.407 BFLOPs 3 max 2 x 2 / 2 304 x 304 x 64 -> 152 x 152 x 64 4 conv 128 3 x 3 / 1 152 x 152 x 64 -> 152 x 152 x 128 3.407 BFLOPs 5 conv 64 1 x 1 / 1 152 x 152 x 128 -> 152 x 152 x 64 0.379 BFLOPs 6 conv 128 3 x 3 / 1 152 x 152 x 64 -> 152 x 152 x 128 3.407 BFLOPs 7 max 2 x 2 / 2 152 x 152 x 128 -> 76 x 76 x 128 8 conv 256 3 x 3 / 1 76 x 76 x 128 -> 76 x 76 x 256 3.407 BFLOPs 9 conv 128 1 x 1 / 1 76 x 76 x 256 -> 76 x 76 x 128 0.379 BFLOPs 10 conv 256 3 x 3 / 1 76 x 76 x 128 -> 76 x 76 x 256 3.407 BFLOPs 11 max 2 x 2 / 2 76 x 76 x 256 -> 38 x 38 x 256 12 conv 512 3 x 3 / 1 38 x 38 x 256 -> 38 x 38 x 512 3.407 BFLOPs 13 conv 256 1 x 1 / 1 38 x 38 x 512 -> 38 x 38 x 256 0.379 BFLOPs 14 conv 512 3 x 3 / 1 38 x 38 x 256 -> 38 x 38 x 512 3.407 BFLOPs 15 conv 256 1 x 1 / 1 38 x 38 x 512 -> 38 x 38 x 256 0.379 BFLOPs 16 conv 512 3 x 3 / 1 38 x 38 x 256 -> 38 x 38 x 512 3.407 BFLOPs 17 max 2 x 2 / 2 38 x 38 x 512 -> 19 x 19 x 512 18 conv 1024 3 x 3 / 1 19 x 19 x 512 -> 19 x 19 x1024 3.407 BFLOPs 19 conv 512 1 x 1 / 1 19 x 19 x1024 -> 19 x 19 x 512 0.379 BFLOPs 20 conv 1024 3 x 3 / 1 19 x 19 x 512 -> 19 x 19 x1024 3.407 BFLOPs 21 conv 512 1 x 1 / 1 19 x 19 x1024 -> 19 x 19 x 512 0.379 BFLOPs 22 conv 1024 3 x 3 / 1 19 x 19 x 512 -> 19 x 19 x1024 3.407 BFLOPs 23 conv 1024 3 x 3 / 1 19 x 19 x1024 -> 19 x 19 x1024 6.814 BFLOPs 24 conv 1024 3 x 3 / 1 19 x 19 x1024 -> 19 x 19 x1024 6.814 BFLOPs 25 route 16 26 conv 64 1 x 1 / 1 38 x 38 x 512 -> 38 x 38 x 64 0.095 BFLOPs 27 reorg / 2 38 x 38 x 64 -> 19 x 19 x 256 28 route 27 24 29 conv 1024 3 x 3 / 1 19 x 19 x1280 -> 19 x 19 x1024 8.517 BFLOPs 30 conv 425 1 x 1 / 1 19 x 19 x1024 -> 19 x 19 x 425 0.314 BFLOPs 31 detection mask_scale: Using default '1.000000' Loading weights from yolov2.weights...Done! data/person.jpg: Predicted in 4.701867 seconds. horse: 82% dog: 86% person: 86% $ ./darknet detector test cfg/coco.data cfg/yolov2-tiny.cfg yolov2-tiny.weights data/person.jpg layer filters size input output 0 conv 16 3 x 3 / 1 416 x 416 x 3 -> 416 x 416 x 16 0.150 BFLOPs 1 max 2 x 2 / 2 416 x 416 x 16 -> 208 x 208 x 16 2 conv 32 3 x 3 / 1 208 x 208 x 16 -> 208 x 208 x 32 0.399 BFLOPs 3 max 2 x 2 / 2 208 x 208 x 32 -> 104 x 104 x 32 4 conv 64 3 x 3 / 1 104 x 104 x 32 -> 104 x 104 x 64 0.399 BFLOPs 5 max 2 x 2 / 2 104 x 104 x 64 -> 52 x 52 x 64 6 conv 128 3 x 3 / 1 52 x 52 x 64 -> 52 x 52 x 128 0.399 BFLOPs 7 max 2 x 2 / 2 52 x 52 x 128 -> 26 x 26 x 128 8 conv 256 3 x 3 / 1 26 x 26 x 128 -> 26 x 26 x 256 0.399 BFLOPs 9 max 2 x 2 / 2 26 x 26 x 256 -> 13 x 13 x 256 10 conv 512 3 x 3 / 1 13 x 13 x 256 -> 13 x 13 x 512 0.399 BFLOPs 11 max 2 x 2 / 1 13 x 13 x 512 -> 13 x 13 x 512 12 conv 1024 3 x 3 / 1 13 x 13 x 512 -> 13 x 13 x1024 1.595 BFLOPs 13 conv 512 3 x 3 / 1 13 x 13 x1024 -> 13 x 13 x 512 1.595 BFLOPs 14 conv 425 1 x 1 / 1 13 x 13 x 512 -> 13 x 13 x 425 0.074 BFLOPs 15 detection mask_scale: Using default '1.000000' Loading weights from yolov2-tiny.weights...Done! data/person.jpg: Predicted in 0.652822 seconds. horse: 92% dog: 92% person: 91% $ ./darknet detector test cfg/coco.data cfg/yolov3-tiny.cfg yolov3-tiny.weights data/person.jpg layer filters size input output 0 conv 16 3 x 3 / 1 416 x 416 x 3 -> 416 x 416 x 16 0.150 BFLOPs 1 max 2 x 2 / 2 416 x 416 x 16 -> 208 x 208 x 16 2 conv 32 3 x 3 / 1 208 x 208 x 16 -> 208 x 208 x 32 0.399 BFLOPs 3 max 2 x 2 / 2 208 x 208 x 32 -> 104 x 104 x 32 4 conv 64 3 x 3 / 1 104 x 104 x 32 -> 104 x 104 x 64 0.399 BFLOPs 5 max 2 x 2 / 2 104 x 104 x 64 -> 52 x 52 x 64 6 conv 128 3 x 3 / 1 52 x 52 x 64 -> 52 x 52 x 128 0.399 BFLOPs 7 max 2 x 2 / 2 52 x 52 x 128 -> 26 x 26 x 128 8 conv 256 3 x 3 / 1 26 x 26 x 128 -> 26 x 26 x 256 0.399 BFLOPs 9 max 2 x 2 / 2 26 x 26 x 256 -> 13 x 13 x 256 10 conv 512 3 x 3 / 1 13 x 13 x 256 -> 13 x 13 x 512 0.399 BFLOPs 11 max 2 x 2 / 1 13 x 13 x 512 -> 13 x 13 x 512 12 conv 1024 3 x 3 / 1 13 x 13 x 512 -> 13 x 13 x1024 1.595 BFLOPs 13 conv 256 1 x 1 / 1 13 x 13 x1024 -> 13 x 13 x 256 0.089 BFLOPs 14 conv 512 3 x 3 / 1 13 x 13 x 256 -> 13 x 13 x 512 0.399 BFLOPs 15 conv 255 1 x 1 / 1 13 x 13 x 512 -> 13 x 13 x 255 0.044 BFLOPs 16 yolo 17 route 13 18 conv 128 1 x 1 / 1 13 x 13 x 256 -> 13 x 13 x 128 0.011 BFLOPs 19 upsample 2x 13 x 13 x 128 -> 26 x 26 x 128 20 route 19 8 21 conv 256 3 x 3 / 1 26 x 26 x 384 -> 26 x 26 x 256 1.196 BFLOPs 22 conv 255 1 x 1 / 1 26 x 26 x 256 -> 26 x 26 x 255 0.088 BFLOPs 23 yolo Loading weights from yolov3-tiny.weights...Done! data/person.jpg: Predicted in 0.670556 seconds. horse: 94% dog: 91% dog: 90% person: 86%
なお、yolov3 は、 Segmentation fault
でした。
WEBカメラ
demo で動くし、映像モデルし、エラーも吐かないが、何もディレクトしない。
なんだろうか?
4A起動給電やSwapメモリ, クロック数の変更, CUDAサンプル実行 - JETSON NANO 開発者キット その3
JETSON NANO 開発者キット を試す その3
その他拡張
この Jetson hacks というサイトを見ると、いろいろ情報が出てくる。公式さいとなのかな?
5V4A
5V4A での動作方法について書いてある。
Jetson Nano - Use More Power! - JetsonHacks
スワップメモリの作成
Jetson Nano - Use More Memory! - JetsonHacks
$ git clone https://github.com/JetsonHacksNano/installSwapfile :~/installSwapfile$ ./installSwapfile.sh Creating Swapfile at: /mnt Swapfile Size: 6G Automount: Y -rw-r--r-- 1 root root 6.0G 4月 23 22:28 swapfile -rw------- 1 root root 6.0G 4月 23 22:28 swapfile Setting up swapspace version 1, size = 6 GiB (6442446848 bytes) no label, UUID=db94d31a-7bec-439a-ac17-8cccd0d5ebba Filename Type Size Used Priority /mnt/swapfile file 6291452 0 -1 Modifying /etc/fstab to enable on boot /mnt/swapfile Swap file has been created Reboot to make sure changes are in effect $ free total used free shared buff/cache available Mem: 4059712 549092 3131308 18896 379312 3340012 Swap: 6291452 0 6291452
クロックスを上げる
$ sudo jetson_clocks --show SOC family:tegra210 Machine:jetson-nano Online CPUs: 0-3 CPU Cluster Switching: Disabled cpu0: Online=1 Governor=schedutil MinFreq=102000 MaxFreq=1428000 CurrentFreq=1428000 IdleStates: WFI=1 c7=1 cpu1: Online=1 Governor=schedutil MinFreq=102000 MaxFreq=1428000 CurrentFreq=1326000 IdleStates: WFI=1 c7=1 cpu2: Online=1 Governor=schedutil MinFreq=102000 MaxFreq=1428000 CurrentFreq=1428000 IdleStates: WFI=1 c7=1 cpu3: Online=1 Governor=schedutil MinFreq=102000 MaxFreq=1428000 CurrentFreq=1326000 IdleStates: WFI=1 c7=1 GPU MinFreq=76800000 MaxFreq=921600000 CurrentFreq=76800000 EMC MinFreq=204000000 MaxFreq=1600000000 CurrentFreq=1600000000 FreqOverride=0 Fan: speed=0 NV Power Mode: MAXN
冷却ファンを足す
ヒートシンクに、ネジ穴が空いていて、ファンを取り付けられるようになっている。
5V の PWM制御できるやつ。サイズは 40mm
ファンの制御
$ sudo sh -c 'echo 255 > /sys/devices/pwm-fan/target_pwm'
Cuda サンプルを一通り動かす
第563回 NVIDIA Jetson Nano Developer KitにUbuntuをインストールしよう!:Ubuntu Weekly Recipe|gihyo.jp … 技術評論社
$ cp -a /usr/local/cuda-10.0/samples/ ~/
$ cd ~/samples/1_Utilities/deviceQuery $ make $ $ ./deviceQuery ./deviceQuery Starting... CUDA Device Query (Runtime API) version (CUDART static linking) Detected 1 CUDA Capable device(s) Device 0: "NVIDIA Tegra X1" CUDA Driver Version / Runtime Version 10.0 / 10.0 CUDA Capability Major/Minor version number: 5.3 Total amount of global memory: 3965 MBytes (4157145088 bytes) ( 1) Multiprocessors, (128) CUDA Cores/MP: 128 CUDA Cores GPU Max Clock rate: 922 MHz (0.92 GHz) Memory Clock rate: 13 Mhz Memory Bus Width: 64-bit L2 Cache Size: 262144 bytes Maximum Texture Dimension Size (x,y,z) 1D=(65536), 2D=(65536, 65536), 3D=(4096, 4096, 4096) Maximum Layered 1D Texture Size, (num) layers 1D=(16384), 2048 layers Maximum Layered 2D Texture Size, (num) layers 2D=(16384, 16384), 2048 layers Total amount of constant memory: 65536 bytes Total amount of shared memory per block: 49152 bytes Total number of registers available per block: 32768 Warp size: 32 Maximum number of threads per multiprocessor: 2048 Maximum number of threads per block: 1024 Max dimension size of a thread block (x,y,z): (1024, 1024, 64) Max dimension size of a grid size (x,y,z): (2147483647, 65535, 65535) Maximum memory pitch: 2147483647 bytes Texture alignment: 512 bytes Concurrent copy and kernel execution: Yes with 1 copy engine(s) Run time limit on kernels: Yes Integrated GPU sharing Host Memory: Yes Support host page-locked memory mapping: Yes Alignment requirement for Surfaces: Yes Device has ECC support: Disabled Device supports Unified Addressing (UVA): Yes Device supports Compute Preemption: No Supports Cooperative Kernel Launch: No Supports MultiDevice Co-op Kernel Launch: No Device PCI Domain ID / Bus ID / location ID: 0 / 0 / 0 Compute Mode: < Default (multiple host threads can use ::cudaSetDevice() with device simultaneously) > deviceQuery, CUDA Driver = CUDART, CUDA Driver Version = 10.0, CUDA Runtime Version = 10.0, NumDevs = 1 Result = PASS
$ cd ~/samples/5_Simulations/oceanFFT/
$ make
$ ./oceanFFT
$ cd ~/samples/5_Simulations/smokeParticles/ $ make make: Nothing to be done for 'all' $ ./smokeParticles
$ cd ~/samples/5_Simulations/nbody/
$ make
$ ./nbody
$ mkdir ~/visionworks/ $ cd /usr/share/visionworks/sources/ $ ./install-samples.sh ~/visionworks/ $ ./install-samples.sh ~/visionworks/ Creating the /home/kiyo/visionworks//VisionWorks-1.6-Samples directory... Copying VisionWorks samples to /home/kiyo/visionworks//VisionWorks-1.6-Samples... Finished copying VisionWorks samples $ cd ~/visionworks/VisionWorks-1.6-Samples/demos/hough_transform/ $ make
Darknet install
メモだけ
エラー
cudnn not found
でたので、 ~/.bash_rc に、2行追加。
CUDA and cuDNN paths
export PATH=/usr/local/cuda-10.0/bin/:${PATH} export LD_LIBRARY_PATH=/usr/lib/aarch64-linux-gnu/::${LD_LIBRARY_PATH}
$ git clone https://github.com/pjreddie/darknet.git $ cd darknet $ make $ ./darknet usage: ./darknet <function>
OOM
Out of memory: Kill process 13202 (darknet) score 52 or sacrifice child
cfg の subdivisions を変更する。
元:subdivisions=16
新:subdivisions=32
Hello AI Worldを試す - JETSON NANO 開発者キット その2
JETSON NANO 開発者キット を試す その1 の続きです
とりあえずなにかしたいわけですが、Hello AI World
として紹介されているやつが便利そう。
jetson-inference
ドキュメントに従って、Using the Console Program on Jetson
まで実行。
Classifying Images with ImageNet
何やら、ImageNet を使用した Classifying らしいです。
~/jetson-inference/build/aarch64/bin$ ./imagenet-console orange_0.jpg output_0.jpg imagenet-console args (3): 0 [./imagenet-console] 1 [orange_0.jpg] 2 [output_0.jpg] imageNet -- loading classification network model from: -- prototxt networks/googlenet.prototxt -- model networks/bvlc_googlenet.caffemodel -- class_labels networks/ilsvrc12_synset_words.txt -- input_blob 'data' -- output_blob 'prob' -- batch_size 2 [TRT] TensorRT version 5.0.6 ・・・ [TRT] layer network time - 141.518982 ms class 0950 - 0.978908 (orange) class 0951 - 0.020961 (lemon) imagenet-console: 'orange_0.jpg' -> 97.89076% class #950 (orange) loaded image fontmapA.png (256 x 512) 2097152 bytes [cuda] cudaAllocMapped 2097152 bytes, CPU 0x1048a0000 GPU 0x1048a0000 [cuda] cudaAllocMapped 8192 bytes, CPU 0x100f62000 GPU 0x100f62000 imagenet-console: attempting to save output image to 'output_0.jpg' imagenet-console: completed saving 'output_0.jpg' shutting down...
97%の確率で、オレンジだそうですよ。
Locating Object Coordinates using DetectNet
つぎは、学習済みの DetectNet-COCO-Dog model を使用した、ディテクションです。
$ ./detectnet-console dog_1.jpg output_1.jpg coco-dog detectnet-console args (4): 0 [./detectnet-console] 1 [dog_1.jpg] 2 [output_1.jpg] 3 [coco-dog] detectNet -- loading detection network model from: -- prototxt networks/DetectNet-COCO-Dog/deploy.prototxt -- model networks/DetectNet-COCO-Dog/snapshot_iter_38600.caffemodel -- input_blob 'data' -- output_cvg 'coverage' -- output_bbox 'bboxes' -- mean_pixel 0.000000 -- class_labels networks/DetectNet-COCO-Dog/class_labels.txt -- threshold 0.500000 -- batch_size 2 [TRT] TensorRT version 5.0.6 ・・・ [TRT] layer network time - 371.817322 ms detectnet-console: finished processing network (1555656574352) 2 bounding boxes detected detected obj 0 class #0 (dog) confidence=0.886617 bounding box 0 (1258.875000, 240.310547) (1672.687500, 563.941406) w=413.812500 h=323.630859 detected obj 1 class #0 (dog) confidence=0.502083 bounding box 1 (594.562500, 328.482422) (1016.437500, 584.718750) w=421.875000 h=256.236328 detectnet-console: writing 1920x1080 image to 'output_1.jpg' detectnet-console: successfully wrote 1920x1080 image to 'output_1.jpg' shutting down...
Dog を2つ検出していて、その位置を矩形で出していますね。
Multi-class Object Detection Models
$ ./detectnet-console peds-003.jpg output-3.jpg multiped ... detectnet-console: finished processing network (1555657903767) 6 bounding boxes detected detected obj 0 class #0 (person) confidence=0.547767 bounding box 0 (382.875000, -127.316528) (837.625000, 583.328979) w=454.750000 h=710.645508 detected obj 1 class #0 (person) confidence=0.671255 bounding box 1 (-6.250000, -5.668457) (218.250000, 577.884277) w=224.500000 h=583.552734 detected obj 2 class #0 (person) confidence=0.554531 bounding box 2 (870.500000, 72.794922) (989.937500, 452.805298) w=119.437500 h=380.010376 detected obj 3 class #1 (baggage) confidence=0.718298 bounding box 3 (681.246094, 263.098450) (761.109375, 410.105408) w=79.863281 h=147.006958 detected obj 4 class #1 (baggage) confidence=0.967225 bounding box 4 (925.593750, 269.661926) (998.937500, 432.219849) w=73.343750 h=162.557922 detected obj 5 class #1 (baggage) confidence=0.979315 bounding box 5 (148.437500, 288.233582) (323.406250, 522.094727) w=174.968750 h=233.861145 detectnet-console: writing 1024x611 image to 'output-3.jpg' detectnet-console: successfully wrote 1024x611 image to 'output-3.jpg' shutting down...
GPU 使用率
GPU使用率については、tegrastats Utility
を使えとのこと。
$ tegrastats RAM 1097/3963MB (lfb 271x4MB) CPU [11%@102,10%@102,6%@102,3%@102] EMC_FREQ 0% GR3D_FREQ 0% PLL@40C CPU@44C PMIC@100C GPU@42C AO@48.5C thermal@43C POM_5V_IN 1248/1248 POM_5V_GPU 0/0 POM_5V_CPU 166/166 RAM 1110/3963MB (lfb 271x4MB) CPU [9%@1428,3%@1428,1%@1428,2%@1428] EMC_FREQ 0% GR3D_FREQ 2% PLL@40.5C CPU@44C PMIC@100C GPU@40C AO@49C thermal@43C POM_5V_IN 2514/1881 POM_5V_GPU 82/41 POM_5V_CPU 823/494 RAM 1342/3963MB (lfb 263x4MB) CPU [8%@1428,97%@1428,7%@1428,6%@1428] EMC_FREQ 0% GR3D_FREQ 6% PLL@41C CPU@45C PMIC@100C GPU@40.5C AO@49.5C thermal@42.5C POM_5V_IN 3317/2359 POM_5V_GPU 163/81 POM_5V_CPU 1226/738 RAM 1474/3963MB (lfb 263x4MB) CPU [8%@1428,96%@1428,6%@1428,6%@1428] EMC_FREQ 0% GR3D_FREQ 0% PLL@41C CPU@44.5C PMIC@100C GPU@40.5C AO@49.5C thermal@42.75C POM_5V_IN 2716/2448 POM_5V_GPU 82/81 POM_5V_CPU 903/779 RAM 1692/3963MB (lfb 250x4MB) CPU [7%@1428,8%@1428,12%@1428,86%@1428] EMC_FREQ 0% GR3D_FREQ 33% PLL@41C CPU@45C PMIC@100C GPU@40.5C AO@49C thermal@43C POM_5V_IN 2917/2542 POM_5V_GPU 123/90 POM_5V_CPU 1025/828 RAM 1711/3963MB (lfb 241x4MB) CPU [8%@403,71%@403,7%@403,5%@403] EMC_FREQ 0% GR3D_FREQ 99% PLL@41C CPU@45.5C PMIC@100C GPU@41.5C AO@50C thermal@43.25C POM_5V_IN 4429/2856 POM_5V_GPU 1706/359 POM_5V_CPU 528/778 RAM 1098/3963MB (lfb 268x4MB) CPU [14%@102,59%@102,0%@102,3%@102] EMC_FREQ 0% GR3D_FREQ 0% PLL@40.5C CPU@44.5C PMIC@100C GPU@40.5C AO@49C thermal@42.5C POM_5V_IN 1904/2720 POM_5V_GPU 82/319 POM_5V_CPU 165/690 RAM 1098/3963MB (lfb 268x4MB) CPU [13%@102,4%@102,4%@102,1%@102] EMC_FREQ 0% GR3D_FREQ 0% PLL@40C CPU@44.5C PMIC@100C GPU@42C AO@49.5C thermal@43.25C POM_5V_IN 1206/2531 POM_5V_GPU 0/279 POM_5V_CPU 166/625
・・・情報多すぎ。
ドキュメント
GR3D_FREQ 99%
って行があるから、GPU使用率 99% に達したという意味かな?
カメラを使用する
note: by default, the Jetson's onboard CSI camera will be used as the video source. If you wish to use a USB webcam instead, change the DEFAULT_CAMERA define at the top of imagenet-camera.cpp to reflect the /dev/video V4L2 device of your USB camera. The model it's tested with is Logitech C920.
ということで、デフォルトでは、オンボードのCSIカメラを使用する設定になっている。これは意外。
USBカメラ設定で再コンパイル
USBカメラを使用する場合には、設定ファイルを書き換えて、再コンパイルが必要です。
ここで注意が必要なのは、detectnet-camera
と imagenet-camera
の2スクリプトそれぞれに、設定ファイルがあるので、両方変えないとだめです。
最初、片方だけ直したせいで、片やWEBカメラ、片やカメラモジュールが起動するという、挙動になり、なぜだろう・・・?と、相当悩みました。
~/jetson-inference/imagenet-camera/imagenet-camera.cpp
~/jetson-inference/detectnet-camera/detectnet-camera.cpp
カメラモジュールについて
Raspberry pi 用の公式カメラモジュールが動きます。
V2.1 を刺したところ正常に認識し、動きました。
V1.4 を刺したところ、認識しませんでした。
ドキュメントには、Version2は動くよーと書いてあるので、V1.4は非対応なのかも。
ただし、手元の v1.4 が壊れていた可能性もあります。
セットアップ - JETSON NANO 開発者キット その1
JETSON NANO 開発者キット を試します。
Jetson nano の情報
技術仕様 GPU 128 基の NVIDIA CUDA® コアを実装した NVIDIA Maxwell™ アーキテクチャ CPU クアッドコア ARM® Cortex®-A57 MPCore プロセッサ メモリ 4 GB 64 ビット LPDDR4 ストレージ 16 GB eMMC 5.1 フラッシュ ビデオ エンコード 4K @ 30 (H.264/H.265) ビデオ デコード 4K @ 60 (H.264/H.265) カメラ 12 レーン (3x4 または 4x2) MIPI CSI-2 DPHY 1.1 (1.5 Gbps) コネクティビティ ギガビット イーサネット ディスプレイ HDMI 2.0 または DP1.2 | eDP 1.4 | DSI (1 x2) の 2 つ同時 UPHY 1 x1/2/4 PCIE、1x USB 3.0、3x USB 2.0 I/O 1x SDIO / 2x SPI / 6x I2C / 2x I2S / GPIOs サイズ 69.6 mm x 45 mm コネクタ 260 ピン エッジ コネクタ
開発者キット
開発者キット I/O USB 4x USB 3.0、USB 2.0 Micro-B カメラ用コネクタ 1x MIPI CSI-2 DPHY レーン コネクティビティ ギガビット イーサネット、M.2 Key E ストレージ microSD (別売) ディスプレイ HDMI 2.0 および eDP 1.4 I/O GPIO、I2C、I2S、SPI、UART
インストール
ガイドはこちら
Getting Started With Jetson Nano Developer Kit | NVIDIA Developer
必須
microSD Card
the minimum recommended is a 16GB UHS-1 card.
Micro-USB Power Supply
5V⎓2A
Write Image to the microSD Card
Download the Jetson Nano Developer Kit SD Card Image, and note where it was saved on the computer.
Write the image to your microSD card by following the instructions below according to the type of computer you are using: Windows, Mac, or Linux.
zipのファイルサイズは 5.5G あります。
解凍後の .img は 12.5G あります
焼く
以下の2つのセットが紹介されています。
Raspberry pi と一緒ですね。
SD Memory Card Formatter for Windows.
- Download, install, and launch SD Memory Card Formatter for Windows.
- Select card drive
- Select “Quick format”
- Leave “Volume label” blank
- Click “Format” to start formatting, and “Yes” on the warning dialog
Etcher.
初期設定
起動
GUI ログイン画面になっていました。
$ cat /etc/os-release NAME="Ubuntu" VERSION="18.04.2 LTS (Bionic Beaver)" ID=ubuntu ID_LIKE=debian PRETTY_NAME="Ubuntu 18.04.2 LTS" VERSION_ID="18.04" HOME_URL="https://www.ubuntu.com/" SUPPORT_URL="https://help.ubuntu.com/" BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/" PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy" VERSION_CODENAME=bionic UBUNTU_CODENAME=bionic
いろいろ設定
root のパスワード sudo su - で root になって、パスワード設定
VNC
いつもトラブル発生のVNC
Vino という VNC server?が入っている。 ログインし、画面共有を Active にして、パスワードを設定する。
WIndows10 の VNC viewer でコネクトするとエラーが出る。
$ gsettings set org.gnome.Vino require-encryption false
電源について
8. DC Barrel jack for 5V power input
となっているが、5V4Aを指しても通電しない模様。
ぐぐったら、横のジャンパーピンを繋ぐ必要があるらしい。
適当につないだら、確かに起動した。
Ubuntu 16.04 lts + CUDA9.0 + cuDNN 7.1.3 Tensorflow1.6 コンパイルまで
Ubuntu14.04 LTS を dist upgrade で、16.04 にしたので、CUDA と cuDNN を入れ直しすことにしました。
NVIDIA Driver を入れ直す
Before installing the CUDA Toolkit on Linux, please ensure that you have the latest NVIDIA driver R390 installed. The latest NVIDIA R390 driver is available at: www.nvidia.com/drivers
を発見。
現在のバージョンを確認。
$ nvidia-smi Tue May 1 21:25:53 2018 +-----------------------------------------------------------------------------+ | NVIDIA-SMI 384.111 Driver Version: 384.111 | |-------------------------------+----------------------+----------------------+ | GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC | | Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. | |===============================+======================+======================| | 0 GeForce GTX 106... Off | 00000000:06:00.0 On | N/A | | 0% 39C P8 9W / 120W | 52MiB / 6071MiB | 0% Default | +-------------------------------+----------------------+----------------------+ +-----------------------------------------------------------------------------+ | Processes: GPU Memory | | GPU PID Type Process name Usage | |=============================================================================| | 0 1135 G /usr/lib/xorg/Xorg 50MiB | +-----------------------------------------------------------------------------+
とのことなので、Driver を先に入れよう。
$ dpkg -l | grep nvidia $ dpkg -l | grep cuda $ sudo add-apt-repository ppa:graphics-drivers/ppa $ sudo apt-get update $ sudo apt-get install nvidia-390 $ sudo reboot $ nvidia-smi Tue May 1 22:00:43 2018 +-----------------------------------------------------------------------------+ | NVIDIA-SMI 390.48 Driver Version: 390.48 | |-------------------------------+----------------------+----------------------+ | GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC | | Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. | |===============================+======================+======================| | 0 GeForce GTX 106... Off | 00000000:06:00.0 On | N/A | | 0% 43C P0 29W / 120W | 61MiB / 6077MiB | 0% Default | +-------------------------------+----------------------+----------------------+ +-----------------------------------------------------------------------------+ | Processes: GPU Memory | | GPU PID Type Process name Usage | |=============================================================================| | 0 1049 G /usr/lib/xorg/Xorg 59MiB | +-----------------------------------------------------------------------------+
CUDA インストール
sudo dpkg -i cuda-repo-ubuntu1604_9.1.85-1_amd64.deb
sudo apt-key adv --fetch-keys http://developer.download.nvidia.com/compute/cuda/repos/ubuntu1604/x86_64/7fa2af80.pub
sudo apt-get update
sudo apt-get install cuda
なお、Tensorflow が、 CUDA9.0 を求めてきたので、
$ sudo apt-get install cuda-9-0
となりました。
邪魔していたのを対処
$ sudo aptitude install cuda
path を通す
cuDNN インストール
tensorflow インストール
sudo pip install tensorflow
で、1.8 かなにかが入ったんですが、tensorflow Illegal instruction core dump
でてしまって、困りました。
回避策として、
$ sudo pip install tensorflow-gpu==1.5
となりました。
pipでバイナリをインストールした場合、1.6以降ではAVX がONになっていて、CPU が AVX に対応していないと、エラーに成るようです。
Note: Starting from 1.6 release, our prebuilt binaries will use AVX instructions. Older CPUs may not be able to execute these binaries.
回避策としては、1.5を使用するか、pip ではなく、自分で AVX OFF でコンパイルすることらしいです。
Tensorflow を、コンパイルする
Installing TensorFlow from Sources | TensorFlow
git で取得
$ git clone https://github.com/tensorflow/tensorflow
$ cd tensorflow
$ git checkout r1.6
$ ./configure
build
$ bazel build --config=opt --config=cuda //tensorflow/tools/pip_package:build_pip_package $ bazel-bin/tensorflow/tools/pip_package/build_pip_package /tmp/tensorflow_pkg $ sudo pip install /tmp/tensorflow_pkg/tensorflow-1.8.0-py2-none-any.whl
Tensorflow で SSD
動作環境
$ cat /etc/os-release NAME="Ubuntu" VERSION="14.04.5 LTS, Trusty Tahr" ID=ubuntu ID_LIKE=debian PRETTY_NAME="Ubuntu 14.04.5 LTS" VERSION_ID="14.04" HOME_URL="http://www.ubuntu.com/" SUPPORT_URL="http://help.ubuntu.com/" BUG_REPORT_URL="http://bugs.launchpad.net/ubuntu/" $ nvcc -V nvcc: NVIDIA (R) Cuda compiler driver Copyright (c) 2005-2016 NVIDIA Corporation Built on Tue_Jan_10_13:22:03_CST_2017 Cuda compilation tools, release 8.0, V8.0.61 $ ls /usr/local/cuda/lib64/libcudnn.so.* /usr/local/cuda/lib64/libcudnn.so.5 /usr/local/cuda/lib64/libcudnn.so.5.1.10 $ pip list | grep tensorflow tensorflow-gpu 1.4.1 tensorflow-tensorboard 0.4.0 $ python Python 3.4.3 (default, Nov 28 2017, 16:41:13) [GCC 4.8.4] on linux Type "help", "copyright", "credits" or "license" for more information.
SSD の取得と、設定?
$ git clone https://github.com/balancap/SSD-Tensorflow.git $ cd SSD-Tensorflow $ cd checkpoints $ unzip ssd_300_vgg.ckpt.zip
サンプルコードを改変して、動かす
$ cd ../notebooks/ $ jupyter nbconvert --to python ssd_notebook.ipynb
matplotlib の設定
$ cat ~/.config/matplotlib/matplotlibrc font.family : IPAexGothic backend : tkagg
サンプルコードを改変
せっかくなので、すべての画像を処理することと、ラベルを設定しました。
./datasets/pascalvoc_common.py
の中身を、使用しやすいように書き換えてます。
SSDによる物体検出を試してみた - TadaoYamaokaの日記
こちら様のデータを使用しています。
ssd_notebook.py
# coding: utf-8 import os import math import random import numpy as np import tensorflow as tf import cv2 slim = tf.contrib.slim #get_ipython().magic('matplotlib inline') import matplotlib.pyplot as plt import matplotlib.image as mpimg import sys sys.path.append('../') from nets import ssd_vgg_300, ssd_common, np_methods from preprocessing import ssd_vgg_preprocessing from notebooks import visualization # TensorFlow session: grow memory when needed. TF, DO NOT USE ALL MY GPU MEMORY!!! gpu_options = tf.GPUOptions(allow_growth=True) config = tf.ConfigProto(log_device_placement=False, gpu_options=gpu_options) isess = tf.InteractiveSession(config=config) # ## SSD 300 Model # # The SSD 300 network takes 300x300 image inputs. In order to feed any image, the latter is resize to this input shape (i.e.`Resize.WARP_RESIZE`). Note that even though it may change the ratio width / height, the SSD model performs well on resized images (and it is the default behaviour in the original Caffe implementation). # # SSD anchors correspond to the default bounding boxes encoded in the network. The SSD net output provides offset on the coordinates and dimensions of these anchors. # Input placeholder. net_shape = (300, 300) data_format = 'NHWC' img_input = tf.placeholder(tf.uint8, shape=(None, None, 3)) # Evaluation pre-processing: resize to SSD net shape. image_pre, labels_pre, bboxes_pre, bbox_img = ssd_vgg_preprocessing.preprocess_for_eval( img_input, None, None, net_shape, data_format, resize=ssd_vgg_preprocessing.Resize.WARP_RESIZE) image_4d = tf.expand_dims(image_pre, 0) # Define the SSD model. reuse = True if 'ssd_net' in locals() else None ssd_net = ssd_vgg_300.SSDNet() with slim.arg_scope(ssd_net.arg_scope(data_format=data_format)): predictions, localisations, _, _ = ssd_net.net(image_4d, is_training=False, reuse=reuse) # Restore SSD model. ckpt_filename = '../checkpoints/ssd_300_vgg.ckpt' # ckpt_filename = '../checkpoints/VGG_VOC0712_SSD_300x300_ft_iter_120000.ckpt' isess.run(tf.global_variables_initializer()) saver = tf.train.Saver() saver.restore(isess, ckpt_filename) # SSD default anchor boxes. ssd_anchors = ssd_net.anchors(net_shape) # ## Post-processing pipeline # # The SSD outputs need to be post-processed to provide proper detections. Namely, we follow these common steps: # # * Select boxes above a classification threshold; # * Clip boxes to the image shape; # * Apply the Non-Maximum-Selection algorithm: fuse together boxes whose Jaccard score > threshold; # * If necessary, resize bounding boxes to original image shape. # Main image processing routine. def process_image(img, select_threshold=0.5, nms_threshold=.45, net_shape=(300, 300)): # Run SSD network. rimg, rpredictions, rlocalisations, rbbox_img = isess.run([image_4d, predictions, localisations, bbox_img], feed_dict={img_input: img}) # Get classes and bboxes from the net outputs. rclasses, rscores, rbboxes = np_methods.ssd_bboxes_select( rpredictions, rlocalisations, ssd_anchors, select_threshold=select_threshold, img_shape=net_shape, num_classes=21, decode=True) rbboxes = np_methods.bboxes_clip(rbbox_img, rbboxes) rclasses, rscores, rbboxes = np_methods.bboxes_sort(rclasses, rscores, rbboxes, top_k=400) rclasses, rscores, rbboxes = np_methods.bboxes_nms(rclasses, rscores, rbboxes, nms_threshold=nms_threshold) # Resize bboxes to original image shape. Note: useless for Resize.WARP! rbboxes = np_methods.bboxes_resize(rbbox_img, rbboxes) return rclasses, rscores, rbboxes # Test on some demo image and visualize output. path = '../demo/' image_names = sorted(os.listdir(path)) for i in range(12): img = mpimg.imread(path + image_names[i]) rclasses, rscores, rbboxes = process_image(img)
visualization.py
# Copyright 2017 Paul Balanca. All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ============================================================================== import sys import cv2 import random import matplotlib.pyplot as plt import matplotlib.image as mpimg import matplotlib.cm as mpcm VOC_LABELS = { 0: 'none', 1: 'aeroplane', 2: 'bicycle', 3: 'bird', 4: 'boat', 5: 'bottle', 6: 'bus', 7: 'car', 8: 'cat', 9: 'chair', 10: 'cow', 11: 'diningtable', 12: 'dog', 13: 'horse', 14: 'motorbike', 15: 'person', 16: 'pottedplant', 17: 'sheep', 18: 'sofa', 19: 'train', 20: 'tvmonitor', } # =========================================================================== # # Some colormaps. # =========================================================================== # def colors_subselect(colors, num_classes=21): dt = len(colors) // num_classes sub_colors = [] for i in range(num_classes): color = colors[i*dt] if isinstance(color[0], float): sub_colors.append([int(c * 255) for c in color]) else: sub_colors.append([c for c in color]) return sub_colors colors_plasma = colors_subselect(mpcm.plasma.colors, num_classes=21) colors_tableau = [(255, 255, 255), (31, 119, 180), (174, 199, 232), (255, 127, 14), (255, 187, 120), (44, 160, 44), (152, 223, 138), (214, 39, 40), (255, 152, 150), (148, 103, 189), (197, 176, 213), (140, 86, 75), (196, 156, 148), (227, 119, 194), (247, 182, 210), (127, 127, 127), (199, 199, 199), (188, 189, 34), (219, 219, 141), (23, 190, 207), (158, 218, 229)] # =========================================================================== # # OpenCV drawing. # =========================================================================== # def draw_lines(img, lines, color=[255, 0, 0], thickness=2): """Draw a collection of lines on an image. """ for line in lines: for x1, y1, x2, y2 in line: cv2.line(img, (x1, y1), (x2, y2), color, thickness) def draw_rectangle(img, p1, p2, color=[255, 0, 0], thickness=2): cv2.rectangle(img, p1[::-1], p2[::-1], color, thickness) def draw_bbox(img, bbox, shape, label, color=[255, 0, 0], thickness=2): p1 = (int(bbox[0] * shape[0]), int(bbox[1] * shape[1])) p2 = (int(bbox[2] * shape[0]), int(bbox[3] * shape[1])) cv2.rectangle(img, p1[::-1], p2[::-1], color, thickness) p1 = (p1[0]+15, p1[1]) cv2.putText(img, str(label), p1[::-1], cv2.FONT_HERSHEY_DUPLEX, 0.5, color, 1) def bboxes_draw_on_img(img, classes, scores, bboxes, colors, thickness=2): shape = img.shape for i in range(bboxes.shape[0]): bbox = bboxes[i] color = colors[classes[i]] # Draw bounding box... p1 = (int(bbox[0] * shape[0]), int(bbox[1] * shape[1])) p2 = (int(bbox[2] * shape[0]), int(bbox[3] * shape[1])) cv2.rectangle(img, p1[::-1], p2[::-1], color, thickness) # Draw text... s = '%s/%.3f' % (classes[i], scores[i]) p1 = (p1[0]-5, p1[1]) cv2.putText(img, s, p1[::-1], cv2.FONT_HERSHEY_DUPLEX, 0.4, color, 1) # =========================================================================== # # Matplotlib show... # =========================================================================== # def plt_bboxes(f_name, img, classes, scores, bboxes, figsize=(10,10), linewidth=1.5): """Visualize bounding boxes. Largely inspired by SSD-MXNET! """ fig = plt.figure(figsize=figsize) plt.imshow(img) height = img.shape[0] width = img.shape[1] colors = dict() for i in range(classes.shape[0]): cls_id = int(classes[i]) if cls_id >= 0: score = scores[i] if cls_id not in colors: colors[cls_id] = (random.random(), random.random(), random.random()) ymin = int(bboxes[i, 0] * height) xmin = int(bboxes[i, 1] * width) ymax = int(bboxes[i, 2] * height) xmax = int(bboxes[i, 3] * width) rect = plt.Rectangle((xmin, ymin), xmax - xmin, ymax - ymin, fill=False, edgecolor=colors[cls_id], linewidth=linewidth) plt.gca().add_patch(rect) class_name = str(cls_id) class_name = VOC_LABELS[cls_id] plt.gca().text(xmin, ymin - 2, '{:s} | {:.3f}'.format(class_name, score), bbox=dict(facecolor=colors[cls_id], alpha=0.5), fontsize=12, color='white') plt.savefig( './results/'+f_name + '.png' ) plt.show()
結果