できたこと
AIで人間を認識して、自動追尾するカメラを作りました。
動画がうまく編集できなかったので、静止画で...
立つと...
追いかけ...
座ると...
また追いかけ...
常に画面の中心にとらえようと、自動的にパン・チルトを行います。
必要なもの
- GENBOLT GB102H = ONVIF対応PTカメラ。Amazonで3,600円くらい。
- Jetson nano = CUDA対応オンボードコンピュータ。Amazonで16,000円くらい。2GB版だと7,000円弱。
- Yolov3-tiny = 物体認識AI
- ONVIFライブラリとサンプルプログラム = PTZカメラを動かすためのライブラリ
- VLC = カメラからのRTSP出力を表示します
手順
1. カメラの設定
1-1. カメラに電源とイーサケーブルをつなぐ
カメラの取説にしたがって、電源(USB-Micro)とイーサケーブルを接続します。
1-2. カメラのIPアドレスを知る
専用のスマホアプリを入れてカメラに接続します。
設定(歯車アイコン) → システム情報 を表示すると
カメラに割り振られたのIPアドレスがわかります。
1-3. カメラの設定をする
http://{カメラのIPアドレス}
をブラウザで開くと設定ができます
デフォルトのユーザ名は admin
デフォルトのパスワードは admin
※ この記事ではこのまま進めますが、セキュリティ上変更したほうがよいです
ビデオ出力の設定をします。
Second StreamをYoloに入力するので、
Second Streamの Maximum frame rate を 6fps に設定します。
ONVIFでカメラを制御するので、ONVIFがOnになっていることを確かめます。
また、ポート番号(8080)も確認しておきます。
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は正しくセットアップされています。
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
を入力します
以上です