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

23mh203 10/24までの報告

合成音声の好感度がリラックス度合にかかわる生理指標にどこまで影響するか、とりあえず予備実験を4名協力していただき、そのデータを概観する

 10/24までに3名のデータを取得(内1名の実験中、別のところに気を取られる場面があったのでデータに不安あり、もう一名取るかも・・・)

・結果
 皮膚温のデータはあまり変化の無いように思える・・・
 RMSSDについては、kybiosの時間設定を間違えていることに気づいたので明日朝修整予定。少し見たところ好感度大と小では被験者内で一貫性があるかもしれない。
まだ順序効果の可能性も捨てきれないため、データの修正と4人目の結果から検討したい。

本日は作業がままならなくなってきたので取り急ぎここまで

R-4.3.1 for Windows

はじめに
 卒論の実験で取得したデータをもとに, js-starから3要因の分散分析(AsBCモデル)を行っていたところ, 二次の交互作用で有意な差が認められた。しかし, js-starでは二次の交互作用の下位検定が行えなかった。一時は断念したがネットで調べると, js-starのもととなった「R」は下位検定を行うことが可能であった。今回は, Rによる下位検定および使用上の注意点をまとめる。

1. R-4.3.1
・Download:リンク
・js-starとの連携方法:リンク

2. パッケージ
 デフォルトでも分析は行えるが入れておくと便利なパッケージを紹介する。パッケージのインストール方法は, 「パッケージ→インストール→Japan→(任意のパックを選択)→ok」を行い, スクリプト画面に「library(パッケージ名)」を入力して漸く使用できる。全体的な操作を通じてPython感があった。

library(Rcmdr):マウス操作で分析を行う
library(sem):Rcmdrのみだとエラー表示のため
library(psych):記述統計量の出力

3. Rの分析方法
 ここでは, js-starの算出結果を元に, Rの3要因分散分析の分析方法および結果の見方について紹介する。なお, プログラムはjs-starで発行されたものを使用.

① js-starで分析
 通常通りjs-starから分析を実行する。この時,Rオプションの多重比較p値調整法は,Holm法にする(デフォルトではBH法).ページを下部にスクロールさせ「Rプログラム:第1~3枠」のプログラムを用いる。それぞれ「第1枠=主分析」「第2枠=交互作用の下位検定」「第3枠=二次の交互作用の下位検定」を表している。

  

② Rで実行
 Rに移動し, 「library(Rcmdr)」と入力して実行する。その後, Rスクリプト部分に, 先ほどの「Rプログラム:第1~3枠」のプログラムをコピペする。実行する箇所を聞かれるため, ctrl+Aで全選択した後, 実行を行う。すると赤文字でプログラムが書き込まれ, 統計結果は青文字で記載される。また, それに応じた図も表示された。

③ 結果の見方
 正直な話, 出力画面に何百行も表示されているが, 第3枠の出力は第2枠も補っているため, 省いていい。また, Rを使用して感動したのが, 統計結果をレポート形式でまとめてくれることだ。つまり, 第3枠の「#結果の書き方」を確認すれば, この長い出力結果と睨めっこしなくていいようだ。下記が出力結果の例である。

  • 要因Aを参加者間,要因B・Cを参加者内に配置した3要因分散分析(TypeⅢ_SS使用)を行った結果 (Table(tx1)参照),主効果Aが有意でなく (F(2,11)=1.196, p=0.338, ηp2=0.179, 1-β=0.866),主効果Bが有意傾向であった (F(1,11)=3.99, p=0.071, ηp2=0.266, 1-β=0.842)。
  • 二次の交互作用を分析するため単純交互作用検定 (α=0.20) を行った (Table(tx5)参照)。その結果,A3におけるBxCが有意であった (F(4,44)=9.366, adjusted p=0, ηp2=0.46)。以下,有意な単純交互作用についてさらに単純・単純主効果検定 (α=0.35) を行った (Table(tx7)参照)。A3におけるBxCについては,単純・単純主効果BがC5で有意であり (F(1,11)=9.317, MSE=0.301, adjusted p=0.17),B1の平均0.681がB2の平均-0.377よりも大きかった。

 一部省略したが, 主効果・一次の交互作用・二次の交互作用の下位検定が確認できる。この記述方法を推奨されているなら, 分析後コピペで済む。めちゃくちゃ楽だ。ただ,多重比較の結果だけは,文章として出力されないためsasのように出力結果を確認する必要がある.また,交互作用の下位検定の有意確率が15%になっているため注意が必要.

==========================================================================

まとめ
 Rによる分析方法を紹介したが, js-starを介せば, プログラムも一切不要。また, 統計結果もレポート形式でまとめてくれて, この面のみ見れば非常に便利であった。また, パッケージなどを使用することにより, 上記で紹介した分析ツール以外にも「PDF化, レポート作成, Googleの各種API取得」などできるようだ(サイト)。Rには驚かされてばかりだ…sasよりこっち習いたかったな。

コットの足

Futurefoxのコットの足が折れること4本目。「保証期間が過ぎたので、オプションパーツを買い求めください」とのことで、2000円かかる。今後も折れる予感がするが、その度買うのはちょっと・・・捨てるしかないのか!?こんな時こそ3Dプリントじゃない!?

PLAで作っても、いかにも折れそうなので、スライサーを設定変更して強化する。外殻(ウォール)は通常2層のところを7層に。TopとBottomの厚みも4ミリに、Infillは80%だ。印刷経過を見てたけど、この設定だと、ほぼほぼ100%詰まってるぞ笑

出来上がったパーツ(印刷時間約2時間)は、ずっしりと重みがある。穴の遊びもまぁ悪くない(純正品と変わらない)レベル。さて、機能するのか!? 写真を取り忘れたけど、ちゃんとコットに組み付けても大丈夫そうだった。「これで足折り放題ですね!(重田)」との事だが、SDGsにはこういう安心感が大事じゃないですか?

M2TP大容量Ver.

M2TP(無線皮膚温測定器)の電池を大容量化した。ケースの下側を再デザインし、850mAhのリチウムイオンバッテリーを内蔵可能とした。ちょっと厚みがあるけれど、6時間程度の動作時間が期待できる。4台作成を試みたけど、4台目は調子が悪いみたいでダメだった。設計ファイルとプログラムも登録し、とりあえず完了。

0628生理心理学特殊研究

18:00~ 
作業内容としては
1.EMG測定器2つの動作チェック
2.配線整理
3.プログラムの修正
(プログラムの修正に関しては長野先生の投稿にて
これで毎度プログラムを書き込まなくて済む・・・)
4.AI測定と同時に実施して、問題点のブラッシュアップ

1.EMG測定器2つの動作チェック
1つめの測定機(大きい方)に関しては問題なし
しかし、0626では使えていたが2つ目の測定器(小さい方)のうち、
  片方の測定ができない(画像青部分)


 左右を変えて計測しても、プラグを変えても測定不可
  配線は手を加えていないので、ボード上の電子機器が接触不良の可能性

2.配線整理
  長い配線が計測中にどこかに引っ掛かり、外れる可能性があるので短いものと交換 
 した

4.AI測定と同時に実施して、問題点のブラッシュアップ
 大きい方の計測器とiPadのAI測定を用いて同時に測定をしてみる
配置は図の通り

 表情読み取りのiPadとEMG測定器はBluetoothでPCと接続
 PCとモニターは有線接続のうえ、2画面のモードにすることで、PC側から動画再生などの操作を可能にした(PC画面はこんな感じ↓)

結果 測定自体は問題なくできることが確認できた

内省報告(兼改善点)
 iPadのカメラが下側にあるため高さを稼ぐ必要がある
 電極によって頬が引っ張られるような感じがした
 PCのポートがほとんど埋まる
 Unity の右上に経過時間が表示されるが、他のタブと被って見えなくなってしまった
 

HTTP_Fcap

WebCamに現在写っている顔の数を数えてサーバーに保存する
開発場所:CVUnity内、HTTPFcapシーン
OpenCVforUnityのLibFaceDetectionV3Exampleを改造し、検出した顔の情報をWebサーバーに投げて保存するプログラム。今回は測定結果の保存先がWebサーバーであるため、新たにスクリプト「HTTTPrecord」を作成した。データの保存先はここ。アプリケーションのダウンロードはこちらから。

データを受け取るPHPスクリプトは、以下のアドレス。
http://kodamalab.sakura.ne.jp/FaceDetectNum/record.php
データは、「20230608.csv」などのように、日付ファイル名で記録される。記録内容は、検出された顔の数、顔1の信頼性、X座標、y座標、横幅、縦幅、顔2の…といった並びである。

<?php
$data = isset($_POST['data']) ? $_POST['data'] : '';  ; // データをPOSTから取得

if (!empty($data)) {   					
    $date = date('Ymd');   				// 現在の日付をYYYYMMDD形式で取得
    $timestamp = date('Ymd_His');   
    $filename = "{$date}.csv";   		
    $file = fopen($filename, 'a');   	
    fwrite($file, $timestamp . ',' . $data . "\n");   // タイムスタンプとデータをファイルに書き込む
    fclose($file);   					
    echo "recorded";   					
} else {
    echo "No data!";   					
}
?>

EliteHRV

PolarH10をHRV解析に用いる、低コストで確実な方法はEliteHRVを用いることだ。このソフトウェアはHRVバイオフィードバックを行うためのものであり、iPhone版とAndroid版がある(これ大事)。日本での紹介事例は少ないが、海外では広く使われている。使い方は下の動画を見ればなんとなくわかるが、Polar H10とEliteHRVの組み合わせはとてもすばらしい。

動画では光計測デバイスを用いる例もあるが、指先の血管に伝わってきた拍動情報では心拍変動を正確に評定することは困難であるため、EliteHRVはH10での計測を推奨しており、計測したRR間隔データをExportする方法も提供している。具体的には測定後、ユーザーアカウント部分をクリックし、ExportDataをクリックすると、登録されたメールアドレスに最近計測したデータがメールで転送されるという仕組みだ。出力結果は標準的なRR間隔データで、kubiosにそのまま読み込むことができるので便利だ。

音声の印象評定のお願い その2

文京学院大学大学院1年の庵袋晴輝と申します。修士論文の予備調査として、音声の印象に関する調査をしています。
ご協力いただける方は下記の手順に従って回答をお願いいたします。
ひとつの音声は30~40秒程度です。

手順
1.下記のFromを表示して質問票を表示してください
 フォームへのリンクはこちら


2.音声再生ページを下記のリンクから表示してください。
 音声再生ページへのリンクはこちら


3.下記のように、印象評定ページと音声再生ページを並べた状態で評価を行ってください。再生する音声の順序は、参加者によってランダムになっているため、Formsに表示された順序で上から順番に8種類を評定してください。

音声は回答ができるなと感じたところで再生を止めていただいても構いません

ARkit vs MediaPipe

Apple ARkitのアドバンテージは
 MediaPipeのFacemeshを使って、「・・・コレ大丈夫か?」と思ったのは事実。推定されたMesh位置情報を高速でサンプルして描画すると、激しいノイズが。メッシュの推定がブレているということだ(見た目にもそんな予感はしていた)。顔の姿勢取得も苦労したが、そもそも2/15の記事で、ARkitの方は眼球の姿勢がとれていた(当然顔の姿勢もとれるだろう)。
 改めてARkitの顔認識をよく見ると、(こんなに暗いのに)ものすごくピッタリ推定できており、口の動作もほとんど完璧だ(Mediapipeは横向くと推定が怪しくなり、口も勝手に開いたりする)。google vs apple、IT界の両雄が作る似たサービス、同じくらいのクオリティがあると思ったら間違いで、おそらくこれに関してはARkitの圧勝だ。・・・自分は今、岐路に立たされている。Appleの軍門に下る事(あるいはApple製品を新たに購入するコスト)を避け、Mediapipeで実装すると、AIによる顔認識研究のクオリティは下がり、僕の評判も悪くなるだろう。「ここは買っとけ、iPad買っとけ!」・・・私のゴーストがそう囁くので、ケチケチせずiPadを2つ購入しようと思う。今、AI非接触計測の経験値を高めておけば、きっと何十倍にもなって返ってくる(ハズ)。このような実践で鍛えられた「◯◯のような用途にはこのAIが使える」といった細かな経験値が、今後数年はモノを言う気がする。

iPadのARkit対応状況はこちらのサイトにまとめられている。2019年のモデルあたりから使えるみたいだけれど一番安いのはどれかな。iPad Proは高機能だけれど2つ買うのは絶対嫌だし、ひょっとして2021年モデル(64GB)が43000円というのは、「買い」なのではないだろうか!?自腹なら中古でiPhoneという手もあるが、\24800のいつ壊れるかわからないXsを購入するのは危険に思える(実際壊れたXsが手元にひとつあるわけだし)。

Blendshapeを取得する
そして確認されるBlendshape。これはあくまでBlendshape値なので、顔の動きそのものではないが、運用上はこのほうが都合が良い。お笑いを見せて、一番動きが大きなBlendshapeを笑いの評価に使うとか。。。大頬骨筋に比べると、皺眉筋の動作検出は弱いように思える。用途の問題なのか、そもそも動く量が少ないからか。数値的にはEMGのアドバンテージは確定的にも思えるが・・・。

皺眉筋、大頬骨筋、上唇挙筋などに対応したブレンドシェイプがあるように思える。いろいろな動画刺激に対して、これで感情評価を行えば良い。ipadをどう固定するか考えないとね。

音声の印象評定のお願い

実験の大まかな内容

1.下記のFromを表示して質問票を表示してください。
フォーム

2.音声再生ページを下記のリンクから表示してください。
音声再生ページ

3.下記のように、印象評定ページと音声再生ページを並べた状態で評価を行ってください。再生する音声の順序は、参加者によってランダムになっているため、Formsに表示された順序で上から順番に10種類を評定してください。

pythonでbardを使う

ChatGPT対抗手段として、とうとうリリースされたのがGoogleの大規模言語AI「Bard(吟遊詩人?)」である。どうやってPythonから使うのかな?・・・なんかBardに教えてもらった方法で、できないんだけど・・・

PythonでBardを使う例(230516)
BardAPIて?
あ、こちらでも解説されていますね
BardAPI本家 すばらしい・・・
GPTとBardで意思決定 自己採点のアイデアが良い。互いに採点もできるの!?
GPTとBardに概念を考えてもらう プロンプトが参考になる

・・・そして完成するBradとの会話プログラム。BradAPIを使っています。APIkeyは、ブラウザのクッキーから取得するという手順。これでいいんだろうか?・・・やはり現在の情報が参照できるのはアドバンテージありますね。しかし、推論の妥当さなどはGPT3.5や4にアドバンテージがあるように思う。どのような実装にすべきか、悩みますね。Unityから呼び出す方法は、まだ解説されていないようだし。

from bardapi import Bard
import os

os.environ['_BARD_API_KEY']="hogehoge."
 
 
def main():
  
    print("チャットをはじめます。q または quit で終了します。")
    print("-"*50)
    while True:
        user = input("<あなた>\n")
        if user == "q" or user == "quit":
            print(f"トークン数は{amount_tokens}でした。")
            break
        else:
            #chat.append({"role": "user", "content": user})
            msg=Bard().get_answer(user)['content']
 
        print("<Bart>")
        print(msg)
 
 
if __name__ == "__main__":
    main()

現状・・・調べ物にはBardがいいけど、人格ドライブにはGPT3.5がいいように思える。Bardに協力してもらおう!

#サイト上のcommandをチェックしBardでanswerに問い合わせ結果を書き込むスクリプト
from bardapi import Bard
import os
import time
import requests

os.environ['_BARD_API_KEY']="ほげ"

command_url = "http://kodamalab.sakura.ne.jp/AIchat/Bard1/command.txt"
response_url = "http://kodamalab.sakura.ne.jp/AIchat/Bard1/response.php"

#ファイルサイズを得る
def get_file_size(file_url):
    response = requests.head(file_url)
    try:
        return int(response.headers['Content-Length'])
    except KeyError:
        return None


#コマンドの内容を得る
def get_command(file_url):
    response = requests.get(file_url)
    response.encoding = 'utf-8'
    return response.text.strip()

#Bardからの回答を保存する
def write_response(response_url, response_text):
    data = {'response': response_text}
    requests.post(response_url, data=data)


answer=""
last_size = get_file_size(command_url) or 0
while True:
    current_size = get_file_size(command_url) or 0
    print("." , end=' ')
    if current_size != last_size:
        command = get_command(command_url)
        print(f"<COMMAND>{command}")
        answer = Bard().get_answer(command)['content']
        print(f"<ANSWER>{answer}")
        write_response(response_url, answer)
        last_size = current_size
    time.sleep(2)  # wait for 5 seconds before checking again

c#から呼び出す方法
解説されているが、アラビア語で理解できないという。コードを見れば・・・わかるよね?

・・・このコードは、UnityではないC#用で、LinqやThreadingなどの新しい手法を用いており、いまいち何をしているのか理解できない。エラーも出ているようだし・・・。とりあえずすべて打ち込んで、GPT4に解説してもらう。

コード1(Bard_Serviceクラス)とコード2(BardResponseModelおよびResultクラス)は、Googleの大規模言語モデルBardのAPIに接続して問い合わせを行うためのクラスです。

コード3は、これらのクラスを使用して実際に問い合わせを行うためのコードです。具体的には、エジプトの面積について問い合わせています。

以下に、各コードの詳細な説明をします。

コード1(Bard_Serviceクラス)

このクラスは、Googleの大規模言語モデルBardのAPIに接続し、問い合わせを行うためのサービスクラスです。

    apikeyとendpointは、Bard APIへの接続情報を保持します。
    Bard_Service(string apikey, string endpoint)は、コンストラクタで、APIキーとエンドポイントをセットします。
    AskBard(string prompt)メソッドは、引数として渡されたプロンプト(問い合わせ)を用いてBard APIにPOSTリクエストを送信し、その応答を返します。成功した場合は応答の内容を返すべきですが、現状では成功した場合の処理が不足していて何も返していません。失敗した場合は例外をスローします。

コード2(BardResponseModelおよびResultクラス)

このクラスは、Bard APIからの応答をデシリアライズ(文字列からオブジェクトへの変換)するためのモデルクラスです。しかし、コード1の現在の状態では、このモデルクラスは使われていません。

コード3(Programクラス)

このクラスは、上記のサービスクラス(Bard_Service)を使って、Bard APIに問い合わせを行うメインのプログラムです。

    BARD_API_ENDPOINTは、Bard APIのエンドポイントを保持しています。
    Mainメソッドでは、Bard_Serviceクラスのインスタンスを作成し、そのAskBardメソッドを呼び出してBard APIに問い合わせを行い、その結果をコンソールに出力します。

ただし、現状のコードでは、問い合わせが成功した場合の処理が不足しているため、問い合わせの結果を正しく取得して出力することはできません。これを修正するには、コード1のAskBardメ

すみません、切れてしまいました。

AskBardメソッド内で、成功した場合の結果(result)を適切に返すように修正する必要があります。つまり、以下のように修正すべきです:
public async Task<string> AskBard(string prompt)
{
    var request = new HttpRequestMessage
    {
        Method = HttpMethod.Post,
        RequestUri = new Uri(endpoint),
        Content = new StringContent(prompt,Encoding.UTF8, "application/json")
    };

    var client = new HttpClient();
    client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", apikey);

    using (var response = await client.SendAsync(request))
    {
        if (response.IsSuccessStatusCode)
        {
            var result = await response.Content.ReadAsStringAsync();
            return result;  // 追加:成功した場合には結果を返す
        }
        else
        {
            throw new Exception("Request failed with status code "+ response.StatusCode);
        }
    }
}

なお、Bard APIからの応答は通常JSON形式であり、コード2に示されたBardResponseModelクラスを用いてデシリアライズすることを想定しているように見えます。したがって、より完全な実装では、応答をこのクラスにデシリアライズし、その結果を返すようにすべきでしょう。それには、たとえばSystem.Text.Json.JsonSerializerを使用することができます。

最後に、ProgramクラスのMainメソッド内では、AskBardメソッドが非同期(Taskを返す)であることを考慮し、その結果を適切に取得するようにする必要があります。具体的には、.Resultまたは.GetAwaiter().GetResult()を使用して結果を取得するか、Mainメソッド自体を非同期にしてawaitを使用することが考えられます。

ふむふむ・・・やはりコード自体も未完成のようだね。UnityでCoroutineをつかう形式に書き換えてもらおうか。・・・うーむ、そもそもこのコード呼び出し用URLもNotFoundだし、正しく動作しない気がする。一旦保留しようか。
・・・BartAPI本家に、Python他言語に移植したソースが昨日公開されていた。CSもあったが、UnityはフルCSじゃないから、GPT4にUnity対応してもらったのが下コード。コレが動けば、Bart関係の処理が盤石になるな。

using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using UnityEngine;
using UnityEngine.Networking;

public class Bard : MonoBehaviour
{
    private const string BARD_URL = "https://bard.google.com/_/BardChatUi/data/assistant.lamda.BardFrontendService/StreamGenerate";

    private string token = "your bard token";
    private int reqId;
    private string conversationId;
    private string responseId;
    private string choiceId;

    void Start()
    {
        this.reqId = new System.Random().Next(1000, 9999);
        this.conversationId = "";
        this.responseId = "";
        this.choiceId = "";
        StartCoroutine(GetAnswer("input text here"));
    }

    private IEnumerator GetAnswer(string inputText)
    {
        Dictionary<string, string> headers = new Dictionary<string, string>
        {
            { "Content-Type", "application/x-www-form-urlencoded;charset=UTF-8" }
        };
        headers.Add("Cookie", $"__Secure-1PSID={this.token}");
        WWWForm form = new WWWForm();
        form.AddField("bl", "boq_assistant-bard-web-server_20230419.00_p1");
        form.AddField("_reqid", reqId.ToString());
        form.AddField("rt", "c");
        // to be filled out with correct data serialization
        form.AddField("f.req", $"[null, []]");
        form.AddField("at", "SNlM0e"); // to be filled out with correct SNlM0e value

        using UnityWebRequest www = UnityWebRequest.Post(BARD_URL, form);
        foreach (KeyValuePair<string, string> entry in headers)
        {
            www.SetRequestHeader(entry.Key, entry.Value);
        }

        yield return www.SendWebRequest();

        if (www.result != UnityWebRequest.Result.Success)
        {
            Debug.Log(www.error);
        }
        else
        {
            // TODO: Process the response, similar to the GetAnswer method
            Debug.Log(www.downloadHandler.text);
        }
    }
}

FcapMeasure230513

プログラムの概要
 OpenCV顔認識を用い、2名の参加者の顔位置と向きを測定します。このプログラムは以下の条件を前提としています。

・2名ぶんの顔のみが画面に写っていること
・2名の顔は、中央の赤線を境界として、左側・右側に写っていること

3名以上の顔が写っている状態や、2名の顔が片側に映るような状況では適切に動作しません。

データの取得方法
 画面下部の1行入力部分に、測定結果のCSVファイルの保存場所が格納されています。エクスプローラーのパス部分にコピーしてお使いください。ファイルには、「20230513_204805.csv」のような、日付と時間を基準にした名前がつけられています。
 取得したファイルを開くと、下記のような構造の25列のデータが入っています。左右の顔に関して、顔である確率(0~1)、右目(x1,y1)、左目(x2,y2)、鼻(x3,y3)、右口角(x4,y4)、左口角(x5,y5)の5ポイントの座標が保存されています。顔が検出されなかった場合は、空白が記録されます。

FcapMeasure実行ファイル

Biopac・KubiosでHRV解析

BIOPACで測定したECGデータをKubiosで解析する
ここでは、Biopacを用いてECGを計測しKubiosを用いて、各種の心拍変動解析を実施する方法を説明します。各手順の詳しい方法は、動画の下の解説をご覧ください。

BIOPACでECGを測定
BiopacのMP100を用いて、1チャンネル目にECG、2チャンネル目にHR、3チャンネル目にRR間隔を表示・計測します。

データの出力と形式の確認
「File>Save as」でデータを保存すると、ECG、HR、RR間隔の各値が、200Hzのサンプル周波数で、タブ区切りで保存されていることがわかります。以下のPythonスクリプトを用いて、ECG波形からRR間隔を算出してみましょう。

#ECG2RR.py
#Transfer ECG wave data to RR interval data
import sys
import os
import numpy as np
from scipy.signal import find_peaks
import matplotlib.pyplot as plt

# コマンドライン引数からファイル名を取得
file_name = sys.argv[1]

# ファイルの読み込み
data = np.genfromtxt(file_name, delimiter='\t', usecols=[0, 1, 2])

# 1列目のデータの取り出し
ecg = data[:, 0]

plt.figure(figsize=(10, 6))  # 幅: 10インチ, 高さ: 6インチ
plt.plot(ecg)
plt.xlabel('Sample')
plt.ylabel('ECG')
plt.title('ECG Data')
plt.show(block=True)

# ピークの検出
peaks, _ = find_peaks(ecg, height=0.5)

# ピーク間隔の計算
peak_intervals = np.diff(peaks) * 0.005 * 1000  # convert to milliseconds
#print(peak_intervals)

plt.figure(figsize=(10, 6), dpi=100)  # 幅: 10インチ, 高さ: 6インチ, dpi: 100
plt.plot(np.arange(1, len(peaks)), peak_intervals)
plt.xlabel('Peak')
plt.ylabel('Interval (ms)')
plt.title('Peak Intervals')
plt.show(block=True)

# ファイル名の拡張子を除いた部分を取得
file_name_base = os.path.splitext(file_name)[0]

# ピーク間隔を保存
output_file_name = file_name_base + '_RR.csv'
np.savetxt(output_file_name, peak_intervals, delimiter=',', fmt='%.2f')
print('Peak intervals saved to', output_file_name)

このスクリプトを使って「ECGdata1.txt」というファイルを処理する際は、「python ECG2RR.py ECGdata1.txt」のようにコマンドを打ち込みます。すると、データが読み込まれ、ECG波形が表示された後、検出されたRR間隔データが表示されます。RR間隔データは、「ECGdata1_RR.csv」という名称で同一階層に保存されます。

Kubiosを用いた心拍変動解析
上記で出力されたRR間隔データをKubiosで解析してみましょう。解析を行う範囲を指定すると、画面下方に「Time-domain」、「Frequency-domain」、「Nonlinear」の解析結果が表示されます。解析範囲を切り替えながら、各評価地をチェックしていきましょう。

Pythonでつくよみちゃん

基本編
Coeiroinkは、Python経由で制御が可能だ。こちらの記事を参考にやってみる。ふむふむ、仮想環境をAnacondaで作成したら必要なライブラリをインストールしていくと。なるほど、ローカルホストに音声合成サーバーが立ち上がっているので、そこに向かってコマンドを投げると喋ってくれるというわけですね?・・・なるほど~、CPU版だと変化にそこそこ時間がかかりますね。リアルタイムで会話するためにはやはりGPU版が必要ですね。まあしかし、チャットjptにクエリを投げるPythonプログラムとこのプログラムが合体させると、音声による会話に一歩近づくわけで。

import json

import requests
from pydub import AudioSegment, playback

# パラメータ
text = "こんにちは、つくよみちゃんです。よろしくお願いします。"  # セリフ
text2="先日さ、友達とカラオケに行ったんだけど、その時の話がすごく面白かったんだよね。みんなで歌って楽しんでいたんだけど、途中で友達の一人が「誰か知らないけど、めちゃくちゃ上手い人が歌ってる!」って言い出したんだ。";
speaker_id = 0  # スピーカーID (0:つくよみちゃん)

# 音声合成のクエリの作成
response = requests.post(
    "http://localhost:50031/audio_query",
    params={
        'text': text2,
        'speaker': speaker_id,
        'core_version': '0.0.0'
    })
query = response.json()

# 音声合成のwavの生成
response = requests.post(
    'http://localhost:50031/synthesis',
    params={
        'speaker': speaker_id,
        'core_version': "0.0.0",
        'enable_interrogative_upspeak': 'true'
    },
    data=json.dumps(query))

# wavの音声を再生
playback.play(AudioSegment(response.content,
    sample_width=2, frame_rate=44100, channels=1))

話者を変える編
さて、Coeiroinkは様々な音声を登録可能だが、どのようにして声を変えるのだろうか?各話者の音声ファイルはspeaker_infoフォルダに、話者ごとにフォルダで区別されて保存されている。その中に、「metas.json」ファイルがあり、Pythonプログラム内で使用できるspeaker_idが記録されている。このIDをPythonスクリプトに記述することで、声を変えることができるというわけだね。

PythonでChatGPT編
ここを参考に進めるが・・・動かない。なんでぇ?ここのほうがわかりやすいか。やはり動かない・・・。結局APIキーを新しく発行したところ、なぜか正しく動作するようになった。前のキーが無効になってる!?なんてことはないと思うんだけど。オープンAIのAPI使用量を、研究費から支払う方法がないかなぁ?

import openai
openai.organization = ""
openai.api_key      = ""

# =============================================================
# チャットボット関数
# =============================================================

def Ask_ChatGPT(message):
    
    # 応答設定
    completion = openai.ChatCompletion.create(
                 model    = "gpt-3.5-turbo",     # モデルを選択
                 messages = [{
                            "role":"user",
                            "content":message,   # メッセージ 
                            }],
    
                 max_tokens  = 1024,             # 生成する文章の最大単語数
                 n           = 1,                # いくつの返答を生成するか
                 stop        = None,             # 指定した単語が出現した場合、文章生成を打ち切る
                 temperature = 0.5,              # 出力する単語のランダム性(0から2の範囲) 0であれば毎回返答内容固定
    )
    
    # 応答
    response = completion.choices[0].message.content
    
    # 応答内容出力
    return response

# =============================================================
# チャットボット実行
# =============================================================

# 質問内容
message = "日本人の若者の特徴を教えてください"

# ChatGPT起動
res = Ask_ChatGPT(message)


# 出力
print(res)

このプログラムで、ChatGPTと延々と会話ができる。

import openai
openai.organization = "org-ほげ"
openai.api_key      = "sk-ほげ"


def main():
    amount_tokens = 0
    chat = []

    setting = input("ChatGPTに設定を加えますか? y/n\n")
    if setting == "y" or setting == "Y":
        content = input("内容を入力してください。\n")
        chat.append({"role": "system", "content": content})

    print("チャットをはじめます。q または quit で終了します。")
    print("-"*50)
    while True:
        user = input("<あなた>\n")
        if user == "q" or user == "quit":
            print(f"トークン数は{amount_tokens}でした。")
            break
        else:
            chat.append({"role": "user", "content": user})

        print("<ChatGPT>")
        response = openai.ChatCompletion.create(
            model="gpt-3.5-turbo",messages=chat
        )
        msg = response["choices"][0]["message"]["content"].lstrip()
        amount_tokens += response["usage"]["total_tokens"]
        print(msg)
        chat.append({"role": "assistant", "content": msg})


if __name__ == "__main__":
    main()

とうとう会話が成立する
それでまあ、音声AIを制御するスクリプトとオープンAIのAPIを呼び出すスクリプトを合体させると、音声で会話ができるということになる。あまり長々喋られると、変換に時間もかかるので、何文字以内で喋ってほしいなど、制限を加えた方がいいかもしれないね。入力側の音声認識を切っておかないと、AI側の発話が認識されてしまうという・・・この辺も工夫が必要だね。

まあ予想していたことではあるんですが、現状で利用可能なGPT 3.5は、ふじみ野市にツインリンクもてぎがあるなど、でたらめなことを平気で行ってくるので、使いどころが難しいですね。「○○について調べて、レポートにまとめておいて」などといった使い方ができるようになれば、少しはエージェントっぽくなるんだけど。GPT 4のウェイティングリストに入らないと・・・

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を直接接続できると、すごく便利なんだけど・・・