11
17

More than 3 years have passed since last update.

ONVIF対応カメラとJetson nanoで人物追跡AIカメラを作る

Last updated at Posted at 2021-02-09

できたこと

AIで人間を認識して、自動追尾するカメラを作りました。
動画がうまく編集できなかったので、静止画で...
image.png
立つと...
image.png
追いかけ...
image.png
座ると...
image.png
また追いかけ...
image.png
常に画面の中心にとらえようと、自動的にパン・チルトを行います。

必要なもの

  1. GENBOLT GB102H = ONVIF対応PTカメラ。Amazonで3,600円くらい。
  2. Jetson nano = CUDA対応オンボードコンピュータ。Amazonで16,000円くらい。2GB版だと7,000円弱。
  3. Yolov3-tiny = 物体認識AI
  4. ONVIFライブラリとサンプルプログラム = PTZカメラを動かすためのライブラリ
  5. VLC = カメラからのRTSP出力を表示します

手順

1. カメラの設定

1-1. カメラに電源とイーサケーブルをつなぐ

カメラの取説にしたがって、電源(USB-Micro)とイーサケーブルを接続します。

1-2. カメラのIPアドレスを知る

専用のスマホアプリを入れてカメラに接続します。
設定(歯車アイコン) → システム情報 を表示すると
カメラに割り振られたのIPアドレスがわかります。
image.png
image.png
image.png

1-3. カメラの設定をする

http://{カメラのIPアドレス} をブラウザで開くと設定ができます
デフォルトのユーザ名は admin
デフォルトのパスワードは admin
※ この記事ではこのまま進めますが、セキュリティ上変更したほうがよいです

ビデオ出力の設定をします。
Second StreamをYoloに入力するので、
Second Streamの Maximum frame rate を 6fps に設定します。
image.png

ONVIFでカメラを制御するので、ONVIFがOnになっていることを確かめます。
また、ポート番号(8080)も確認しておきます。
image.png

2. Yoloのインストール

darknetをクローンします

$ sudo apt install git
$ git clone https://github.com/AlexeyAB/darknet.git

CUDAを有効にしてビルドします

$ cd darknet
$ vi Makefile
#GPU CUDNN OEPNCVの設定を有効にする
GPU=1
CUDNN=1
OPENCV=1

$ make

weightsをダウンロードします

$ wget https://pjreddie.com/media/files/yolov3.weights
$ wget https://pjreddie.com/media/files/yolov3-tiny.weights

Yoloを実行してみます

$ ./darknet detect cfg/yolov3.cfg yolov3.weights data/dog.jpg

このように認識されれば、Yoloは正しくセットアップされています。

image.png

3. Yoloにカメラの画を流し、物体認識させる

$ ./darknet detector demo cfg/coco.data cfg/yolov3-tiny.cfg yolov3-tiny.weights rtsp://admin:admin@192.168.0.100/2

admin:admin の部分はパスワードを変えた場合には、そのパスワードに変更してください
192.168.0.100 の部分は GB102H のIPアドレスに変更してください

4. Jetson nanoからカメラのパン・チルト(PT)操作をする

4-1. ライブラリとサンプルアプリのクローン

ONVIFライブラリとサンプルプログラムをクローンします。
nodejsのプロジェクトなので、必要なライブラリを npm install でインストールします。

$ git clone https://github.com/agsh/onvif.git
$ cd onvif
$ npm install

4-2. コード変更(アドレス設定など)

カメラのIPアドレス、もし変えていたらポート番号、ユーザ名、パスワードを修正します。

$ vi example3.js
------------------------------------
var HOSTNAME = '192.168.0.100',
PORT = 8080,
USERNAME = 'admin',
PASSWORD = 'admin',
STOP_DELAY_MS = 50;
------------------------------------

4-2. 実行

$ node example3.js

上下左右のカーソルキーを押すと、カメラが動く様子がわかると思います。

5. 物体認識結果をもとにカメラのパン・チルト(PT)操作をする (完成)

example3.js をベースに改造をします。

$ cp example3.js example_yolo.js

5-1. 必要なライブラリをインストール

JSONStream をインストールします

$ npm install JSONStream --save

5-2. ライブラリのrequireと、Yoloのhost/portの追加

$ vi example_yolo.js
const request = require('request')
const JSONStream = require('JSONStream') // ★ これ

// ONVIF
var HOSTNAME = '192.168.0.100',
PORT = 8080,
USERNAME = 'admin',
PASSWORD = 'admin',
STOP_DELAY_MS = 50;

// YOLO
var YOLO_HOST = '127.0.0.1' // ★ これ
var YOLO_PORT = 5000        // ★ これ

5-3. キーボード操作関数呼び出しをコメントアウト、Yolo操作関数呼び出しを追加

cam_obj.getStreamUri({
    protocol : 'RTSP'
},  // Completion callback function
    // This callback is executed once we have a StreamUri
    function (err, stream, xml) {
        if (err) {
            console.log(err);
            return;
        } else {
            console.log('------------------------------');
            console.log('Host: ' + HOSTNAME + ' Port: ' + PORT);
            console.log('Stream: = ' + stream.uri);
            console.log('------------------------------');

            // start processing the keyboard
            //read_and_process_keyboard(); // ★ この行をコメントアウト

            // start processing the Yolo
            read_and_process_yolo(); // ★ この行を追加
        }
    }
);

5-2. Yolo操作関数本体

Yoloに接続すると、認識結果がJsonとして出力されるので、
pipeでストリーム出力し、JSONStreamにたべさせて、パースします。

パース結果をもとに、パン・チルトコマンドを発行してカメラを動かします。

function read_and_process_yolo() {
    console.log('yolo : ' + YOLO_HOST + " : " + YOLO_PORT)
    const stream = request('http://' + YOLO_HOST + ':' + YOLO_PORT).pipe(JSONStream.parse('$*'))
    var cnt = 0;
    stream.on('data', (data) => {
        cnt = (cnt + 1) % 4;
        var objs = data.value.objects
        objs.forEach(v => {
            if (v.name === 'person') {
                const xadj = 0.05
                const yadj = 0.05
                var cx = v.relative_coordinates.center_x;
                var cy = v.relative_coordinates.center_y;
                console.log('cx : ' + cx + ' / cy : ' + cy)
                if ((0 == cnt % 2) && (cx < 0.5 - xadj)) move(-1, 0, 0, 'left');
                if ((0 == cnt % 2) && (0.5 + xadj < cx)) move( 1, 0, 0, 'right');
                if ((0 == cnt)     && (cy < 0.6 - yadj)) move( 0, 1, 0, 'up');
                if ((0 == cnt)     && (0.6 + yadj < cy)) move( 0,-1, 0, 'down');
            }
        }); // end of objs.forEach
    }); // end of stream.on
}

5-3. Yoloの実行

認識結果をJson形式で出力させるために -json_port 5000 を引数に追加します。
また、Yoloの出力する画像が不要な場合には -dont_show をつけます。

$ ./darknet detector demo cfg/coco.data cfg/yolov3-tiny.cfg yolov3-tiny.weights rtsp://admin:admin@192.168.0.100/2 -json_port 5000 -dont_show

5-4. example_yolo.js の実行

$ node example_yolo.js

カメラが自分の方向に自動的にパン・チルトしてくれれば成功です

5-5. VLCで画像を観察

VLCを起動し、メディア >> ネットワークストリームを開く を選択し
URLに rtsp://admin:admin@192.168.0.100/1 を入力します
image.png
image.png

以上です

11
17
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
17