差分
このページの2つのバージョン間の差分を表示します。
| 両方とも前のリビジョン 前のリビジョン 次のリビジョン | 前のリビジョン | ||
| tutorial_2 [2022/01/04 10:31] – [第五項 エリア座標判定処理の考え方] satoshi | tutorial_2 [2022/05/02 14:09] (現在) – satoshi | ||
|---|---|---|---|
| 行 1: | 行 1: | ||
| - | ====== 第2章 スターターコード【初級編 エリア判定(立ち止まり判定)】 ====== | + | ====== 第2章 エリア判定(立ち止まり判定)【初級編】 ====== |
| 行 5: | 行 5: | ||
| ===== 第一項 スターターコードの中身を確認する ===== | ===== 第一項 スターターコードの中身を確認する ===== | ||
| 第2章のスターターコードは2つのプログラムコードに分かれます\\ | 第2章のスターターコードは2つのプログラムコードに分かれます\\ | ||
| - | 一つがSCORER People | + | 一つがSCORER People |
| もう一つが保存したログからあらかじめ指定したエリア内で立ち止まりがあるかどうかを調べるプログラムとなります。 | もう一つが保存したログからあらかじめ指定したエリア内で立ち止まりがあるかどうかを調べるプログラムとなります。 | ||
| 行 350: | 行 350: | ||
| } | } | ||
| </ | </ | ||
| - | ===== 第二項 座標ログをSCCORERシステムから受け取る ===== | + | ===== 第二項 座標ログをSCORERシステムから受け取る ===== |
| 以下、前項でのプログラムの解説を中心に、最終形を作る過程のプログラムも併せて掲載します。 | 以下、前項でのプログラムの解説を中心に、最終形を作る過程のプログラムも併せて掲載します。 | ||
| 行 605: | 行 605: | ||
| ちなみに取得したログを見ると、どのカメラからのデータなのか、いつのフレームの時刻なのかの情報がありません。\\ | ちなみに取得したログを見ると、どのカメラからのデータなのか、いつのフレームの時刻なのかの情報がありません。\\ | ||
| - | こちらはデータ取得時の時間を追記して保存しましょう(将来のSCORER People | + | こちらはデータ取得時の時間を追記して保存しましょう(将来のSCORER People |
| さて変更した部分をハイライトしておきます。 | さて変更した部分をハイライトしておきます。 | ||
| 行 1022: | 行 1022: | ||
| SCORER People Trackerでは1秒間に5-10回もの高頻度で検知を行っているため、前後の検知結果同士を見比べれば同じ人物であることが容易に推定されます。\\ | SCORER People Trackerでは1秒間に5-10回もの高頻度で検知を行っているため、前後の検知結果同士を見比べれば同じ人物であることが容易に推定されます。\\ | ||
| {{:: | {{:: | ||
| - | 本来は複数の人物がすれ違った時や、画面の外に出てまた入ってきた場合はどうなるかなどいろいろ考えるべきことはありますが、そのあたりはSCORER People | + | 本来は複数の人物がすれ違った時や、画面の外に出てまた入ってきた場合はどうなるかなどいろいろ考えるべきことはありますが、そのあたりはSCORER People |
| 今回は画面内にある人物の判定と前提があるため、あまり気にせず固有IDをそのまま活用していきましょう。\\ | 今回は画面内にある人物の判定と前提があるため、あまり気にせず固有IDをそのまま活用していきましょう。\\ | ||
| 行 1057: | 行 1057: | ||
| - 固有IDが初めて出てきたら配列に固有IDと座標等を登録。2回目以降は配列に座標を追加。 | - 固有IDが初めて出てきたら配列に固有IDと座標等を登録。2回目以降は配列に座標を追加。 | ||
| - 同時にエリア内にいたかどうかを判定。いた場合は固有ID配列に時刻ごとに「通過したフラグ」を立てる。 | - 同時にエリア内にいたかどうかを判定。いた場合は固有ID配列に時刻ごとに「通過したフラグ」を立てる。 | ||
| - | - 5秒前の情報からエリアにいた(検知漏れも考慮し9割以上の頻度で)場合は立ち止まったと判断して固有IDに「立ち止まったフラグ」を立てる。 | + | - 5秒前の情報からエリアにいた場合は立ち止まったと判断して固有IDに「立ち止まったフラグ」を立てる。 |
| - 全部の集計が完了したら配列をCSVにして出力する。 | - 全部の集計が完了したら配列をCSVにして出力する。 | ||
| という流れになります。\\ | という流れになります。\\ | ||
| 行 1163: | 行 1163: | ||
| | | ||
| json_open = open(area_def_file, | json_open = open(area_def_file, | ||
| - | result_json_file = open(' | + | result_json_file = open(' |
| areadef = json.load(json_open) | areadef = json.load(json_open) | ||
| resultarr = {} | resultarr = {} | ||
| - | for area in areadef: | + | for areaidx, |
| - | | + | |
| + | print(areaname) | ||
| + | resultarr[areaname]={} | ||
| print(" | print(" | ||
| - | for area in areadef: | + | for areaidx, |
| - | | + | |
| + | print(areaname) | ||
| polygon = [] | polygon = [] | ||
| for point in area[' | for point in area[' | ||
| 行 1179: | 行 1182: | ||
| for filename in file_list: | for filename in file_list: | ||
| - | print(area[' | + | print(areaname+" |
| if os.path.getsize(filename) == 0: | if os.path.getsize(filename) == 0: | ||
| continue | continue | ||
| 行 1191: | 行 1194: | ||
| for person in people: | for person in people: | ||
| | | ||
| - | #print(area[' | + | #print(areaname+' |
| personpos = [(person[" | personpos = [(person[" | ||
| test = cv2.pointPolygonTest(contour, | test = cv2.pointPolygonTest(contour, | ||
| if test>0: | if test>0: | ||
| - | if person[' | + | if person[' |
| - | resultarr[area[' | + | resultarr[areaname][person[' |
| - | resultarr[area[' | + | resultarr[areaname][person[' |
| - | resultarr[area[' | + | resultarr[areaname][person[' |
| - | if resultarr[area[' | + | if resultarr[areaname][person[' |
| - | resultarr[area[' | + | resultarr[areaname][person[' |
| else: | else: | ||
| - | resultarr[area[' | + | resultarr[areaname][person[' |
| json.dump(resultarr, | json.dump(resultarr, | ||
| 行 1208: | 行 1211: | ||
| for areaname, records in resultarr.items(): | for areaname, records in resultarr.items(): | ||
| print(areaname) | print(areaname) | ||
| - | f = open(sys.argv[1]+" | + | f = open(area_def_file[: |
| write = csv.writer(f) | write = csv.writer(f) | ||
| write.writerow([" | write.writerow([" | ||
| 行 1214: | 行 1217: | ||
| write.writerow([record[' | write.writerow([record[' | ||
| | | ||
| - | f.close() | + | f.close() |
| </ | </ | ||
| 実行は\\ | 実行は\\ | ||
| 行 1228: | 行 1231: | ||
| 24行目でエリア情報のファイルを開きます。(JSON形式のため26行目で配列に変換しています)\\ | 24行目でエリア情報のファイルを開きます。(JSON形式のため26行目で配列に変換しています)\\ | ||
| 25行目で結果CSVファイルを新規で開きます。\\ | 25行目で結果CSVファイルを新規で開きます。\\ | ||
| - | 28-29行目では結果データの配列をエリアごとに事前に初期化します。\\ | + | 28-31行目では結果データの配列をエリアごとに事前に初期化します。\\ |
| さて、今回多角形のエリアに対応した判定ができるようなコードとなっています。\\ | さて、今回多角形のエリアに対応した判定ができるようなコードとなっています。\\ | ||
| ここで初めて出てきますが、映像解析でよく使われる計算ライブラリにOpenCVというものがあります。\\ | ここで初めて出てきますが、映像解析でよく使われる計算ライブラリにOpenCVというものがあります。\\ | ||
| このライブラリを利用して多角形内にある点が入っているか入っていないかが簡単に判明します。\\ | このライブラリを利用して多角形内にある点が入っているか入っていないかが簡単に判明します。\\ | ||
| - | 54-55行目\\ | + | 57-58行目\\ |
| < | < | ||
| personpos = [(person[" | personpos = [(person[" | ||
| 行 1251: | 行 1254: | ||
| これは結果データを個体IDごとに集計しなおすことで、一つのIDに判定情報を蓄積していく形としています。\\ | これは結果データを個体IDごとに集計しなおすことで、一つのIDに判定情報を蓄積していく形としています。\\ | ||
| - | 56-64行目ではエリア内だった場合に、初めてその個体IDが現れた場合は初期化をし時刻を書きこみます。二回目以降出てきた場合は時刻を更新して、最初に検知された時刻との差分を増やしていき、5秒以上になった場合は立ち止まり判定フラグにTrueを入れます。\\ | + | 59-67行目ではエリア内だった場合に、初めてその個体IDが現れた場合は初期化をし時刻を書きこみます。二回目以降出てきた場合は時刻を更新して、最初に検知された時刻との差分を増やしていき、5秒以上になった場合は立ち止まり判定フラグにTrueを入れます。\\ |
| なお、エリアに一度も入っていない場合は今回集計対象からは外しています。\\ | なお、エリアに一度も入っていない場合は今回集計対象からは外しています。\\ | ||
| - | 68-76行目では一度すべての情報を配列で集計し終わった後、CSVファイルに書き込む処理をしています。CSVファイルの1行目には列のヘッダー情報を入れておきます。\\ | + | 71-79行目では一度すべての情報を配列で集計し終わった後、CSVファイルに書き込む処理をしています。CSVファイルの1行目には列のヘッダー情報を入れておきます。\\ |
| 細かいところなどは省きましたが、上記の動作するコードに対して様々な変更を加えて自分なりに動作を確認してみましょう。\\ | 細かいところなどは省きましたが、上記の動作するコードに対して様々な変更を加えて自分なりに動作を確認してみましょう。\\ | ||
| 次の章ではエリア座標を設定する手間を大幅に軽減するためにWEB画面で変更できるところなども学んでみましょう。 | 次の章ではエリア座標を設定する手間を大幅に軽減するためにWEB画面で変更できるところなども学んでみましょう。 | ||