生体・環境センサを用い、数値からストレス値を計測.行動識別から現時点での場所,状態を取得しストレス値を検知したらコーピングを実施する.コーピングは状況に応じた内容を被験者に指示を出し,実行させることで実現させる.コーピング指示はスマートグラスにARオブジェクトを表示させて知らせる.この流れを通じ人間の精神的身体的負担削減を目指す
| 扱うデータ | 用途 | ファイル名 | ファイルの場所 |
| 生体・環境データ | 音声以外のデータ取得 | 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のやり方でやりました。
主に使用するデバイスによってツールをインストールする。
| 使用端末 | android | iOS |
| ARCore | ArToolkit |
ARグラスとして扱いやすいものを選んだ。
この端末はARCoreをサポートしていないのでVuforiapositionも使用できない。
なのでARの使用範囲がかなり狭い
以降は生態環境情報の取得する方法を習得している前提で記録する
ここでprocessing_data.py,newsensa_all.pyが正常に動いて
デンドログラムが表示され、センサ数値が取れているようなったら次行けます
以降はproscessing_data.pyのデンドログラム表示関数に書き加えていきます
表示用に取得,算出するデータ
| コード変数 | now_time | location | situation | total_time | stress_data | state | cope | figure |
| html | Today | 場所 | 状況 | 経過時間 | ストレス予測値 | 状態 | 指令 | 画像 |
csvファイルに保存,デンドログラム作成に関しては先行研究あるので省略
ラベリングは一回しか行わないので最新がどのラベルの行動分析と一致するかを探る.
今回は場所と状態の2単語をマイクで入力する
1.「Okgoogle」のあと1秒待ってマイクをオフ。最短で入力できる
2.「机」(1秒待つ)「パソコン」(1秒待つ)マイクオフで確実に入る
3.processing_data.pyのラベル同期の部分で秒数が指定してあるからセンサの間隔と合わせる
4.「鬼滅の刃」とかは入らない「千の風になって」は全部入った
このデンドログラムからわかるように、同じ行動=色でラベルは一つしかないしラベルされてない色もある.
縦軸の関連度を表すユーグリッド距離を指定し,色付けされている.約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))
#ref(): File not found: "12021.JPG" at page "平井さん卒論_backup"
この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)))
上から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.1でクラスター番号とラベリングした場所を関連付けられたので,最新と同じ状況をどれだけ続いているかを調べる.
#ref(): File not found: "3.JPG" at page "平井さん卒論_backup"
#場所が変わったかの判断と経過時間の算出
#前回と今回の値が一緒だったら時間を加算、違ったら計測しなおす
#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(): File not found: "12011.JPG" at page "平井さん卒論_backup"
数の微調整のため、ラズパイにarduinoIDEをインストールしておくと楽
王道:心拍からストレス値を出す
1.心電図からRRI間隔を出す
2.パワースペクトル密度を算出
周波数解析によって求めることができる。データ数は1024はいるから心拍を配列にためてたまってから求める
3.高周波(HF)と低周波(LF)の面積を求める。LF/HFでストレス数値
4.個人差はあるが2以上が注意、5以上が表注意と言われている
処理はラズパイのnewsensa_all.pyのメインのところ、cnt<=5になっていると思うが、このcntを心拍配列にしておく
生体環境センサにくっつけて送信。
行動時間は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(): File not found: "newsensaall.py" at page "平井さん卒論_backup"
ストレスが検知されたらコーピングを発動させる
まず行動経過時間から長時間か短時間化を判別。
今回は60分(1,2時間)同じ行動だと判断されたら場所に応じた内容、短かったら行動自体に問題があるので行動切り替えを促す
(本人が気づかぬうちに長時間行動で身体的負担が増すことを防止する)
また想定される場所に応じて、(ストレス感じる内容を把握)適度なコーピングを示したい。
いろいろ調べてもコーピング内容はほぼ一緒だったので、その行動が可能かを踏まえた。
#ref(): File not found: "1131.JPG" at page "平井さん卒論_backup"
#スプレッドシートの単語から
#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
追記:pyにhtml直書きにしてテキストファイル経由しないようにした
データをドライブに保存し,自身のPCでcsvファイルにログを備蓄したあと,データをもとにhtmlを作成する.
流れはcsvファイルを編集するコード(py),表示されるウェブページ(html),MOVERRIO(グラス)の順で表示する
#ref(): File not found: "87.JPG" at page "平井さん卒論_backup"
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)
ラズパイ,グラス,実行PC(を同一Wi-Fiに接続し,表示する。
・IISの設定
#ref(): File not found: "11102.JPG" at page "平井さん卒論_backup"
・実際表示されたhtml
#ref(): File not found: "13.JPG" at page "平井さん卒論_backup"
winscpのミラーリング機能を使ったら時間限定で
パソコンで変更しても研究室のサーバーから発信できたので
学外のスマートグラスでも見れるようになった
#ref(): File not found: "arg2.JPG" at page "平井さん卒論_backup"
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ファイルが更新される。
#ref(): File not found: "232.JPG" at page "平井さん卒論_backup"
1.htmlをhttps通信で公開
2.何らかのスマホ(デザリングしたスマホ?)で開く
3.そのスマホにAuto Refreshアプリをダウンローそしてchromeを30秒で更新
4.そのスマホとMOVERIOをミラキャスト。スマホはAndroidがいい?iPhoneは分からん
5.つまりMOVERIOにスマホ画面を表示させる。
pcを操作し、ラズパイからデータを受信できるよう設定する
・手順
1.pcでコマンドプロンプトを開く。
2.ssh iie.lab.tpu@133.55.115.240と入力する。(転送プロトコル→SFTP、ホスト名→133.55.115.240、ポート番号→22、ユーザー名→raspi、パスワード→(秘匿))
3.パスワードを要求されるので入力する。(パスワードは8*NJ9!$a%cKm)
4.sudo su -と入力すると、ルート権限を入手できる。また、その時に再度パスワードを入力する。
5.cd ..と入力する。
6.cd var/www/html/iie.lab.tpu.comと入力し、/var/www/htmlのフォルダに移動する。
7.python processing_data_server2.pyと入力する。(これにより、ラズパイとサーバーのデータの送受信ができるようになる。)
・コマンドプロンプトが以下の通りとなっていればよい。
#ref(): File not found: "1.png" at page "平井さん卒論_backup"
・手順
1.ラズパイ上のコマンドプロンプトでpython sendata.pyと入力する。(これにより、サーバー上にデータを送信できるようになる)
2.別のコマンドプロンプトを起動し、python newsensa_all_esk_3.pyと入力する。
3.newsensa_all_esk_3.pyが作動している間はウェアラブル装置を装着しながら待つ。
4.newsensa_all_esk_3.pyの表示が500に達したら、別のコマンドプロンプトを起動し、pyhon gassmic_esk_2.pyと入力する。
5.gassmic_esk_2.pyを実行したら、マイクにok googleと言う。
6.start recignized by ok googleと表示されたら待機。
・ラズパイ上のsendata.pyの実行画面において、1024に達したときにpython processing_data_server2.pyの実行画面が以下の通りになっていればラズパイのデータがpcに送信されたことになる。
#ref(): File not found: "2.png" at page "平井さん卒論_backup"
・手順
1.ラズパイ上のsendata.pyの実行画面において、1024に達したときpcの別のコマンドプロンプトを起動し、再度/var/www/htmlのフォルダに移動する。
2.processing_data_server.pyと入力する。
3.pcでhttps://dic515s2.pu-toyama.ac.jp/iie.lab.tpu.com/Image2.html
にアクセスし、実行結果を確認する。
実行結果一覧
・ストレス数値が0以上2未満のとき↓
#ref(): File not found: "3.png" at page "平井さん卒論_backup"
・ストレス数値が2以上5の未満とき↓
#ref(): File not found: "4.png" at page "平井さん卒論_backup"
・ストレス数値が5以上のとき↓
#ref(): File not found: "5.png" at page "平井さん卒論_backup"
行動を変えるたびにマイクで「場所 状況」を入力する。ホットワード含め入力できたかはボードのランプを見れば分かる。
入力後にランプが点滅したら成功。
グラスのHTMLが更新されなくなったらなんか不具合が起きたのでもう一度HDMI接続しなおしてみる。
◎考えられる不具合
実行と無視を行う場合、最後の実行指令に従いコーピングを行う
・windowsの場合
サーバーにセンサデータ(fordend.xlsx,fordend2.xlsx)とライフログ(fordend.csv)とストレスログ(foo.csv)が記録されている
それらを見るためにwinSCPというサーバーを遠隔操作するソフトをインストールしておく
アカウントや権限に関しては管理者に一任します
実験後、foo.csvには実験中のHTMlの情報が記録されている。
つまり1分ごとのLF/HFなどが記録されている。
Excelで開いてグラフ作ってLF/HFの変移が分かる
ちなみにcsvファイルをExcelで開いてグラフを作っても保存されないから適当にxslxファイルに丸写しして作成したほうがいい
もしくはグラフ作ったらキャプチャして残す。二度と見れなくなるけど
こんな表を用意する
| 無視前 | 無視後 | 差(後―前) | 実行前 | 実行後 | 差(後ー前) |
◎検定方法
コーピング発動したか(1か0、copenとする)とコーピングしたか(1か0、copegとする)を見て無視したときと実行したときのLF/HFの変化を見る
まずcopenが0から1になった時、
次にcopenが1のままcopegが0から1もしくは1から0になった時
さらにcopenが1のままcopegが0から0、もしくは1から1になった時
記録が終わったら差分を計算して両方の差を求める。
つづいてF検定を行う。変数は無視の差(後ー前)と実行の差(後ー前)の2つ(習ったやろから省略)
F検定で等分散性があるかないかでちがうT検定を行う
検定のタイトルが(等分散性があると仮定したT検定とかだったから見りゃわかる)
T検定のP値が0.05以下なら2つの変数には有意な差があると断定できる
つまりコーピング実行と無視したときではLF/HFの変化の仕方が違うと言える
まず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のグラフは作成されるのに
本研究ではデンドログラムはぶっちゃけいらんのやけど行動識別できているか確かめるために作成しなきゃいけない
ワイが作ったゼミ用のページに「processing_data_2.py」がある。
これはスプレッドシートにアクセスせずに同じフォルダにあるfordend.csvからデンドログラムとコーピング処理を行うプログラムになっている。
これを実行するとデンドログラムがど作成され、den.pngが保存される
#ref(): File not found: "226.JPG" at page "平井さん卒論_backup"
江崎のドライブに全部ある、はず
江崎のドライブに全部ある、はず名前が若干違うかも