「未分類」カテゴリーアーカイブ

AI音声実験230419

木下実験の詩
風が吹いている。
私の身体を押し戻そうと必死になって。
それでも前へ前へと歩みを進める。
そんな私の頬を風は冷たく撫でた。
分からないほど辛くなって、何が辛いのかも解らなくなった。
堪えた涙も頬を伝ってはじめて気が付く。
躓き,よろめき,また転げる。
それでも傷まみれの身体は動く。
少しずつ、ゆっくりと。
腕を伸ばしたその先で、掴めたものは朝日でした。
やがて光は溢れだし、すべてを明るく照らし出す。
暖かく、柔らかな陽射しで。
人々が目覚め、私に気が付く。
貴方はこちらへ駆け寄って手を差し伸べてくれた。
私の脚が前に進めためのものならば、この手は一体何のためにあるのだろう。
初めて抱いた疑問を前に、私の視線は地面に向かう。
少しの時間が過ぎた後、貴方は微笑みながら語りかけてくれた。
その一言一言に私は救われた気がする。
今、私は泣いているのでしょうか?
それとも笑えているのでしょうか?
穏やかな風が吹いてきた。
それは、何かを届けるように。

Webcam Motion Captureのページはこちら

BoothのWonさんのページがすごい!

授業観察アプリ230415

測定結果
・データ保存先は下記ディレクトリ
http://kodamalab.sakura.ne.jp/WGL/SCRIPT/class/data
ブラウザからは、ディレクトリリトがとれないので、NotepadなどのFTP対応型のエディタがあると望ましい。
・使用しているレンタルサーバーはSakura Internet(5000円/年)

PlayerPrefsについて
・Unityアプリ実行時に簡易的にゲームパラメータを保存できる仕組み。シーンを切り替えるとき、変数を維持するために使っている。

FireHD関連
・うまいことキャンセルするとアカウントを登録せずに使えるらしい。
開発者モードに設定しないとAndroidビルドが書き込めない

Unity開発環境
・AndroidBuildSupportが必要

 

音声合成

長い文章を読むとき、「読み上げてくれるといいんだけどなぁ」と思うこともあります。音声合成技術は今どんななんでしょう?

調査結果
PC Watch220416の記事
有料VoicePeakは読み上げがスムーズだが24000円で購入必要。体験版もある。
無料のVoiceVoxはやや不自然だがPython連携できるらしい。

合成音声AIまとめ221122の記事
CoeiroinkもPythonから使えるらしい。

SeirenVoice
抑揚を自動で読み込むので、再現率がすごい。でも高い。

使ってみる
・CoeiroInk
性能は・・・まずまずですね。イントネーションの不自然さは、辞書登録でどうにかなりそう。ボイスが沢山選べるのもいいね。ちなみにこれ、自分で声作れるらしい。バーチャル自分の構築に一歩前進だな。
・SeirenVoice
体験版を使ってみる。ずんだもんスゲェ!!!これがナガノ由来の声だと気がつく者はもうおるまい。でもリアルタイムでは変換できないらしい。買っちゃおうか迷う性能だな(2万円)。ずんだもん以外の声は大したことないと思う。

次はMMVCだな・・・。NEURTINOって・・・やばすぎるだろコレ!!?シルブブレジデントずんだもん。いやいやこりゃぁ眠れなくなってしまいそうだなぁ。

PolarH10でkubios

kubiosとPolarSensorLoggerの導入
とりあえずKubiosStandardを0円で購入して導入する。PolarH10で測定したRR間隔で、HRV解析をしてみる。測定は、PolarSensorLoggerというAndroidアプリ(無料)で行ってみる。Main画面でStartを押すとデバイスの候補が出るので、使用中のH10を選んでOKを押すと計測が始まる。計測中はGraph画面からResume/Pauseを押すと波形とHRをリアルタイムで確認できる。Main画面でStopを押すと、メールやGoogleDriveで共有できる。H10のECG波形メチャクチャきれい。

Kubiosへのデータ取り込みとHRV解析
Standard版のKubiosはRR間隔データしか読み込まない。しょうがないので、PolarSensorLoggerが出力する***RR.txtを加工してRR部分だけを食わせてみる。ふむふむグラフが表示されますね。分析区間は、samples for analysisのAddボタンを押して、追加することができる。時間領域や周波数領域だけでなく、非線形のポアンカレプロットなどもできて良い感じです。大抵の分析なら、これで良いのでは。この「いかにも分析してる」感が意外に楽しいのかもしれん。

H7でも解析できるの?
H7でも波形でるのかなぁ?HRだけ?→PolarSensorLoggerでH7を検証してみると、認識するものの測定できるのはHRだけでした(しかも波形も表示されず)。KubiosでHRV解析するにはH10が必要みたい。

その他懸案事項
・KubiosScientificを購入するとアプリから直接測定できて便利だけど、二人同時に測定するにはアプリが2本いるのかな?
・PCにPolarH10を直接接続できると、すごく便利なんだけど・・・

FitbitとPolarの比較

測定結果の概観
FitbitCharge4とPolarUniteを装着し、学内を歩いたり多少走ったりしながら測定結果を比較した。位置情報はGPSを内蔵したCharge4の方が正確だ。心拍数も似たような変化を示していたものの、変化を観察していると、他サイトでも指摘されていたとおり、Fitbitの変化がやや遅れてやってくる印象であった。

測定結果取得方法の比較
Polarのデータ取得は、デバイスをPCに接続しPolarFlowSyncで同期を行い、WebアプリのPolarFlowにログインしてセッションを選択し、エクスポートを選ぶだけだ。非常に簡単だ。出力されるCSVデータの内容も極めて常識的である。対するFitbitのデータ取得は、自由度が高い反面、その手順は煩雑だ。Pythonを使って取得する方法が一般的なようだが、実行環境を整えたり、必要に応じてスクリプトを用意したりする必要がある。下に1秒単位でHRを取得するコードを掲載した。

import sys
import fitbit
import gather_keys_oauth2 as Oauth2
from datetime import datetime, date, timedelta
  
print('Fitbit02') 
USER_ID     = "ほげほげ"
CLIENT_SECRET = "ほげほげ"
DATE = "2023-03-24" # 取得したい日付 
  
print('Hello fitbit02') 
   
def requestFitbit(DATE):
    rval=""
    global auth2_client
 
    fitbit_stats = auth2_client.intraday_time_series('activities/heart', DATE, detail_level='1sec')
    HRstats = fitbit_stats['activities-heart-intraday']['dataset']
    
    OUTPUT_FILE = "ALL2.csv"
    csv_file = open(OUTPUT_FILE, 'a')
   
    csv_file.write(DATE+",")
    for num1 in range(24):
        for num2 in range(60):
            for num3 in range(60):
                key='{:02}'.format(num1)+':{:02}'.format(num2)+':{:02}'.format(num3)
                hr=""
                for var in range(0, len(HRstats)):
                    #csv_file.write(str(HRstats[var]['time']))
                    #csv_file.write(",")            
                    if str(HRstats[var]['time']) == key:
                        hr=str(HRstats[var]['value'])
                        #print("hit")
                        break
                print(key+"/"+hr)
                csv_file.write(key+","+hr)
                csv_file.write("\n")              
                 
    csv_file.write("\n")
    csv_file.close()
    return rval
##################################################
 
def writeindex():   
    OUTPUT_FILE = "ALL.csv"
    csv_file = open(OUTPUT_FILE, 'a')
     
    csv_file.write(",")
    for num1 in range(24):
        for num2 in range(60):
            key='{:02}'.format(num1)+':{:02}'.format(num2)+':00'
            csv_file.write(key)
            csv_file.write(",")              
             
    csv_file.write("\n")
    csv_file.close()
##################################################
 
"""Get tokens"""
server = Oauth2.OAuth2Server(USER_ID, CLIENT_SECRET)
server.browser_authorize()
ACCESS_TOKEN = str(server.fitbit.client.session.token['access_token'])
REFRESH_TOKEN = str(server.fitbit.client.session.token['refresh_token'])
  
#print(ACCESS_TOKEN)  
#print(REFRESH_TOKEN)
 
"""Authorization"""
auth2_client = fitbit.Fitbit(USER_ID, CLIENT_SECRET, oauth2=True, access_token=ACCESS_TOKEN, refresh_token=REFRESH_TOKEN)
  
"""request"""
 
#writeindex()
today = datetime.today()
for var in range(0, 1):
    #day=today + timedelta(days=1)
    #print(var+":" + datetime.strftime(yesterday, '%Y-%m-%d'))
    stamp=datetime.strftime(today - timedelta(days=var), '%Y-%m-%d')
    print("target: " + stamp)
    requestFitbit(stamp)

測定されたHRの比較
FitbitCharge4のデータをPythonで取得し、同区間のPolarUniteのデータに重ねてみた。PolatUniteは3色10点のPolar Precision Primeセンサー搭載でいかにも正確に測れそうだ。対するFitbitCharge4は単色で測定点数も少なくやや心もとない。結果を見比べると、概ね一緒なのだが、Charge4は中盤の走っている場面で値が低めというか、かなり遅れて変化している事が見て取れる。また、PolarUniteのデータが1秒間隔で全量取得できるのに対し、Fitbitは1~5秒程度の不定間隔データとなっている。走り終わって座っている後半区間に関しては、両者はほとんど一緒だ。動きが大きくなると正確な測定が難しくなるという研究もあり、その結果を裏付ける比較結果であった。動きが少ない場面ではFitbitでも良いと言えそうだが、心理学実験での利便性は、総合的にPolarが高いと言えそうだ。
追記:わー!!文献:Assessment of the Fitbit Charge 2 for monitoring heart rateでも同様の結果だ。Charge4と2は同じアルゴリズムと思われる。30BPM低く見積もることがある、と。

Polar UniteとH7の比較
Polarには旧来のチェストバンド型センサー(H7やH10など)もある。H7を保有しているため、胸部から心電図を測定するH7と、腕から脈波を測定するUniteでHRがどのように異なるか比較してみることにした。左が座位で3分ほど、右が屋外を走り休憩する12分ほどの比較。H7で測ったデータも、Uniteで測ったデータも、PolarFlow(Webアプリ)で参照可能になる。とても便利だ。

H7の値を真のHRとすると、Uniteの測定はかなり頑張っていると言える。特に走っている最中でも追従しているのは素晴らしい。しかし「やや遅れている」のも事実のようである。そもそもH7の心拍数データは正しいのだろうか?(後継機種のH10の売り文句は「Polar史上最も正確なHRセンサー」だ)正確に測れているかは、心電図を見ないと結局わからないので、H10を買う必要があるのかもしれない。

Fitbit/Python230324

この期に及んでPythonである。Fitbit/Pythonとの縁はしばらく切れぬらしい。


Anacondaのインストール
Python実行環境であるAnacondaのインストールを行う。とりあえずAnaconda3をダウンロードして道なりにインストール。終了すると、Anaconda PromptからPythonが実行できるようになる。インストールは、こちらのサイトが参考になる。インストールできたら、startメニューからAnaconda Promptを起動。Pythonコマンドで動作確認。Ctrl+Zで対話モード終了。

Fitbitの開発者向けサイトでアプリケーションを登録する
FitbitDevelopperサイトにログインして、Manage>RegisterAppの順で進み、アプリケーションを登録する。設定は以下の通り。URL関係は全て「https://kodamalab.sakura.ne.jp/wordpress/?p=46853」、RedirectURLは、「http://127.0.0.1:8080/」とする。ページ内で作成された「OAuth 2.0 Client ID」と「Client Secret」をPythonスクリプト中で使用することになる。

FitbitDevelopperサイトにログインする必要あり
Devサイトでのアプリ作成方法

Fitbit API Python Clientのインストール
GitHub – orcasgit/python-fitbit: Fitbit API Python Client Implementationからcodeボタンを押し、Zipファイルをダウンロードし、中身をCドライブ直下に配置する(こちらのサイトが参考になる)。さらに、下記コマンドで追加パッケージをインストールする。

pip install -r requirements/base.txt
pip install cherrypy 


Pythonスクリプトでクラウド上のファイルを取得
c:\python-fitbitフォルダに下記スクリプトをfitbit01.pyという名前で保存し、実行する。Anaconda Promptから下記コマンドを打ち込む

python fitbit01.py

import sys
import fitbit
import gather_keys_oauth2 as Oauth2
 
print('Hello FitbitAPP3') 
 
USER_ID     = "ほげ"
CLIENT_SECRET = "ほげ"
 
DATE = "2021-06-03" # 取得したい日付
 
 
server = Oauth2.OAuth2Server(USER_ID, CLIENT_SECRET)
server.browser_authorize()
ACCESS_TOKEN = str(server.fitbit.client.session.token['access_token'])
REFRESH_TOKEN = str(server.fitbit.client.session.token['refresh_token'])
 
#print(ACCESS_TOKEN) print('\n') 
#print(REFRESH_TOKEN)print('\n') 
 
"""Authorization"""
auth2_client = fitbit.Fitbit(USER_ID, CLIENT_SECRET, oauth2=True, access_token=ACCESS_TOKEN, refresh_token=REFRESH_TOKEN)
 
"""Getting data"""
#print('Getting data\n') 
#fitbit_stats = auth2_client.intraday_time_series('activities/heart', DATE, detail_level='1min')
  
##################################################
fitbit_stats = auth2_client.intraday_time_series('activities/heart', DATE, detail_level='1min')
stats = fitbit_stats['activities-heart-intraday']['dataset']
 
OUTPUT_FILE = "HR_%s.csv" % DATE
csv_file = open(OUTPUT_FILE, 'w')
for var in range(0, len(stats)):
    csv_file.write(stats[var]['time'])
    csv_file.write(",")
    csv_file.write(str(stats[var]['value']))
    csv_file.write("\n")
csv_file.close()
 
##################################################
fitbit_stats = auth2_client.intraday_time_series('activities/steps', DATE, detail_level='1min')
stats = fitbit_stats['activities-steps-intraday']['dataset']
 
OUTPUT_FILE = "STEP%s.csv" % DATE
csv_file = open(OUTPUT_FILE, 'w')
for var in range(0, len(stats)):
    csv_file.write(stats[var]['time'])
    csv_file.write(",")
    csv_file.write(str(stats[var]['value']))
    csv_file.write("\n")
csv_file.close()
 
##################################################
fitbit_stats = auth2_client.intraday_time_series('activities/calories', DATE, detail_level='1min')
stats = fitbit_stats['activities-calories-intraday']['dataset']
 
OUTPUT_FILE = "CALO%s.csv" % DATE
csv_file = open(OUTPUT_FILE, 'w')
for var in range(0, len(stats)):
    csv_file.write(stats[var]['time'])
    csv_file.write(",")
    csv_file.write(str(stats[var]['value']))
    csv_file.write("\n")
csv_file.close()

トラブルシューティング

・RedirectURLが、http://127.0.0.1:8080/で正しく動作しない場合
ポート8080をなにかのプログラムが使っている可能性がある。その場合は、RedirectURLを、「http://127.0.0.1:8088/」とし、python-fitbitフォルダ中のgather_keys_oauth2.pyの該当部分を「8088」に変更してスクリプトを実施する。

・Pythonのスクリプトは何で作ればいいの?
プログラミング用のテキストエディタ、Notepad++がおすすめです。

WS230315@同志社大学

Arduino入門
 今回のワークショップでは、生理指標の測定にArduinoを使用します。Arduinoは、電子工作で何かをプロトタイプする場合に使用される開発環境です。用途に応じた様々なタイプのマイクロコンピュータを、ArduinoIDEという単一のインターフェースで使用することができ、世界中の人々が、ありとあらゆるハードウェアをArduino経由でPCに接続しています。

//プログラム名:Blink
//LEDを点滅させる
void setup()
{
  pinMode(13, OUTPUT); //13番のピンを出力モードに
}

void loop()
{
  digitalWrite(13, HIGH); //13をONにする
  delay(1000); //1000ms待つ
  digitalWrite(13, LOW); //13をOFFにする
  delay(1000); //
}

電源およびAD変換部分の組み立て
下の写真と部品リストを照らし合わせ、ブレッドボード上に電源およびAD変換部分の部品をセットしてみましょう。Arduinoに接続できたら、下のプログラム「ADC1」をArduinoに書き込んで動作させてみましょう。プログラムを動作させるには、「Adafruit ADS1x15」ライブラリが必要です。ライブラリのインストール方法、プログラムの動作のさせかたは動画をご覧ください。

//プログラム名:ADC1
#include <Wire.h> //I2C通信ライブラリ
#include <Adafruit_ADS1X15.h> //ADS1015ライブラリ
Adafruit_ADS1015 ads; //ADS1015クラスのインスタンス化
 
void setup(void)
{
  Serial.begin(115200);  //シリアル通信開始
  // ADS1015 gain 2/3  input range +/- 6.144V 
  ads.begin(); //ADS1015通信開始
}
 
void loop(void)
{
  int16_t results; //AD変換結果
  results = ads.readADC_Differential_0_1();  //差動入力
    
  float   multiplier = 3.0F;  // デフォルトゲイン(2/3倍)における係数
  Serial.print(results * multiplier); //得られたデジタル値をmvに換算しシリアルモニタに表示
  Serial.print(",3000,0"); 
  Serial.println(); //シリアルモニタ改行
  delay(0);
}

SCC測定アンプの組み立てと測定
さらに、下の写真と部品リストを照らし合わせ、ブレッドボード上にSCC測定アンプの部品をセットしてみましょう。

組み立て手順は自由ですが、下記のような順序でやってみるとやりやすいかもしれません。組み立て中は、念のためArduinoのUSBケーブルを抜いて、回路の電源を切っておきましょう。

部品の配置が終わったら、ArduinoをPCに接続し、プログラム「SCC1」をArduinoに書き込んで動作させてみましょう。
※身体に電極を装着して測定する際は、感電を防止するため、PCから電源を必ず抜くようにしましょう。

//プログラム名:SCC1
#include <Wire.h>
#include <Adafruit_ADS1X15.h>
Adafruit_ADS1015 ads;
 
void setup(void)
{
  Serial.begin(115200);
  // ADS1015 gain 8x  input +/- 0.512V
  ads.setGain(GAIN_EIGHT);  //ゲインを8倍に設定
  ads.begin();
}
 
void loop(void)
{
  int16_t results1,results2;
  results1 = ads.readADC_Differential_0_1();  //差動入力
     
  float   multiplier = 0.25F; //ゲイン8倍時の係数
  Serial.print(results1 * multiplier); 
  Serial.print(","); 
  Serial.print("194,"); //24k Ohm = 42uS
  Serial.print("-7,");  //1M Ohm = 1uS
  Serial.println();
 
  delay(200);
}

ECG測定アンプの組み立てと測定
 下の写真と部品リストを照らし合わせ、ブレッドボード上にECG測定アンプの部品をセットしてみましょう。

組み立て手順は自由ですが、下記のような順序でやってみるとやりやすいかもしれません。組み立て中は、念のためArduinoのUSBケーブルを抜いて、回路の電源を切っておきましょう。

部品の配置が終わったら、ArduinoをPCに接続し、プログラム「ECG1」をArduinoに書き込んで動作させてみましょう。電極は、上記資料を参考に、胸部に装着します。
※身体に電極を装着して測定する際は、感電を防止するため、PCから電源を必ず抜くようにしましょう。

//プログラム名:ECG1
#include <Wire.h> //I2C通信ライブラリ
#include <Adafruit_ADS1X15.h> //ADS1015ライブラリ
Adafruit_ADS1015 ads; //ADS1015クラスのインスタンス化
 
void setup(void)
{
  Serial.begin(115200);  //シリアル通信開始
  // ADS1015 gain 2/3  input range +/- 6.144V 
  ads.begin(); //ADS1015通信開始
}
 
void loop(void)
{
  int16_t results; //AD変換結果
  results = ads.readADC_Differential_0_1();  //差動入力
    
  float   multiplier = 3.0F;  // デフォルトゲイン(2/3倍)における係数
  Serial.print(results * multiplier); //得られたデジタル値をmvに換算しシリアルモニタに表示
  Serial.print(",4000,1000"); 
  Serial.println(); //シリアルモニタ改行
  delay(0);
}

資料
Arduinoで生理指標を測る
右足回路動画

使用部品

TLE2426CLP レールスプリッタ
LM385B-1.2 電圧リファレンス

その他

追記

改善点

  • 作業進行用ブレットボードの用意
  • Ardino開発環境は1.8.19に指定
  • ライブラリinstall時に問題発生多し(MacOS,OneDrive内Desktopなど)
  • 可変抵抗の向き(銀点が見えなくなってしまっている)
  • ICの向き
  • テスト用24kΩ抵抗の用意
  • ディスポ電極を多めに用意

授業観察アプリ230223

FireHD8plusが到着したので、作業を進めてインストールしてみる。スマートフォンだと小さすぎるし10インチだと重いしで、8インチくらいがちょうど良いのかな?とりあえず1ページ目で観察者名や実験名、生徒数、インターバルなどの基本情報を入力し、2ページ目で行動を記録する、というインターフェースにしてみた。

でもこれくらい画面が広いと、
1.いっそボタンに観察対象となる行動を文字で表示する
2.座席表や簡単な作業マニュアルなどを画面上で参照可能にする
などの改善案が可能という気もする。

以下にUnity側のc#スクリプトと、サーバー側のPHPスクリプトを記載する。


1行入力やスライダーの値をPlayerPrefsに保存し、「次へ」ボタンでページ遷移するプログラム。PlayerPrefsはUnity実行環境で利用できるディスク領域のようなもの。テキストや数値などの各種パラメータを保存できる。シーンをまたぐときに使うと便利。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.SceneManagement;
using UnityEngine.Networking;
using TMPro;


public class procP1 : MonoBehaviour
{
    public TMP_InputField input1;
    public TMP_InputField input2;
    public Slider slider1;
    public TextMeshProUGUI mes1;
    public Slider slider2;
    public TextMeshProUGUI mes2;

    // Start is called before the first frame update
    void Start()
    {
        //Screen.SetResolution(1200, 540, true, 60);    // RedmiNote11
        Screen.SetResolution(1280, 800, true, 60);      // Fire HD 8

        //read PlayerPrefs
        string username,expcode;
        int studentnum = 0;
        int interval = 0;
        username = PlayerPrefs.GetString("username", "-");
        if (username.Length > 1) {input1.text = username;}
        expcode = PlayerPrefs.GetString("expcode", "-");
        if (expcode.Length > 1) { input2.text = expcode; }
        studentnum = PlayerPrefs.GetInt("studentnum", 0);
        slider1.value = studentnum;
        interval = PlayerPrefs.GetInt("interval", 0);
        slider2.value = interval;

        /*
         username
        expcode
        studentnum
        interval
         */
    }

    // Update is called once per frame
    void Update()
    {
        mes1.text = slider1.value + "名";
        mes2.text = slider2.value + "秒";
    }

    public void procNextBtn() {

        // write playerPrefs
        PlayerPrefs.SetString("username", input1.text);
        PlayerPrefs.SetString("expcode", input2.text);
        PlayerPrefs.SetInt("studentnum", (int)slider1.value);
        PlayerPrefs.SetInt("interval", (int)slider2.value);
        SceneManager.LoadScene("P2");   // load scene "P2"
    }
}

ボタンのOn/Offを記憶し、定められた時間間隔でHTTP通信でサーバーへ値を送信するプログラム。ボタンのOn/Offは毎フレーム、文字などの更新処理は1秒間隔でおこなっている。HTTP通信はStartCoroutineで非同期処理。Post形式でサーバー側のPHPスクリプトに値を送っている。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using System;
using TMPro;
using UnityEngine.SceneManagement;
using UnityEngine.Networking;

public class procP2 : MonoBehaviour
{
    public Button b1;
    public Button b2;
    public Button b3;
    public Button b4;
    public Button b5;
    public TextMeshProUGUI mes1;
    public TextMeshProUGUI mes2;
    public TextMeshProUGUI mes3;
    public AudioClip clip1;

    bool sw1, sw2, sw3, sw4, sw5;
    Color pink;
    DateTime dt;
    long t1, t0;
    AudioSource audio;
    int interval =10;
    int currentst = 0;


    // Start is called before the first frame update
    void Start()
    {
        sw1 = sw2=sw3=sw4=sw5=false;
        pink= new Color(255f / 255f, 100f / 255f, 100f / 255f, 1f);

        // read PlayerPrefs
        interval= PlayerPrefs.GetInt("interval", 0);

        audio = gameObject.GetComponent<AudioSource>();
    }

    // Update is called once per frame
    void Update()
    {
        dt = DateTime.Now;  // get time info

        // process SW color
        if (sw1) { b1.image.color = pink; } else { b1.image.color = Color.white; }
        if (sw2) { b2.image.color = pink; } else { b2.image.color = Color.white; }
        if (sw3) { b3.image.color = pink; } else { b3.image.color = Color.white; }
        if (sw4) { b4.image.color = pink; } else { b4.image.color = Color.white; }
        if (sw5) { b5.image.color = pink; } else { b5.image.color = Color.white; }

        ////// 1S loop //////
        t0 = t1;
        t1=(long)Time.time;
        if (t1 != t0) {
            Debug.Log(t1);
            mes2.text = "日時:" + dt;
            mes1.text = "評価者:" + PlayerPrefs.GetString("username", "-");
            mes1.text += " 研究区分:" + PlayerPrefs.GetString("expcode", "-");
            mes1.text += " 観察生徒:" + currentst + "/" + PlayerPrefs.GetInt("studentnum", 0);

            // exec HTTP communication
            if (dt.Second % interval == 0) {
                Debug.Log("HTTP_send");
                audio.PlayOneShot(clip1);
                StartCoroutine("HTTP_Post");
                sw1 = sw2 = sw3 = sw4 = sw5= false; // reset SW
                currentst++;                        // increment student cnt
            }
        }
    }

    public void ApplicationQuit()
    {
        Application.Quit();
    }

    public void procButton(int swnum)
    {
        if (swnum == 1) { sw1 = !sw1; }
        if (swnum == 2) { sw2 = !sw2; }
        if (swnum == 3) { sw3 = !sw3; }
        if (swnum == 4) { sw4 = !sw4; }
        if (swnum == 5) { sw5 = !sw5; }
    }

    IEnumerator HTTP_Post()
    {
        string URL = "http://kodamalab.sakura.ne.jp/WGL/SCRIPT/class/regist.php";
        Debug.Log("URL:" + URL);

        WWWForm form = new WWWForm();
        form.AddField("sampletime", dt.ToString());
        form.AddField("username", PlayerPrefs.GetString("username", "---"));
        form.AddField("expcode", PlayerPrefs.GetString("expcode", "---"));
        form.AddField("studentnum", PlayerPrefs.GetInt("studentnum", 99));
        form.AddField("interval", PlayerPrefs.GetInt("interval", 99));
        form.AddField("currentst", currentst);
        form.AddField("sw1", Convert.ToInt32(sw1));
        form.AddField("sw2", Convert.ToInt32(sw2));
        form.AddField("sw3", Convert.ToInt32(sw3));
        form.AddField("sw4", Convert.ToInt32(sw4));
        form.AddField("sw5", Convert.ToInt32(sw5));

        UnityWebRequest www = UnityWebRequest.Post(URL, form);
        yield return www.SendWebRequest();

        if (www.isNetworkError || www.isHttpError)
        {
            Debug.Log(www.error);
        }
        else
        {
            string log;
            log = www.downloadHandler.text;
            Debug.Log("POST process complete!:" + log);
            mes3.text = "LOG:" + log;
        }

    }
}

PHP側のスクリプト。postで受け取った値をディスクに追加方式で書き込むだけ。

<?
$stamp=strftime("%Y%m%d_%H%M%S");
$fn=strftime("./data/classdat%Y%m%d.csv");
echo"posted ";


if($_POST['username']!=""){
		
	$fp=fopen($fn,"a");
	fprintf($fp,"%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s\n",
		$_POST['sampletime'],
		$_POST['username'],
		$_POST['expcode'],
		$_POST['studentnum'],
		$_POST['interval'],
		$_POST['currentst'],
		$_POST['sw1'],
		$_POST['sw2'],
		$_POST['sw3'],
		$_POST['sw4'],
		$_POST['sw5'],
		);
	fclose($fp);
	echo"->saved $fn/$stamp";

}

//echo"{$_POST['IF1']}/{$_POST['IF2']}/{$_POST['IF3']}/";
?>

授業観察アプリ230221

あらまし
授業観察を行うための装置は、独自HW準備の夢はあるものの、実利をとってAndroidタブレット化をメインにすすめることに。

実行環境

ハードウェアの候補はAmazonのFireHDタブレット。価格の割に質が高く、かつ入手性が良いのが特徴。ハードウェアのラインアップは、7,8,10のインチ、無印orPlusのグレードがあり、インチ数が大きくPlusがついているモデルがRAMや、GPUのコアが多いなど、リッチな構成。片手で操作でき、そこそこ性能の良いHD8が良さそうである。FireOS搭載というが、Unityで作成したAndroidアプリが動作する(従来どおりであれば)。ぱっと見、WebGLは非サポートのようである。

FireHD 8Plus(2022) パフォーマンスが30%向上したという。
HD8無印とPlusの違い RAMが2->3G、外側カメラの画素が200->500万
SoCはMT8169A GPUがMaliG52だ・・・。でも性能がいいのはやっぱHD10だね。
FireHDタブレットにUnityアプリをインストールする例 2019年なので比較的最近


アプリの作成
とりあえず手持ちのアンドロイドスマホRedmiNote11にビルドして入れてみる。5行動をボタンで記録できる。触れると赤くなり、定期的にHTTPでサーバーに情報を送る。送る情報は、1)評価者、2)評価時刻、3)評価対象者、4)行動記録・・・だろうか。評価対象者はたくさんいるだろうから、プルダウンにしたほうが良いのだろうか?詳しく聞いておけばよかった。一定時間おきに定期的に送信し、送信時に振動・・・FireHDはバイブないかもねぇ。

TextureMeshで日本語使いたい TextureMeshになってから結構面倒なのね。
UnityでHTTP POST形式でHTTP通信する場合

OpenCVで顔検出

Processing+OpenCVで顔を検出して位置を保存するアプリを作成。dataフォルダにファイル名「日付_日時.csv」でデータが保存される。サンプル間隔は100msに設定。保存データにはタイムスタンプがつくので、複数マシンで計測する場合は、時間を手掛かりに後から同期すればよい。csv形式なので、エクセルで開いてXYグラフにするとこんな感じ。Webカメラは、ミニ三脚でPCの背後にセットしたほうが自由度があってよい感じと思われる。
OpenCVの顔認識は、あまり横方向を向くと検出されなくなるので、ちょっと注意が必要だ。このライブラリでは顔の向きまでは判定できない。WidthとHeight、できれば顔の検出数も記録しておけば、横をむいているかを判断できるかもしれない。


さらに1台のマシンに2カメラ接続して動作を検証。CPU負荷は100%になっちゃうけど、サンプル数も足りているし、軌跡もほとんど一緒だ。どうやら、二つのカメラを1台のマシンで測定できるようだ。これどうにかして一本のアプリにならんものだろうか・・・
あ、一個になりますね。これ一個にした方が絶対速いし、タイムスケジュールの管理も楽だ。しかし改造にはもう少し時間が必要かも。

M2設定方法

計測器の使用方法自体はこちらで解説されています。ここでは、Wifiの設定方法を解説します。

計測器の電源を入れ、一番下のボタンを押すと、LEDが、緑→青→赤、の順で変化します。

・緑はアクセスポイント1に繋がるモード
・青はアクセスポイント2に繋がるモード
・赤はサーバー(設定)モード

サーバーモードにすると、PCのWifi設定に計測器が現れます。ESPから始まり、計測器に書かれている英数字(上記では8f64)が含まれるSSIDが計測器です。接続し、ブラウザのアドレスバーからhttp://192.168.4.1をひらくと、計測器の設定画面にアクセスできます。ここで、接続先のアクセスポイントのSSIDとパスワードを設定します。

設定した二つのアクセスポイントは、計測器の起動時に一番下のボタンを押すことで切り替えることができます。緑がひとつめのアクセスポイント、青はふたつめのアクセスポイントにつながる事を意味します。

バイオフィードバックトピック

心拍変動バイオフィードバック
 心理学系の貢献が大きいのは、心拍変動バイオフィードバックの解説と普及であると思われる。筋電図や発汗、血流などの指標に関するバイオフィードバックは、リハビリ(非心理系)を除き、ここ数年ほとんど議論されておらず、心拍変動BF一色となっている。特にこの数年は(コロナの影響もあり)、ウェアラブル機器を利用して、各自が心拍変動バイオフィードバックを行う事例が紹介されている。

各種新技術の応用事例
 ここ数年、スマートグラス、VR、IoT、ウェアラブル、非接触計測、スマートフォンアプリなど、新しい技術をBFに取り込んだ事例が紹介されているが、コストが高かったり、不安定であったり(非接触計測)、実際はあまり普及していないと思われる。現代のバイオフィードバックとして最も有望なのは、アクティブトラッカーを使った活動量と心拍数の自己制御であると思われる。

2021年度
・スマートフォンアプリを使った共鳴周波数の評価
・少年院における心拍変動バイオフィードバックを用いた呼吸セルフコントロールプログラム
→心拍変動バイオフィードバックが近年のトピックになっている。さらにそれを、スマートフォンなどの携帯機器で行う事例が紹介されている。

・AI, ICT, VRを活用する未来に向けて 
・遠隔による心拍変動バイオフィードバック
→コロナの影響を受けて、BF機器を遠隔診療へ応用する可能性が論議されている。心拍変動バイオフィードバック(emWaveなどの機器使用が推奨される)を遠隔で行った事例が紹介される。

2020年度
・呼吸法とリラクセーション‒心拍変動バイオフィードバックによる呼吸法の評価‒
→”同定された共鳴周波数の呼吸法を実践することで,副交感神経系の活動を活発にし,喘息などの疾患の治療に役立つとして,詳しい治療プログラムを発表している”の部分に、心拍変動バイオフィードバックの元論文が紹介されている。

2019年
・長時間心拍変動解析 : その適用と誤用
→ウェアラブルセンサーによって測定された心拍変動データの読み方について解説。ウェアラブル計測は急速に普及しつつある、と紹介されている。

・臨床に活かす心拍変動バイオフィードバック
→心拍変動バイオフィードバックの臨床応用が講座で紹介されている。

・入眠困難者の入眠期における生理心理学的指標の動態
→入眠困難者の生理指標が検討されているが、脳波と心拍変動が解析対象となっている。

2018年
・医療からみた次世代バイオフィードバック
・バーチャルリハビリテーションにおける次世代バイオフィードバックの可能性
・ICTやAIの時代にバイオフィードバックはどう活用できるか : 産・学・官の連携
・AI・IoTの基礎とバイオフィードバック装置への応用検討
→スマートグラス利用のBF、VRを用いたリハビリ、認知行動療法アプリ、AIやIoT利用などの新しいアプローチが紹介される。

・カメラを用いた非接触バイタルセンシング技術とその応用
・ウエアラブル バイオフィードバックについて
→非接触計測、ウェアラブル機器によるBFの可能性などが紹介される。

EasyRoad3D Tips

・ロードネットワークを調整して、VegetationMaskLineがズレてしまった場合は、VegetationStudioStatusのActiveを一度はずして入れなおせば、MaskLineが再描画されて、道路エリアに木が生えなくなる。

・TreePerimeterなどの設定で、道路わきから何メートルまで木を生やさなくするかなどの設定ができる。が、この設定は、エリア下方のResetAllRoadTypes and Objectsのボタンを押さないと反映されない。

ふー2:21になった。

・・・と思ったら、Activeを押してもResetAllRoadTypes and Objectsを押しても反映されなくなった。なんでやー涙。これバグなんじゃないの!?と思い、藁にもすがる思いでUnity再起動して設定してみると、ちゃんと動くのだった。・・・バグじゃん!怒EasyRoadには悩まされてばかりだ。

ふー2:43になった。

なんか日本語のWikiがあるっぽい?ただのリンクにも思えるが。

3Dモデリングを始めたって話

ここに八角形があるじゃろ?

( ^ω^)

⊃八角形⊂

これをこうして

( ^ω^)
≡⊃⊂≡

こうじゃ
( ^ω^)
⊃手⊂

\テ↑ーテレレ テレレ レー♪/

3Dモデリングもいろいろ

そもそもモデリングの方法っていろいろあって、上の手はボックスモデリングといってコンピューターで扱いやすいポリゴンの作りになってます。

ソフトで扱うには4角形か3角形がベストらしいです。ちなみにUnityは3角形のポリゴンを使うらしい。よう知らんけど。他にもスカルプティングという方法で、多分想像する液タブを使って粘土こねくり回して作ってるような感じでモデルを作る方法もあるのですが、あれは異様にポリゴンが多くなるのでコンピューターで扱うにはやや処理が重すぎるので画像みたいな感じでレンダリングするのに使われます。リトポといってスカルプティングで作ってからボックスモデリングでポリゴンを減らしたりすればソフトでも使えるようになるようですが。

3D CAD

CADは3D CADと2D CADがあって、3D CADは車とか精密なものを作ったりするのが得意です。あとはパーツ事に編集できるものが多いので保守・改造が楽です。業界ではAuto CADが有名ですが、自分はFree CAD使ってます。

 覚えれば割と複雑なものが作れますが、残念ながら日本人金持ちが多いのかFree CADの記事が少ない。学習するならYoutubeで海外のチュートリアルを見るといいです。この辺とか。Free CADは大して使ってないので画像はないです。

疲れたんでこの辺で書くのやめときます。

Blender(手を作ったモデリングソフト)は無料だし、決して業界でメジャーではないにしても最近でっけぇ企業も使い始めた激熱な3Dモデリングソフトなのでお勧め。何より2.8以降は2.7系と違ってすっきりしたので使いやすくなってます。とてもいい。ただ業界ではMayaがメジャーなようです(金持ちどもめ。。。)Blenderの使い方はBlender Guruって人の動画が分かりやすいし、この人教え方がうまいです。それとBlenderのバージョンが上がるたびにドーナツ作ってますが、ドーナツとマグカップが作れるころにはBlenderで大半のものはモデリングできるようになってるので、やるなら見て損はないかと。全部英語だけど。

以上。

WordPressでLMS

LMSとはなんぞや?LearningManagementSystemの略である。Wordpressはプラグインが豊富なので、低コストで作れるのでは・・・?実際、WordPressにはLMSプラグインがいくつもあるらしい。探すと日本人でやってるひともいるようだ。


オンラインコースをノーコード(NoCode)で作れるプラグインLearnDash
ナオミさんの紹介サイトがある。テスト、質問、課題、証明書なども、機能として統合されている。WooCommerceと組み合わせてオンライン講座を売ることもできる(!)。個人学校ができるってワケね。単純に面白そうである。10サイトで$189は高いのか安いのか・・・機能による。

根本さんの動画のほうが詳しいね。ライセンスキーとプラグインのダウンロード・・・。有効化などの方法が。見てるとやってみたくなるね。

2時間の英語講座。かなり詳しくわかりそう。学習サイトを作成するために学習しなければならないという、ポジティブな本末転倒が生じるような。。。

あ・・・他にもいろいろたくさんあるね。

・Teachableのようなeラーニングシステムが構築できるLMS有料プラグインLearnDash使い方解説目次
なるほど日本語化しやすいのも魅力か。そうかオンラインサロンというジャンルなのか。はへー。

LearnDashの使い方:WordPressでオンラインスクールを作成する方法(根本さん
ふむ・・・。LearnDashはシェアが高いLMSらしい。ふーむ、具体的な情報は少ないね。

・LearnDash LMS 世界シェアナンバーワン(恐らく)のLMSシステム
「ほとんど全てのLMSツールを知っているがLearnDash LMSが一番の大本命だろう。」だそうで。Udemyレベルのものが作れると。Udemy使ったことないからわからないけど。

LifterLMSというものもあるらしい。無料で使えるが課金システムがない。社内教育などはこれで十分とも。小テストのバリエーションは少ない。なるほど。