#author("2021-02-24T06:38:51+00:00","","") #author("2021-02-26T05:51:45+00:00","","") [[技術資料]] *目次 [#e890b3d5] #CONTENTS **目的 [#z78b3c7b] 生体・環境センサを用い、数値からストレス値を計測.行動識別から現時点での場所,状態を取得しストレス値を検知したらコーピングを実施する.コーピングは状況に応じた内容を被験者に指示を出し,実行させることで実現させる.コーピング指示はスマートグラスにARオブジェクトを表示させて知らせる.この流れを通じ人間の精神的身体的負担削減を目指す~ ~ ~ ***使用するファイル全部 [#ta19c6d2] |扱うデータ|なにする|ファイル名|ファイルの場所| |生体・環境データ|音声以外のデータ取得|newsensa_all_esk_3.py|ラズパイ| |音声テキスト|デンドログラムのラベリング取得|gasmic_esk_2.py|ラズパイ| |↑の二つ|送信するためファイルとして保存|sendata.json,sendata2.json|ラズパイ| |↑の二つ|↑のファイルが作成されたらサーバーに送信する|sendata.py|らずアピ| |↑の二つ|↑のプログラムから受信したらサーバーに蓄積|processing_data_server2.py|サーバー| |↑の二つ|↑で蓄積したファイル|fordend.xslx,fordend2xslx|サーバー| |蓄積された全データ|クラスター分析、ライフログ作成、コーピング処理、html編集|processing_data_server.py|サーバー| |取得したデータ|ライフログ作成モデル|model.bin|サーバー| |取得したデータ|ライフログ|fordend.csv|サーバー| |識別とストレス状態|ネットに公開しユーザーに通知|Image2.html|サーバー(メイン)| |なし|htmlに表示|1.png,2,jpg,5.jpg|サーバー| |htmlの記録|コーピングの有無ととストレス状態を記録|foo.csv|サーバー| |ライフログ|センサデータとLF/HFだけを記録|koo.csv|各自のPC | |↑|センサデータとストレス状態の分析|stress_decision_tree.py|各自のPC| 決定木に関しては使うモジュールのインストールがややこしかったのと決定木分析がオマケみたいな扱いなのと実験の最後にやるもんでリアルタイム性がいらないの理由で、サーバーのfordend.xslxとfordend2.xlsxをGoogleドライブに書き込んで自分のPCでIoTのやり方でやりました。~ **開発ツールの決定 (ARを作る場合) [#m0fcb0ef] 主に使用するデバイスによってツールをインストールする。~ |使用端末|android|iOS| ||ARCore|ArToolkit| ***使用端末がEPSON開発・MOVERIO-BT300の場合 [#d1f0219d] ARグラスとして扱いやすいものを選んだ。~ この端末はARCoreをサポートしていないのでVuforiapositionも使用できない。~ なのでARの使用範囲がかなり狭いです ~ *コーピング処理 [#ccda06db] 以降は生態環境情報の取得する方法を習得している前提で記録する~ ***[[センサとマイコン(Arduino, Raspberry Pi)による行動分類]] [#p93c5eab] ~ ここでprocessing_data.py,newsensa_all.pyが正常に動いて~ デンドログラムが表示され、センサ数値が取れているようなったら次行けます~ ~ **1.データ取得 [#c9661663] &size(25){以降はproscessing_data.pyのデンドログラム表示関数に書き加えていきます}; ~ 表示用に取得,算出するデータ~ |コード変数|now_time|location|situation|total_time|stress_data|state|cope|figure| |html|Today|場所|状況|経過時間|ストレス予測値|状態|指令|画像| ***1.1 音声入力による現在地と状況(location,situation) [#uff6c3d3] csvファイルに保存,デンドログラム作成に関しては先行研究あんので省略~ ラベリングは一回しか行わないので最新がどのラベルの行動分析と一致するかを探る.~ 今回は場所と状態の2単語をマイクで入力する~ ***マイク入力のコツ! [#c0fff484] 1.「Okgoogle」のあと1秒待ってマイクをオフ。最短で入力できる~ 2.「机」(1秒待つ)「パソコン」(1秒待つ)マイクオフで確実に入る~ 3.processing_data.pyのラベル同期の部分で秒数が指定してあるからセンサの間隔と合わせる~ 4.「鬼滅の刃」とかは入らない「千の風になって」は全部入った~ ~ #ref(2.JPG) このデンドログラムからわかるように、同じ行動=色でラベルは一つしかないしラベルされてない色もある.~ 縦軸の関連度を表すユーグリッド距離を指定し,色付けされている.約2000で場所ごとに分けられることが分かっている.(吟味する必要あり)~ そこで最新地を識別するには色別に分ける必要がある~ #leaf_rotation=0がラベルの向き、orientation="top"がクラスタリングの図の方向 #color_threshold=xでユークリッド平方距離がx以上を同色で表示 #above_threshold_color="color"でユークリッド平方距離がx以上を"color"色に染める ##最新ラベルとラベルされているデータの距離が2000以内の場合同じ場所として判別##### dendrogram(Z, labels=df_label,leaf_rotation='vertical',leaf_font_size=16,color_threshold=2000,above_threshold_color='gray') #各データのクラスター番号出力 group = fcluster(Z, 2000, criterion='distance') groupリストには時系列でクラスター番号が格納される.つまり色ごとに番号が与えられた。~ つづいてcsvファイルから必要なデータをコード内にリストで出力する~ df['時間'] = pd.to_datetime(df['時間'],format='%Y%m%d %H:%M:%S') frame_time = pd.to_datetime(df['時間'],format='%Y%m%d %H:%M:%S') gsr=df['GSR'].to_list() snp=df['心拍数'].to_list() loc_label=df['mic'].to_list() list_time=frame_time.to_list() このリストからラベルとクラスター番号を関連付けるためにリストをつくる~ loc_c = [] //入力した分だけのラベルの配列 loc_d = [] //入力した分だけのラベルのクラスター番号の配列 loc_b = [] //クラスター番号とラベルの合体配列.サイズはデータ数 loc_label //リスト型のラベル配列 loc_num = [] //リスト型のクラスター番号配列 for num in group: loc_num.append(num) loc_b = list(zip(loc_num, loc_label)) このloc_bリストにクラスター番号とそのラベルがセットになって格納されているが、ラベルはほとんどがnanというflort形の空データなので除外する。~ for i in loc_label: if isinstance(i, str): loc_c.append(i) print(loc_c) for j,k in zip(loc_num, loc_label) : if isinstance(k,str): loc_d.append(j) print(loc_d) print("合体") print(list(zip(loc_c,loc_d))) #ref(12021.JPG) 上からloc_c,loc_d,ラベルとその番号がセットになったリスト ラベルにはマイクで「机 勉強中」などつづけて入力するのでこの入力を(場所)と(状況)に分ける必要がある~ nowpoint = group[length-1] //最新のクラスター番号 #最新地のクラスター番号を調べ、それに対応している場所を特定 if not nowpoint in loc_d: location = '不明 不明' else: for s,t in zip(loc_d, loc_c): //最新のクラスター番号がラベリングリストにあったら場所が特定 if nowpoint == s: location = t #マイクで場所と状況を一度に入れているので分割 loc_sp = location.split() #print(loc_sp) location=loc_sp[0] situation=loc_sp[1] この(location)が場所、(situation)を状況、としてhtmlに書き込む~ ~ ~ ***1.2 現在地による行動経過時間(today,total_time) [#ad9614fa] 1.1でクラスター番号とラベリングした場所を関連付けられたので,最新と同じ状況をどれだけ続いているかを調べる.~ #ref(3.JPG) -デンドログラムは左からクラスターごとに,距離が近い順に並べられている.~ -クラスターの中に,マイクラベルが存在するライフログが一つは存在する.他はマイクラベルがない.~ -出力したクラスター配列は時系列である.番号はデンドログラムの左からクラスターごとに順に振り分けられる.~ つまりクラスター配列の最初の数字は7なのでデンドログラムでいう右端の緑色に当たる.~ よってライフログの序盤10個のデータは会議室のデータと分かる.~ -逆に配列の終盤は6が続いている.dん度ログラムから黒色,パソコン作業とわかる~ よって(ライフログ内では)現在コイツはパソコンパチパチしていることになる.~ さらに言うとライフログは約30秒に一回取得する.配列では6が30個以上続いているのでコイツは15分ぐらいパチパチしていると分かる。~ #場所が変わったかの判断と経過時間の算出 #前回と今回の値が一緒だったら時間を加算、違ったら計測しなおす #start_timeを用意しnow_timeと引き算して分を出す.行動変化したらそれをstaretimeに変更する if lastpoint != nowpoint: print("行動変化") start_time = now=time else : print("継続中") #start_timeの算出、一個ずつ戻っていって行動変化したときの時刻をstart_timeとする for g in range(len(group)): if nowpoint != group[length -2-g]: start_time = list_time[length -1-g] break #行動経過時間の算出 total_time=now_time-start_time #total_time = total_time.strftime("%H:%M:%S")...0dayを消したい print('START ' , start_time) print('NOW ' , now_time) print("TOTAL " , total_time) まずnowpoint=最新のクラスター番号とlastpoint=そのひとつ前のクラスター番号を比較.~ 同じなら同じ行動が続いている、違ったら行動が変わったということになる.~ その2つに応じてstart_time=計測開始時刻を設定する.行動が継続されていると判断された場合は一つ戻って比較,を繰り返す.~ 時間の演算はdatatimeを使えば簡単な引き算で求められる. #ref(12011.JPG) ~ ***1.3 生体センサによるストレス予測:その2(stress_data,state) [#cf1d2f7f] &size(20){数の微調整のため、ラズパイにarduinoIDEをインストールしておくと楽 }; ~ 王道:心拍からストレス値を出す~ 1.心電図からRRI間隔を出す~ さんざん悩んだけどよく考えたらRRIって心拍じゃん… 1/心拍ででるやん…~ 2.パワースペクトル密度を算出~ 詳しい理論は木下先生のの実験でも思い返して。データ数は1024はいるから心拍を配列にためてたまってから求める~ 3.高周波(HF)と低周波(LF)の面積を求める。LF/HFでストレス数値~ 4.個人差はあるけど2以上がやばい、5以上がかなりやばいと言われている~ ~ 処理はラズパイのnewsensa_all.pyのメインのところ、cnt<=5になっていると思うが、このcntを心拍配列にしておく~ 生体環境センサにくっつけて送信。IoTみろ。 ~ ~ 行動時間はtotal_secondsで経過時間を秒に直し、規定値(45分)と比べる~ processing_data.pyのstate決定するとこ,ついでにここでコーピングしない場合の図と指令も定義する(コーピング発動しない場合) #発動しない場合 if total_second_time < 2700 and stress_data <6.0: if stress_data <=2.0: state = '良好' figure='1.png' cope = 'No' else : state = '注意' figure='2.jpg' cope = '警告 : 危機が迫っている' #発動する場合 else:#コーピング内容をだらだらかく ~ #ref(newsensaall.py,,だいぶ絞ったnewsensa_all_1.py) ***1.4 3つの要素からコーピング内容決定 (cope,figure)[#l19ce9fe] ストレスが検知されたらコーピングを発動させる~ まず行動経過時間から長時間か短時間化を判別。~ 今回は60分(1,2時間)同じ行動だと判断されたら場所に応じた内容、短かったら行動自体に問題があるので行動切り替えを促す~ (本人が気づかぬうちに長時間行動で身体的負担が増すことを防止する)~ また想定される場所に応じて、(ストレス感じる内容を把握)適度なコーピングを示したい。~ いろいろ調べてもコーピング内容はほぼ一緒だったので、その行動が可能かを踏まえた。~ (会議中だったら休憩には入れないなど) #ref(1131.JPG,,60%) 。~ #スプレッドシートの単語から #if ('computer' and 'monitor') in camera11: #とりあえずPC操作にしておいた # cope2 = 'コンピューター操作により' # cope3 = '休憩に入り、目を休め' #行動識別から if 'パソコン' in situation: cope2 = 'コンピューター操作により' cope3 = '休憩に入り、目を休め' elif '会議'in situation: cope2 = '会議中なので' cope3 = 'ちょっと休め、耐えろ' elif '休'in situation: cope2 = '休憩でも' cope3 = '止めなさい' elif '天井'in location: cope2 = 'お前' cope3 = '休みすぎ' elif 'kichen'in location: cope2 = '打ち合わせより' cope3 = '止めた方がいいんじゃない' else: cope2 = 'その他の行動により' cope3 = '気分展開しよう' #とりあえす経過時間が長かった(90分以上,30分以上,それ以下)ら if int(total_time.total_seconds()) > 2400: print("長すぎ") cope1 = '長時間行動より' elif int(total_time.total_seconds()) > 1800: print("長時間行動") cope1 = '長時間行動と' else: print("短時間労働") cope1 = '行動は短いが' #cope3 = '行動を止めたほうがいい' state = '要注意、コーピングを実行' figure = '5.jpg' cope= cope1+cope2+cope3 *ウェブ表示法アシスト:GooGle経由の場合 [#c37f58b5] &size(15){追記:pyにhtml直書きにしてテキストファイル経由しないようにした}; データをドライブに保存し,自身のPCでcsvファイルにログを備蓄したあと,データをもとにhtmlを作成する.~ 流れはcsvファイルを編集するコード(py),表示されるウェブページ(html),MOVERRIO(グラス)の順で表示する~ #ref(87.JPG,,70%) 1.収集したデータをもとに表示する文字を作成(選択)~ 2.processing_data.py内で編集、htmlファイルの文字を書き直す形で編集する~ 3.htmlファイルができる~ 4.PC(Windowsの場合)htmlがある📁のパスを通す.~ Internet Information service (IIS)のDefault WebSiteの「機能ビュー」の「詳細設定」で📁物理パスを設定.~ さらに「既定のドキュメント」に追加.~ 5.こうするとPCと同一Wi-Fi内でのみ「http://(PCの物理アドレス)」でグラスにhtmlが表示される.~ ~ ・py内のhtmlファイル編集~ #コーピング発動html opendata = r"C:/Users/wasaza/Desktop/nana/nan.html" with open(opendata, mode='w+', encoding="utf_8") as f: data_line4=('<!DOCTYPE html>\n<head>\n<meta http-equiv="content-type" charset="utf-8">\n</head>\n<body>\n<div style="font-size:small">\n') data_line5=('<br>\n</div>\n</body>\n<img src=' + figure + ' width="60"></html>') data_lines=('場所 :' + location + '<br>\n状況 :' + situation + '<br><br>\n\n経過時間 :' + str(total_time) + '<br>\n') data_lines2 = ('ストレス予測値 :' + str(stress_data) + ' / 状態 :'+ state+'<br>\n指令 :'+cope) data_lines3=('Today :' + str(now_time) + '<br>\n') f.write(data_line4) f.write(data_lines3) f.write(data_lines) f.write(data_lines2) f.write(data_line5) ~ GooGleスプレッドシート云々はIoTのページ見ろ~ ラズパイ,グラス,実行PC(個人のノーパソで十分)を同一Wi-Fiに接続し,表示する.ただしコーピング処理を行う実行PCは,スペック低いノーパソは勧めん。~ ~ ~ ・IISの設定 #ref(11102.JPG,,50%) ・実際表示されたhtml #ref(13.JPG) winscpのミラーリング機能を使ったら時間限定で~ パソコンで変更しても研究室のサーバーから発信できたので~ 学外のスマートグラスでも見れるようになった~ ~ ~ *研究室サーバー:Google経由しない場合 [#a17a2d66] ~ #ref(arg2.JPG,,80%) ***データの流れ [#b64087fd] 0.サーバー側のserver.pyと、ラズパイ側のsendata.pyをソケット通信~ 1.newsensa_all.pyでマイク以外のセンサデータを30秒毎取得しjsonファイルを作成、gasmic.pyで音声データを任意のタイミングで取得しjsonファイルを作成~ 2.sendata.pyでjsonファイルが生成されたらサーバーに送信。その後送ったファイルは消す。~ 3.送られてきたデータサイズでセンサデータかマイクデータか識別、各々のxlsxファイルに保存~ 4.processing_data.pyでxlsxファイルにアクセス、新規データ含めライフログ作成、クラスター分析しhtml作成~ 5.コーピングしたか(1,0)とかLH/HFとかをストレスログ(foo.csv)に保存~ 6.同フォルダにあるhttps通信設定したhtmlファイルが更新される。(htmlのhttps設定は横井さんがやってくれたから全然わかんない)~ ~ #ref(232.JPG,,50%) ~ ***MOVERIOにhtmlを映す方法 [#i5d236cb] 1.htmlをhttps通信で公開~ 2.何らかのスマホ(デザリングしたスマホ?)で開く~ 3.そのスマホにAuto Refreshアプリをダウンローそしてchromeを30秒で更新~ 4.そのスマホとMOVERIOをミラキャスト。スマホはAndroidがいい?iPhoneは分からん~ 5.つまりMOVERIOにスマホ画面を表示させる。~ ~ **実際の流れ [#j1f1f074] **1.ラズパイでデータを取得 [#da8f96b0] ラズパイ装置を身に着け、プログラムを動かす~ この時VNCでラズパイを実行すると外に出られなくなるからなんかのディスプレイにHDMIで表示して操作したほうがいい。~ ラズパイとグラスはテザリングしたスマホのWi-Fiニッ接続しておく~ newsensa_all.pyで生体・環境センサデータ。gasmic.pyで音声データ。~ 心拍データを取るのに最初は5分かかるからその間にサーバーを動かす。~ ~ **2.サーバーを動かす [#pb5df19e] 自分のパソコンでコマンドプロンプトを2つ起動する[「ssh iie.lab.tpu@~」ってやってコードがある📁まで移動する(移動の仕方はサーバーの管理者に聞いて)~ proseccing_data_sever2.pyを実行しソケット通信で待機する。~ もう一つのコマンドプロンプトでproseccing_data_sever.pyの実行する準備をしておく。~ ~ **3.ソケット通信を行う [#cc66f51f] もうすぐ5分が経とうとしたあたりでラズパイのsendata.pyを実行しソケット通信ができたら成功。~ proseccing_data_sever2.pyのコマンドプロンプトに「stay」、sendata.pyの実行画面に「wait」と表示されたらOK~ HDMIをぶっこ抜いてprocessing_data\sever.pyを実行し自由に行動をとる~ ~ **4.行動を行う [#b3c4137b] 行動を変えるたびにマイクで「場所 状況」を入力する。ホットワード含め入力できたかはボードのランプを見れば分かる。~ 入力後にランプが点滅したら成功。~ グラスのHTMLが更新されなくなったらなんか不具合が起きたのでもう一度HDMI接続しなおしてみる。~ ◎考えられる不具合~ -カメラセンサが何かで覆われてデータが取得できなかった。processing_data_server.pyのコマンドプロンプトに「camera[i][r] リストの数が合わない」みたいなエラーが出た場合 --fordend.xlsxのカメラテキストで1単語しかない場所を探し出しなんでもいいから1単語追加する。 -生体センサが取れなかった。 --ラスパイのnewsensa_all.pyを実行しなおす。 -ソケット通信が途切れた --ラズパイの方でWi-Fiが切り替わった可能性がある。テザリングでも切り替わったらラズパイの方で設定する必要がある(かなりめんどい、テザリングの場合はそうおこらない) -LF/HFグラフが更新されない --アドレスから表示しなおす。なぜか別の端末で見ると更新されている。 実行と無視を行う場合、最後の実行指令に従いコーピングを行う~ 本来は無視とかどーでもいい~ ~ **5.(実験後)検証 [#i7d0ce66] ***検証の準備 [#y49a8698] ・windowsの場合、Macは知らん~ サーバーにセンサデータ(fordend.xlsx,fordend2.xlsx)とライフログ(fordend.csv)とストレスログ(foo.csv)が記録されている、はず~ それらを見るためにwinSCPというサーバーを遠隔操作するソフトをインストールしておく ~ winSCPを開いたら~ -raspi@133.55.115.240アカウントにログイン -ファイル消す?って表示出るけど&COLOR(red){絶対に消さない}; -転送プロトコル→SFTP、ホスト名→133.55.115.240、ポート番号→22、ユーザー名→raspi、パスワード→(秘匿) -/var/www/htmlのフォルダに移動 -見るとさっきのファイルや実行コードを開くことができる。多分そのアカウントで編集もできる -ちなみにコードを編集するときはプログラムで編集を選択してVS Codeのpathを渡せばそれで編集できるで -koo.csvとfordend.csvを自分のPCのフォルダに映したら準備OK~ アカウントや権限に関しては管理者に一任します ***検証1 LF/HFの変化の検定 [#k5fc1ebf] 実験後、foo.csvには実験中のHTMlの情報が記録されている。~ つまり1分ごとのLF/HFなどが記録されている。~ Excelで開いてグラフ作ってLF/HFの変移が分かる~ &COLOR(red){ちなみにcsvファイルをExcelで開いてグラフを作っても保存されないから適当にxslxファイルに丸写しして作成したほうがいい};~ &COLOR(red){もしくはグラフ作ったらキャプチャして残す。二度と見れなくなるけど};~ こんな表を用意する |無視前|無視後|差(後―前)|実行前|実行後|差(後ー前)| ◎検定方法~ コーピング発動したか(1か0、copenとする)とコーピングしたか(1か0、copegとする)を見て無視したときと実行したときのLF/HFの変化を見る~ まずcopenが0から1になった時、~ -copegが1だったらその時のLF/HFを表の「実行前」にかく -その時刻から3分後のLF/HFを表の「実行後」にかく -copegが0だったらその時のLF/HFを表の「無視前」にかく -その時刻から3分後のLF/HFを表の「無視後」にかく 次にcopenが1のままcopegが0から1もしくは1から0になった時~ -copegが1だったらその時のLF/HFを表の「実行前」にかく(以下略)~ さらにcopenが1のままcopegが0から0、もしくは1から1になった時~ -だいたい3分程度でcopegが変わるからそのタイミングを推測する~ -copegが1だったらその時のLF/HFを表の「実行前」にかく -その時刻から3分後のLF/HFを表の「実行後」にかく -その次のLF/HFを表の「実行前」に書く -その時刻から3分後のLF/HFを表の「実行後」にかく -copegが0だったらその時のL(略) 記録が終わったら差分を計算して両方の差を求める。~ つづいてF検定を行う。変数は無視の差(後ー前)と実行の差(後ー前)の2つ(習ったやろから省略)~ F検定で等分散性があるかないかでちがうT検定を行う~ 検定のタイトルが(等分散性があると仮定したT検定とかだったから見りゃわかる)~ T検定のP値が0.05以下なら2つの変数には有意な差があると断定できる~ つまりコーピング実行と無視したときではLF/HFの変化の仕方が違うと言える~ ***検証2 全センサデータの決定木分析 [#e3a1f1ff] まずkoo.csvを用意する~ ワイのドライブに使用したkoo.csvがあるからデータを消して(1列目のラベルだけ残す)おく~ 実はprocessing_data_sever.pyの最後にstress_decision_tree.pyを実行するようになってんだけどサーバーにtreeをインストールするのがだるいから自分のパソコンに入れた ~ というわけでまず自分のPCにtreeモジュールとgraphvizをネットで調べてインストールしろ(ワイのドライブに一応ある)~ インストールできたらさっき自分のPCに入れたfordend.csvとkoo.csvと同じフォルダにワイのドライブにあるpython.pyをダウンロードして実行する~ そのフォルダ内に決定木結果(tree.png)が作成される。~ stress_decision_tree.pyのフォルダ名とかをちゃんと変更しておくこと~ ~ ちなみになぜかサーバーで実行するとデンドログラムが表示されない、LF/HFのグラフは作成されるのに~ 本研究ではデンドログラムはぶっちゃけいらんのやけど行動識別できているか確かめるために作成しなきゃいけない~ [[ワイが作ったゼミ用の>ライフログからコーピングhtmlを作成]]ページに「processing_data_2.py」がある。~ これはスプレッドシートにアクセスせずに同じフォルダにあるfordend.csvからデンドログラムとコーピング処理を行うプログラムになっている。~ これを実行するとデンドログラムがどべーーんって作成され、den.pngが保存される、はず~ #ref(226.JPG) 以上 **使ったコード全部 [#s8144bcb] 江崎のドライブに全部ある、はず~ 江崎のドライブに全部ある、はず名前が若干違うかも~