====== 第3章 ライン判定(WEBUIを使った通過判定)【中級編】 ====== この章では、\\ * エリア検知からラインをまたいだ検知への応用 * WEB UIを利用することで画像から座標情報をペイントツールで目視で読み取って転記するという面倒な作業の廃止 * カメラ画像座標から見取り図画像座標への切り替え がテーマとなります。\\ WEBUIについてはカスタマイズ対象としませんが、興味がある人が調べられるように簡単に説明します。\\ ===== 第一項 スターターコードの中身を確認する ===== WEB UIを利用した時の解析プログラム\\ import sys import os import json import math from datetime import datetime, timedelta, timezone import csv import glob import numpy as np def intersect(p1, p2, p3, p4): tc1 = (p1[0] - p2[0]) * (p3[1] - p1[1]) + (p1[1] - p2[1]) * (p1[0] - p3[0]) tc2 = (p1[0] - p2[0]) * (p4[1] - p1[1]) + (p1[1] - p2[1]) * (p1[0] - p4[0]) td1 = (p3[0] - p4[0]) * (p1[1] - p3[1]) + (p3[1] - p4[1]) * (p3[0] - p1[0]) td2 = (p3[0] - p4[0]) * (p2[1] - p3[1]) + (p3[1] - p4[1]) * (p3[0] - p2[0]) return tc1*tc2<0 and td1*td2<0 if __name__ == '__main__': dirpath = 'data' line_def_file = os.environ['HOME']+'/drawui/sketchlines.json' JST = timezone(timedelta(hours=+9), 'JST') print(sys.argv[1]+"を集計しています・・") file_list = sorted(glob.glob('./'+dirpath+'/'+sys.argv[1]+'/raw_'+sys.argv[1]+'*.json')) print("対象ファイル一覧") for filename in file_list: print(filename) json_open = open(line_def_file, 'r') result_json_file = open('result_sketchlines_'+sys.argv[1]+'.json', 'w') linedef = json.load(json_open) resultarr = {} for lineidx, line in enumerate(linedef['lines']): linename='lineID'+str(lineidx) print(linename) resultarr[linename]={} print("集計・・") for lineidx, line in enumerate(linedef['lines']): linename='lineID'+str(lineidx) print(linename) polygon = [] print(line) for point in line['points']: polygon.append([point['x'],point['y']]) for filename in file_list: print(linename+"_"+filename) if os.path.getsize(filename) == 0: continue raw_json_open = open(filename, 'r') raw_json = json.load(raw_json_open) for frame in raw_json: jptime = datetime.fromtimestamp(frame['frame_time'],JST) people = frame['objects'] for person in people: #print(linename+'_'+person['tracking_id']+'_'+str(judgenum)) personpos = [person["floor"]["x"],person["floor"]["y"]] if person['tracking_id'] in resultarr[linename]: if intersect(personpos,resultarr[linename][person['tracking_id']]['prev_pos'],polygon[0],polygon[1]): resultarr[linename][person['tracking_id']]['passing_judge'] = True resultarr[linename][person['tracking_id']]['passing_time'] = jptime.isoformat() resultarr[linename][person['tracking_id']]['end_time'] = frame['frame_time'] resultarr[linename][person['tracking_id']]['end_time_jp'] = jptime.isoformat() else: resultarr[linename][person['tracking_id']]={'line':linename,'start_time_jp':jptime.isoformat(),'end_time_jp':jptime.isoformat(),'start_time':frame['frame_time'],'end_time':frame['frame_time'],'stream_id':frame['stream_id'],'passing_judge':False,'passing_time':0,'prev_pos':personpos} json.dump(resultarr,result_json_file) for linename, records in resultarr.items(): print(linename) f = open("sketchlines_"+sys.argv[1]+"_"+linename+".csv", 'w', encoding='utf-8', newline='') write = csv.writer(f) write.writerow(["stream_id","linename","tracking_id","start_time_jp","end_time_jp","passing_judge","passing_time"]) for tracking_id, record in records.items(): write.writerow([record['stream_id'],linename,tracking_id,record['start_time_jp'],record['end_time_jp'],record['passing_judge'],record['passing_time']]) f.close() 二章で作成したプログラムからの改変となっているので、基本的な構造は同じになります。\\ 線情報はUIから都度更新される下記のものを参照しています\\ { "lines": [ { "points": [ {"x": 131, "y": 134}, {"x": 260, "y": 128} ] }, { "points": [ {"x": 59, "y": 226}, {"x": 130, "y": 100} ] } ] } ===== 第二項 ライン通過検知座標判定処理の考え方 ===== WEB UIを使う前に、まず前章と同じように座標値を手で調べる前提でラインを通過した時の検知を作りましょう 通過については下記のように例えば一つ前の11秒00のフレームと現在の11秒10のフレームとの人物位置をそれぞれA(p1)、B(p2)、検知線の開始・終了位置C(p3)、D(p4)の線が交差しているかどうかを判定することになります。\\ {{::peopletracker_03lines.png|}}\\ これらについては一つまとまった判定になるため、下記のように4点与えてあげれば通過・非通過を1,0で応答してくれる関数を別途定義します。 def intersect(p1, p2, p3, p4): tc1 = (p1[0] - p2[0]) * (p3[1] - p1[1]) + (p1[1] - p2[1]) * (p1[0] - p3[0]) tc2 = (p1[0] - p2[0]) * (p4[1] - p1[1]) + (p1[1] - p2[1]) * (p1[0] - p4[0]) td1 = (p3[0] - p4[0]) * (p1[1] - p3[1]) + (p3[1] - p4[1]) * (p3[0] - p1[0]) td2 = (p3[0] - p4[0]) * (p2[1] - p3[1]) + (p3[1] - p4[1]) * (p3[0] - p2[0]) return tc1*tc2<0 and td1*td2<0 また、前章のエリア判定から変わっているポイントとして\\ * ライン判定になっているので関連する変数をすべて変更 * 1つ前の座標を結果配列で保持(prev_pos項目)しておいて、簡単にintersect関数に引き渡せるようにしている * 通過時間を記録する * CSVに出力する内容を変更 となっています。\\ これらを反映したプログラムがこちらです。\\ import sys import os import json import math from datetime import datetime, timedelta, timezone import csv import glob import numpy as np def intersect(p1, p2, p3, p4): tc1 = (p1[0] - p2[0]) * (p3[1] - p1[1]) + (p1[1] - p2[1]) * (p1[0] - p3[0]) tc2 = (p1[0] - p2[0]) * (p4[1] - p1[1]) + (p1[1] - p2[1]) * (p1[0] - p4[0]) td1 = (p3[0] - p4[0]) * (p1[1] - p3[1]) + (p3[1] - p4[1]) * (p3[0] - p1[0]) td2 = (p3[0] - p4[0]) * (p2[1] - p3[1]) + (p3[1] - p4[1]) * (p3[0] - p2[0]) return tc1*tc2<0 and td1*td2<0 if __name__ == '__main__': dirpath = 'data' duration = 5 line_def_file = '03lines.json' JST = timezone(timedelta(hours=+9), 'JST') print(sys.argv[1]+"を集計しています・・") file_list = sorted(glob.glob('./'+dirpath+'/'+sys.argv[1]+'/raw_'+sys.argv[1]+'*.json')) print("対象ファイル一覧") for filename in file_list: print(filename) json_open = open(line_def_file, 'r') result_json_file = open('result_'+line_def_file[:len(line_def_file)-5]+'_'+sys.argv[1]+'.json', 'w') linedef = json.load(json_open) resultarr = {} for lineidx, line in enumerate(linedef['lines']): linename='lineID'+str(lineidx) print(linename) resultarr[linename]={} print("集計・・") for lineidx, line in enumerate(linedef['lines']): linename='lineID'+str(lineidx) print(linename) polygon = [] print(line) for point in line['points']: polygon.append([point['x'],point['y']]) for filename in file_list: print(linename+"_"+filename) if os.path.getsize(filename) == 0: continue raw_json_open = open(filename, 'r') raw_json = json.load(raw_json_open) for frame in raw_json: jptime = datetime.fromtimestamp(frame['frame_time'],JST) people = frame['objects'] for person in people: #print(linename+'_'+person['tracking_id']+'_'+str(judgenum)) personpos = [(person["x0"]+person["x1"])/2,person["y1"]] if person['tracking_id'] in resultarr[linename]: if intersect(personpos,resultarr[linename][person['tracking_id']]['prev_pos'],polygon[0],polygon[1]): resultarr[linename][person['tracking_id']]['passing_judge'] = True resultarr[linename][person['tracking_id']]['passing_time'] = jptime.isoformat() resultarr[linename][person['tracking_id']]['end_time'] = frame['frame_time'] resultarr[linename][person['tracking_id']]['end_time_jp'] = jptime.isoformat() else: resultarr[linename][person['tracking_id']]={'line':linename,'start_time_jp':jptime.isoformat(),'end_time_jp':jptime.isoformat(),'start_time':frame['frame_time'],'end_time':frame['frame_time'],'stream_id':frame['stream_id'],'passing_judge':False,'passing_time':0,'prev_pos':personpos} json.dump(resultarr,result_json_file) for linename, records in resultarr.items(): print(linename) f = open(line_def_file[:len(line_def_file)-5]+"_"+sys.argv[1]+"_"+linename+".csv", 'w', encoding='utf-8', newline='') write = csv.writer(f) write.writerow(["stream_id","linename","tracking_id","start_time_jp","end_time_jp","passing_judge","passing_time"]) for tracking_id, record in records.items(): write.writerow([record['stream_id'],linename,tracking_id,record['start_time_jp'],record['end_time_jp'],record['passing_judge'],record['passing_time']]) f.close() ===== 第三項 座標をUIで設定する ===== さて、前項でライン判定まではできるようになったので、WEBUIを利用してみましょう\\ 今まではtutorialフォルダのみで作業していましたが、次は\\ cd ~/drawui でフォルダを切り替えましょう\\ ここではフロントエンド(WEB画面で表示される部分のプログラム)とバックエンド(フロントエンドのプログラムから指示されてデータを保存したり出力したりする部分のプログラム)両方を兼ね備えており、\\ ./start.sh を押してしばらく待てば\\ [[http://解析端末のIP/]]\\ で\\ {{::peopletracker_drawui01.png?400|}}{{:peopletracker_drawui02.png?400|}}{{:peopletracker_drawui03.png?400|}}\\ などの画面にアクセスすることができます。\\ この画面では\\ - ナビゲーションページ - カメラから静止画を取得して、その上に複数の多角形を設定できるページ - カメラから静止画を取得して、その上に複数の線分を設定できるページ - カメラからリアルタイム映像を取得して、その上に複数の多角形を設定できるページ - カメラからリアルタイム映像を取得して、その上に複数の線分を設定できるページ - SCORER People Trackerで保存した見取り図を取得して、その上に複数の多角形を設定できるページ - SCORER People Trackerで保存した見取り図を取得して、その上に複数の線分を設定できるページ が用意されています。\\ エリアや線分を追加してsaveボタンをおすことでJSONファイルに結果が保存され、次回表示時にもその結果が表示されます\\ 2と4、3と5は同じ設定値を参照していますので、どちらかで更新すればもう片方に反映します。\\ データの出力先はdrawuiフォルダ内の\\ camareas.json camlines.json sketchareas.json sketchlines.json となっており、JSON形式は前章までで利用していたものと同じになります。\\ 利用を終了する場合はTerminal上でCtrl+Cでサーバーが止まります。\\ スターターコードの完成の項でデータのつなぎ込みをしてみましょう\\ ===== 第四項 Reactについて ===== drawuiで利用しているのはReactという最近のWEB開発ではデファクトスタンダード(事実上の業界標準)となりつつある技術を利用しています。\\ 昔のイメージのHTMLファイルをページごとに作成して表示というものではなく、1つのindex.htmlに複雑なjavascriptを追加することで、スマホのアプリのような動きのある自由な表現が可能になる仕組みです。 そのため、解説しているサイトや本は日本でも多数でてきています。\\ 公式ページも日本語で公開されており、技術に興味がある人は\\ [[https://ja.reactjs.org/docs/getting-started.html]]\\ 等から学び始めることがよいでしょう。\\ ただし今回はReact自体が分からなくても、どのプログラムファイルをどういじれば何が変わるかという点だけでピンポイントで上級編の一環として解説していこうと思いますので、本チュートリアルを進めるうえではReactの学習は必須ではありません。\\ ===== 第五項 WEBサーバーの解説===== WEBサーバーについては今回FlaskというPythonで簡単にWEBサーバーを構築できる仕組みを採用します。\\ Flaskでは\\ from flask import Flask app = Flask(__name__) @app.route('/') def hello_world(): return "Hello World!" if __name__ == '__main__': app.run(host='0.0.0.0', debug=False, port=80) だけで\\ python app.py を実行すると[[http://解析端末のIP/]]でアクセスができ、白い画面に「Hello World!」と表示されWEBページが見れることを確認できます。\\ 今回はHello World!ではなく、Reactで作ったコードにアクセスできるように設定します。スターターコードの\\ app = Flask(__name__, static_folder="./build/static", template_folder="./build") (中略) @app.route("/") def index(): return render_template("index.html") @app.errorhandler(404) def not_found(e): return render_template("index.html") がその設定になり、トップページと、何もないページにアクセスした場合強制的にトップページを表示するという設定となります。Reactを使う上ではこういうものだと思ってもらえれば大丈夫です。\\ なお、このFlaskでのWEBページ公開方法は開発用となっており、インターネットで大量にアクセスしてくるような大規模な本番用WEBページには非推奨です。\\ 昔から有名なApacheや最近はNginxなどのWEBサーバーがよく使われています。\\ ですが、SCORER Edge上で少数の人間がアクセスしてくる分には全く問題ありません。\\ ===== 第六項 APIサーバーの解説 ===== 描画画面でエリアや線分を設定したあと、そのデータを保存したり、ページ表示時に読み込んだりする部分のプログラム(API)についての解説ですが、今回は特殊な方法を使っているため、WEBサーバー公開と同じserver.py内で処理が行われています。 import os import sys from flask import Flask, json, jsonify, request, render_template app = Flask(__name__, static_folder="./build/static", template_folder="./build") def get_file(filename): print(f'{filename}') try: with open( f'{filename}', 'r', encoding='utf8') as infile: file = json.load(infile) except Exception: return jsonify(reason='Not Found', message='Existing file not found.'), 404 else: return file def save_file(filename, data): try: with open(f'{filename}', 'w', encoding='utf8') as infile: json.dump(data, infile) except Exception: return ( jsonify(reason='Internal Server Error', message='A fatal error occurred while trying to save line data'), 500 ) return data, 200 @app.route("/") def index(): return render_template("index.html") @app.errorhandler(404) def not_found(e): return render_template("index.html") @app.route('/api/camareas', methods=['GET', 'PUT']) def camareas(): if request.method == 'GET': return get_file('camareas.json') elif request.method == 'PUT': return save_file('camareas.json',request.json) else: return {'message': 'Method not allowed.'}, 405 @app.route('/api/sketchareas', methods=['GET', 'PUT']) def sketchareas(): if request.method == 'GET': return get_file('sketchareas.json') elif request.method == 'PUT': return save_file('sketchareas.json',request.json) else: return {'message': 'Method not allowed.'}, 405 @app.route('/api/camlines', methods=['GET', 'PUT']) def camlines(): if request.method == 'GET': return get_file('camlines.json') elif request.method == 'PUT': return save_file('camlines.json',request.json) else: return {'message': 'Method not allowed.'}, 405 @app.route('/api/sketchlines', methods=['GET', 'PUT']) def sketchlines(): if request.method == 'GET': return get_file('sketchlines.json') elif request.method == 'PUT': return save_file('sketchlines.json',request.json) else: return {'message': 'Method not allowed.'}, 405 if __name__ == '__main__': app.run(host='0.0.0.0', debug=False, port=80) 10-30行目が読み出しや保存に関するコード\\ 39-73行目はどのURLにアクセスして来たらどういう動き(どのファイルを保存・読み出しするか)かを定義しています。\\ ===== 第七項 スターターコードの完成 ===== 第四項のコードからの変更として、\\ * 保存ファイルの読み出し先を変更する ということを行います。\\ import sys import os import json import math from datetime import datetime, timedelta, timezone import csv import glob import numpy as np def intersect(p1, p2, p3, p4): tc1 = (p1[0] - p2[0]) * (p3[1] - p1[1]) + (p1[1] - p2[1]) * (p1[0] - p3[0]) tc2 = (p1[0] - p2[0]) * (p4[1] - p1[1]) + (p1[1] - p2[1]) * (p1[0] - p4[0]) td1 = (p3[0] - p4[0]) * (p1[1] - p3[1]) + (p3[1] - p4[1]) * (p3[0] - p1[0]) td2 = (p3[0] - p4[0]) * (p2[1] - p3[1]) + (p3[1] - p4[1]) * (p3[0] - p2[0]) return tc1*tc2<0 and td1*td2<0 if __name__ == '__main__': dirpath = 'data' line_def_file = os.environ['HOME']+'/drawui/camlines.json' JST = timezone(timedelta(hours=+9), 'JST') print(sys.argv[1]+"を集計しています・・") file_list = sorted(glob.glob('./'+dirpath+'/'+sys.argv[1]+'/raw_'+sys.argv[1]+'*.json')) print("対象ファイル一覧") for filename in file_list: print(filename) json_open = open(line_def_file, 'r') result_json_file = open('result_camlines_'+sys.argv[1]+'.json', 'w') linedef = json.load(json_open) resultarr = {} for lineidx, line in enumerate(linedef['lines']): linename='lineID'+str(lineidx) print(linename) resultarr[linename]={} print("集計・・") for lineidx, line in enumerate(linedef['lines']): linename='lineID'+str(lineidx) print(linename) polygon = [] print(line) for point in line['points']: polygon.append([point['x'],point['y']]) for filename in file_list: print(linename+"_"+filename) if os.path.getsize(filename) == 0: continue raw_json_open = open(filename, 'r') raw_json = json.load(raw_json_open) for frame in raw_json: jptime = datetime.fromtimestamp(frame['frame_time'],JST) people = frame['objects'] for person in people: #print(linename+'_'+person['tracking_id']+'_'+str(judgenum)) personpos = [(person["x0"]+person["x1"])/2,person["y1"]] if person['tracking_id'] in resultarr[linename]: if intersect(personpos,resultarr[linename][person['tracking_id']]['prev_pos'],polygon[0],polygon[1]): resultarr[linename][person['tracking_id']]['passing_judge'] = True resultarr[linename][person['tracking_id']]['passing_time'] = jptime.isoformat() resultarr[linename][person['tracking_id']]['end_time'] = frame['frame_time'] resultarr[linename][person['tracking_id']]['end_time_jp'] = jptime.isoformat() else: resultarr[linename][person['tracking_id']]={'line':linename,'start_time_jp':jptime.isoformat(),'end_time_jp':jptime.isoformat(),'start_time':frame['frame_time'],'end_time':frame['frame_time'],'stream_id':frame['stream_id'],'passing_judge':False,'passing_time':0,'prev_pos':personpos} json.dump(resultarr,result_json_file) for linename, records in resultarr.items(): print(linename) f = open("camlines_"+sys.argv[1]+"_"+linename+".csv", 'w', encoding='utf-8', newline='') write = csv.writer(f) write.writerow(["stream_id","linename","tracking_id","start_time_jp","end_time_jp","passing_judge","passing_time"]) for tracking_id, record in records.items(): write.writerow([record['stream_id'],linename,tracking_id,record['start_time_jp'],record['end_time_jp'],record['passing_judge'],record['passing_time']]) f.close() 実際変更するところは20行目のみで、ファイルの参照先をtutorial内ではなく隣のdrawuiフォルダのcamlines.jsonに切り替えています。\\ さて、これでカメラ座標系の設定としては洗練されたものになりましたが、そのまま見取り図座標での設定ができるようにコードを変更していきましょう。\\ import sys import os import json import math from datetime import datetime, timedelta, timezone import csv import glob import numpy as np def intersect(p1, p2, p3, p4): tc1 = (p1[0] - p2[0]) * (p3[1] - p1[1]) + (p1[1] - p2[1]) * (p1[0] - p3[0]) tc2 = (p1[0] - p2[0]) * (p4[1] - p1[1]) + (p1[1] - p2[1]) * (p1[0] - p4[0]) td1 = (p3[0] - p4[0]) * (p1[1] - p3[1]) + (p3[1] - p4[1]) * (p3[0] - p1[0]) td2 = (p3[0] - p4[0]) * (p2[1] - p3[1]) + (p3[1] - p4[1]) * (p3[0] - p2[0]) return tc1*tc2<0 and td1*td2<0 if __name__ == '__main__': dirpath = 'data' line_def_file = os.environ['HOME']+'/drawui/sketchlines.json' JST = timezone(timedelta(hours=+9), 'JST') print(sys.argv[1]+"を集計しています・・") file_list = sorted(glob.glob('./'+dirpath+'/'+sys.argv[1]+'/raw_'+sys.argv[1]+'*.json')) print("対象ファイル一覧") for filename in file_list: print(filename) json_open = open(line_def_file, 'r') result_json_file = open('result_sketchlines_'+sys.argv[1]+'.json', 'w') linedef = json.load(json_open) resultarr = {} for lineidx, line in enumerate(linedef['lines']): linename='lineID'+str(lineidx) print(linename) resultarr[linename]={} print("集計・・") for lineidx, line in enumerate(linedef['lines']): linename='lineID'+str(lineidx) print(linename) polygon = [] print(line) for point in line['points']: polygon.append([point['x'],point['y']]) for filename in file_list: print(linename+"_"+filename) if os.path.getsize(filename) == 0: continue raw_json_open = open(filename, 'r') raw_json = json.load(raw_json_open) for frame in raw_json: jptime = datetime.fromtimestamp(frame['frame_time'],JST) people = frame['objects'] for person in people: #print(linename+'_'+person['tracking_id']+'_'+str(judgenum)) personpos = [person["floor"]["x"],person["floor"]["y"]] if person['tracking_id'] in resultarr[linename]: if intersect(personpos,resultarr[linename][person['tracking_id']]['prev_pos'],polygon[0],polygon[1]): resultarr[linename][person['tracking_id']]['passing_judge'] = True resultarr[linename][person['tracking_id']]['passing_time'] = jptime.isoformat() resultarr[linename][person['tracking_id']]['end_time'] = frame['frame_time'] resultarr[linename][person['tracking_id']]['end_time_jp'] = jptime.isoformat() else: resultarr[linename][person['tracking_id']]={'line':linename,'start_time_jp':jptime.isoformat(),'end_time_jp':jptime.isoformat(),'start_time':frame['frame_time'],'end_time':frame['frame_time'],'stream_id':frame['stream_id'],'passing_judge':False,'passing_time':0,'prev_pos':personpos} json.dump(resultarr,result_json_file) for linename, records in resultarr.items(): print(linename) f = open("sketchlines_"+sys.argv[1]+"_"+linename+".csv", 'w', encoding='utf-8', newline='') write = csv.writer(f) write.writerow(["stream_id","linename","tracking_id","start_time_jp","end_time_jp","passing_judge","passing_time"]) for tracking_id, record in records.items(): write.writerow([record['stream_id'],linename,tracking_id,record['start_time_jp'],record['end_time_jp'],record['passing_judge'],record['passing_time']]) f.close() 20行目参照JSONファイルの変更と61行目人物の座標を座標を見取り図上のものを利用するだけの変更するだけにとどまりました。\\ これでスターターコードは完成です。\\ ===== 第八項 エリア検知のUI連携 ===== ついでにエリア検知もUIで設定できるようにしましょう。変更箇所の解説はあまりいらないかと思いますので、結果プログラムを見てください。 import sys import os import json import cv2 import math from datetime import datetime, timedelta, timezone import csv import glob import numpy as np if __name__ == '__main__': dirpath = 'data' duration = 5 area_def_file = os.environ['HOME']+'/drawui/sketchareas.json' JST = timezone(timedelta(hours=+9), 'JST') print(sys.argv[1]+"を集計しています・・") file_list = sorted(glob.glob('./'+dirpath+'/'+sys.argv[1]+'/raw_'+sys.argv[1]+'*.json')) print("対象ファイル一覧") for filename in file_list: print(filename) json_open = open(area_def_file, 'r') result_json_file = open('result_sketchareas_'+sys.argv[1]+'.json', 'w') areadef = json.load(json_open) resultarr = {} for areaidx, area in enumerate(areadef['areas']): areaname='areaID'+str(areaidx) print(areaname) resultarr[areaname]={} print("集計・・") for areaidx, area in enumerate(areadef['areas']): areaname='areaID'+str(areaidx) print(areaname) polygon = [] for point in area['points']: polygon.append([point['x'],point['y']]) contour = np.array(polygon) print(contour) for filename in file_list: print(areaname+"_"+filename) if os.path.getsize(filename) == 0: continue raw_json_open = open(filename, 'r') raw_json = json.load(raw_json_open) for frame in raw_json: jptime = datetime.fromtimestamp(frame['frame_time'],JST) people = frame['objects'] for person in people: #print(areaname+'_'+person['tracking_id']+'_'+str(judgenum)) personpos = [person["floor"]["x"],person["floor"]["y"]] test = cv2.pointPolygonTest(contour, personpos, False) if test>0: if person['tracking_id'] in resultarr[areaname]: resultarr[areaname][person['tracking_id']]['end_time'] = frame['frame_time'] resultarr[areaname][person['tracking_id']]['duration'] = frame['frame_time']-resultarr[areaname][person['tracking_id']]['start_time'] resultarr[areaname][person['tracking_id']]['end_time_jp'] = jptime.isoformat() if resultarr[areaname][person['tracking_id']]['duration'] > duration: resultarr[areaname][person['tracking_id']]['stop_judge'] = True else: resultarr[areaname][person['tracking_id']]={'area':areaname,'start_time_jp':jptime.isoformat(),'end_time_jp':jptime.isoformat(),'start_time':frame['frame_time'],'end_time':frame['frame_time'],'stream_id':frame['stream_id'],'duration':0,'stop_judge':False} json.dump(resultarr,result_json_file) for areaname, records in resultarr.items(): print(areaname) f = open("sketchareas_"+sys.argv[1]+"_"+areaname+".csv", 'w', encoding='utf-8', newline='') write = csv.writer(f) write.writerow(["stream_id","areaname","tracking_id","start_time_jp","end_time_jp","total_duration","stop_judge"]) for tracking_id, record in records.items(): write.writerow([record['stream_id'],areaname,tracking_id,record['start_time_jp'],record['end_time_jp'],record['duration'],record['stop_judge']]) f.close()