tutorial_3

差分

このページの2つのバージョン間の差分を表示します。

この比較画面へのリンク

両方とも前のリビジョン 前のリビジョン
次のリビジョン
前のリビジョン
tutorial_3 [2022/01/04 14:07] – [第五項 WEBサーバーの解説] satoshitutorial_3 [2022/01/05 10:49] (現在) – [第四項 Reactについて] satoshi
行 1: 行 1:
-====== 第3章 スターターコード【中級編 ライン判定(通過判定)】 ======+====== 第3章 ライン判定(WEBUIを使った通過判定)【中級編】 ======
 この章では、\\ この章では、\\
   * エリア検知からラインをまたいだ検知への応用   * エリア検知からラインをまたいだ検知への応用
行 265: 行 265:
 等から学び始めることがよいでしょう。\\ 等から学び始めることがよいでしょう。\\
  
-ただし今回はReact自体が分からなくても、どのプログラムファイルをどういじれば何が変わるかという点だけでピンポイントで解説していこうと思いますので、本チュートリアルを進めるうえではReactの学習は必須ではありません。\\+ただし今回はReact自体が分からなくても、どのプログラムファイルをどういじれば何が変わるかという点だけでピンポイントで上級編の一環として解説していこうと思いますので、本チュートリアルを進めるうえではReactの学習は必須ではありません。\\ 
 ===== 第五項 WEBサーバーの解説===== ===== 第五項 WEBサーバーの解説=====
 WEBサーバーについては今回FlaskというPythonで簡単にWEBサーバーを構築できる仕組みを採用します。\\ WEBサーバーについては今回FlaskというPythonで簡単にWEBサーバーを構築できる仕組みを採用します。\\
行 304: 行 305:
 ===== 第六項 APIサーバーの解説 ===== ===== 第六項 APIサーバーの解説 =====
 描画画面でエリアや線分を設定したあと、そのデータを保存したり、ページ表示時に読み込んだりする部分のプログラム(API)についての解説ですが、今回は特殊な方法を使っているため、WEBサーバー公開と同じserver.py内で処理が行われています。 描画画面でエリアや線分を設定したあと、そのデータを保存したり、ページ表示時に読み込んだりする部分のプログラム(API)についての解説ですが、今回は特殊な方法を使っているため、WEBサーバー公開と同じserver.py内で処理が行われています。
-一般的はWEBサバーとAPI部分別となっていが、+<sxh Python;title:server.py;highlight:10-30,39-73> 
 +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) 
 + 
 +</sxh> 
 +10-30行目が読み出しや保存関するコド\\ 
 +39-73行目どのURLにアクセスし来たらどうう動き(どファイルを保存・読み出しるか)かを定義しています。\\ 
 ===== 第七項 スターターコードの完成 ===== ===== 第七項 スターターコードの完成 =====
 +
 +第四項のコードからの変更として、\\
 +  * 保存ファイルの読み出し先を変更する
 +ということを行います。\\
 +<sxh Python;title:03outoftheline_cam_byui.py;highlight:20>
 +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()    
 +</sxh>
 +実際変更するところは20行目のみで、ファイルの参照先をtutorial内ではなく隣のdrawuiフォルダのcamlines.jsonに切り替えています。\\
 +
 +さて、これでカメラ座標系の設定としては洗練されたものになりましたが、そのまま見取り図座標での設定ができるようにコードを変更していきましょう。\\
 +<sxh Python;title:03outoftheline_sketch.py;highlight:20,61>
 +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()    
 +</sxh>
 +20行目参照JSONファイルの変更と61行目人物の座標を座標を見取り図上のものを利用するだけの変更するだけにとどまりました。\\
 +これでスターターコードは完成です。\\
 +
 +
 ===== 第八項 エリア検知のUI連携 ===== ===== 第八項 エリア検知のUI連携 =====
-===== 第九項 カメラ座標から見取り図座標への切り替え =====+ついでにエリア検知もUIで設定できるようにしましょう。変更箇所の解説はあまりいらないかと思いますので、結果プログラムを見てください。 
 +<sxh Python;title:03stopinfront_sketch.py> 
 +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 
 +    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()     
 +</sxh>
  
  • tutorial_3.1641272871.txt.gz
  • 最終更新: 2022/01/04 14:07
  • by satoshi