NVIDIAのJetson Nano 2G 開発者キットでカメラに写った物体の検知をやってみた
Contents
Hello AI Worldの物体の検知
NVIDIAのJetson Nano 2GB 開発者キットを購入したのでGithubで公開されているHello AI WorldのDeploying Deep Learningの「Locating Objects with DetectNet(DetectNetによる物体の検知)」をやってみた時の記事。
静止画像を読み込んで画像に写っている物体をバウンディングボックス(四角い枠)で囲んで検知して、その物体の名称を推論したり、Jetson NanoにUSB接続したWEBカメラに写っている物体(ペットボトル、フィギュア、etc)のリアルタイムでの推論などを試してみた。

尚、Jetson Nano 2GB 開発者キットのセットアップはこちら、入門コース(Getting Started with AI on Jetson Nano!)をやってみた時の記事はこちら、ディープ・ラーニングによる画像分類についてはこちらの記事を参照して欲しい。
環境
今回の実行環境は以下の通り。
本体 | NVIDIA Jetson Nano 2GB 開発者キット |
OS | Ubuntu18.04.5 LTS |
JetPack SDK | JetPack 4.4.1 |
カメラ | ロジクール ウェブカメラ C270n |
事前準備
セットアップ
Jetson Nano 2GB開発者キットのOSや必要なミドルソフトウェアのセットアップは終了している前提とする。
セットアップについては過去の記事の「Jetson Nano 2GB 開発者キットのセットアップ」を参照して欲しい。
プロジェクトの準備
NVIDIAのHello AIのページの”Running the Docker Container“(Dockerコンテナの実行)をクリックしてページ先の手順に沿ってDockerコンテナの実行を行う。

上記リンク先のページの手順に沿って事前準備を行う。
プロジェクトのコピー
git clone --recursive https://github.com/dusty-nv/jetson-inference
Dockerコンテナの実行
cd jetson-inference
docker/run.sh
詳細な手順については「NVIDIAのJetson Nanoで「ディープ・ラーニングによる画像分類」をやってみた」の事前準備の章を参照して欲しい。
必要に応じてデフォルト以外のモデルをダウンロードすることも出来る。
物体検出
使用するモデル
モデルは91-class SSD-Mobilenet-v2 model trained on the MS COCO datasetを使用した。
以下の特徴がある。
- Microsoftが提供しているCOCOデータセット上で学習させている
- COCOはCommon Objects in Contextの略で日常的な物を学習させている
- (今回のモデルは)91種類のクラス分類が可能
- 物体の検知のアルゴリズムにSSD(Single Shot MultiBox Detector)を使用している
- モバイル端末でも使用できる軽量なCNN(Convolutional Neural Network)のMobilenet Version2を使用している
学習済みの91種類のモノはこちらの一覧で確認して欲しい。
静止画の物体検出
まずは静止画の物体検出を試みる。
LXTerminalから該当ディレクトリに移動して物体検出プログラム(detectnet.py)を以下のコマンドで実行する。
尚、初回の実行はネットワークの最適化などで若干時間がかかる。
cd build/aarch64/bin/
./detectnet.py --network=ssd-mobilenet-v2 images/peds_0.jpg images/test/peds_out.jpg
detectnet.py | 物体検知用プログラム(後述) 画像、映像を入力として学習済みの物体を検知してバウンディングボックス(四角い枠)で囲み、名称を推論する。 | ||||||||||||||||||||
–network | 使用するネットワーク(ssd-mobilenet-v2)を指定した。 指定できるネットワークは以下の通り。
| ||||||||||||||||||||
入力画像 | 入力画像(images/peds_0.jpg)の指定。 横断歩道を数人の歩行者が横切っている写真を使用した。 | ||||||||||||||||||||
出力画像 | 物体検知後の写真の出力先(images/test/peds_out.jpg) Dockerコンテナ実行後もファイルが残るディレクトリ(images/test/)を指定している。 4人の歩行者がperson(人)として検知されて、緑色の枠(バウンディングボックス)で囲まれている。 また予測スコアが表示されているが一番左の女性が69.9(%)と若干低い事も分かる。 プログラム中でデフォルトで50%以上のしきい値の物体のみを検知するようにしている。 |
pednetでの実行結果
同様の写真に対してpednet(歩行者)のネットワークで試した時の出力結果。

左の2人が1つの大きなバウンディングボックスで囲まれて、156.4%(100%以上)のスコアが検知されている。
また真ん中の男性も100%以上のスコアを示している。
facenetでの実行結果
同様の写真に対してfacenet(顔)のネットワークで試した時の出力結果。

サングラスを掛けていたり、若干うつむき気味であっても顔のみが正しく検知できている。
また一番右の後ろ向きの男性は顔が写っていないので検知されていない。
人と犬の写真
人と犬が写った写真の ssd-mobilenet-v2 での検出結果。
人と犬がぞれそれ検出されている。

coco-dogでの実行結果
上記と同じ写真の coco-dog ネットワークでの検出結果。
人は検出されずに犬だけが検知されている。
使用するネットワークを用途によって使い分けることにより特定のモノのみを検出することが出来る。

プログラムソース
detectnet.py のソースコードは以下の通り。
上部にNVIDIAの著作権(制限無しで使用可能、コピー、変更、マージ、公開、配布、サブライセンス・・・)が記述されている。
またコード中に日本語でコメントを追記した。
#!/usr/bin/python3
#
# Copyright (c) 2020, NVIDIA CORPORATION. All rights reserved.
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the "Software"),
# to deal in the Software without restriction, including without limitation
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
# and/or sell copies of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
# DEALINGS IN THE SOFTWARE.
#
import jetson.inference
import jetson.utils
import argparse
import sys
# parse the command line
parser = argparse.ArgumentParser(description="Locate objects in a live camera stream using an object detection DNN.",
formatter_class=argparse.RawTextHelpFormatter, epilog=jetson.inference.detectNet.Usage() +
jetson.utils.videoSource.Usage() + jetson.utils.videoOutput.Usage() + jetson.utils.logUsage())
parser.add_argument("input_URI", type=str, default="", nargs='?', help="URI of the input stream") # 入力
parser.add_argument("output_URI", type=str, default="", nargs='?', help="URI of the output stream") # 出力
parser.add_argument("--network", type=str, default="ssd-mobilenet-v2", help="pre-trained model to load (see below for options)") # 使用ネットワーク(デフォルトはssd-mobilenet-v2)
parser.add_argument("--overlay", type=str, default="box,labels,conf", help="detection overlay flags (e.g. --overlay=box,labels,conf)\nvalid combinations are: 'box', 'labels', 'conf', 'none'") # オーバーレイ表示
parser.add_argument("--threshold", type=float, default=0.5, help="minimum detection threshold to use") # しきい値 50%以上を検出対象
is_headless = ["--headless"] if sys.argv[0].find('console.py') != -1 else [""]
try:
opt = parser.parse_known_args()[0] # パラメーターのチェック
except:
print("")
parser.print_help()
sys.exit(0)
# load the object detection network
net = jetson.inference.detectNet(opt.network, sys.argv, opt.threshold) # detectNetの起動
# create video sources & outputs
input = jetson.utils.videoSource(opt.input_URI, argv=sys.argv) # 入力 videoSourceは画像、映像両方に対応
output = jetson.utils.videoOutput(opt.output_URI, argv=sys.argv+is_headless) # 出力
# process frames until the user exits
while True:
# capture the next image
img = input.Capture() # キャプチャーして画像をimgに保存
# detect objects in the image (with overlay)
detections = net.Detect(img, overlay=opt.overlay) # 画像をベースにモノを検出、検出部をオーバーレイ表示
# print the detections
print("detected {:d} objects in image".format(len(detections)))
for detection in detections:
print(detection)
# render the image
output.Render(img) # 画像・映像を出力(videoOutputは両方に対応している)
# update the title bar
output.SetStatus("{:s} | Network {:.0f} FPS".format(opt.network, net.GetNetworkFPS()))
# print out performance info
net.PrintProfilerTimes()
# exit on input/output EOS
if not input.IsStreaming() or not output.IsStreaming(): # ストリーミング中で無ければ終了
break
補足説明
入力、出力で使用している jetson のユーティリティの videoSource(入力) と videoOutput(出力) は画像、映像の両方に対応している。
videoSource | 指定例
|
videoOutput | 指定例
|
動画の物体検出
続いてUSB接続したWEBカメラに写った物体をリアルタイムで物体検知してみる。

Jetsonはデスクトップ(GUI)表示している状態でLXTerminalから以下のコマンドで先程を同じプログラムを実行する。
ネットワークは指定をしないとデフォルトのCOCO MobilenetのVersion2が使用される。
./detectnet.py /dev/video0
物体検知の様子は以下の動画で確認して欲しい。
デジタル時計
デジタル時計については若干認識しない怪しい時もあったが正しく認識された。
cocoではこのタイプのデジタル時計の学習量が足りないのかも知れない。

レゴのフィギュア(女性)
レゴのフィギュア(女性)については常にperson(人)と認識された。
尚、もっとデフォルメされたレゴのフィギュアもpersonと認識されたので人は比較的認識しやすい物体(Object)のようだ。

ニホンカモシカ
海洋堂のニホンカモシカは距離が離れるとperson(人)、近づくとdog(犬)と認識された。
また時々 horse(馬)と認識された時もあった。
また台座の上の雪が積もった足場の石の部分が boat(ボート)と判定されることもあった。
そもそもニホンカモシカは coco では学習していないので正しく判定されないのはある意味当然の結果だ。

ペットボトル
ペットボトルはbottle(ボトル)と判定されたが中心部が何故かclock(時計)と判定されることもあった。

終わりに
デフォルトで用意された coco mobileモデルで、ある程度の精度が出ることが分かった。
利用目的にも寄るが監視カメラでの物体検知(個人利用)程度であれば十分な精度であると感じた。
より精度を上げたり新しい物体を学習させる為には別途転移学習が必要になる。
転移学習については別記事としたい。
以上で今回の記事は終了とする。
この記事が何処かで誰かの役に立つことを願っている。
尚、当記事中の商品へのリンクはAmazonアソシエイトへのリンクが含まれています。Amazonのアソシエイトとして、当メディアは適格販売により収入を得ていますのでご了承ください。
このサイトを参考にしているものです
カメラを持った男性と犬の写ったいる写真のもと画像を貼っていただきたいです。
images ディレクトリ配下にありませんか?
記事中のプロジェクトのコピーを行うと下記のGithubよりコピーされます。
https://github.com/dusty-nv/jetson-inference/tree/master/data/images