Whisper_文字起こしAI

はじめに
 噂によると,OpenAI社のWhisperという文字起こしAIの精度がとても高いようだ。学部2年の時に20分程度の面接法を行ったが,手作業で1文字ずつ文字起こしするのがとても辛かった思い出がある。そこで,AIが普及している今これを解消できるのでは?と思い試した記録をのこす。

1. Whisper_Web版:簡易版リンク
 こちらのWeb版Whisperは,ソフト不要で扱えるようだ。試しに,1分程度の音声合成AIのボイスで因子分析の解説音声を読み込ませてみたら,修正不要だった。20分程度の肉声動画ファイルもほぼほぼ修正不要であった。

操作方法は,「Audio file→音声ファイルをドラッグアンドドロップ→Transcribe→送信」で終了。translateを選択すると翻訳もできる。

Whisperは,どの形式の動画ファイルも読み込むことができる。この利点は,一台のスマホでメインの作業(例えば,通話やカンペを見る)を行い,バックグラウンドで録画できることだ。旧式のレコーダーいらずで,スマホ1台あれば事足りそうだ。録画は,カメラや下記画像のレコーダーアプリなどから行える。

 

2. Whisper_ソフト版使い方,無料ソフト

Web版の他に,ソフト版のWhisperがある。こちらは,プログラムを書かないといけないが,ソースコードはネットに掲載されており,APIキーも取得できるようだ。

ソフト版のメリットは,Web版に比べ多機能であること。その中の一つに,環境音を限りなく除去できるということ。上記画像2枚が,その一例のようだ。

3. 応用方法
 実際に面接を行ったデータをWhisperに読み込ませると,出力結果は下記のように文章が全てつながった状態で出力されてしまう。そこで,ChatGPT-4oに会話形式で出力してもらったところ,見事調査者と対象者に分かれ文章の誤字脱字も訂正してくれた。

しかし,所々語尾が変わったり,脱字の修正が適切でない場合があるため,プロンプトを練り直すこと,録画に気を付けること,そしてファクトチェックをすること。人間の仕事は,AIが出力した結果を確認し,指示を出すことで済みそうだ。

Pythonでランドマークの検出と,モーフィングをかける

はじめに
 悲しみや喜びの表情をモーフィングするには,まず顔のランドマークを検出する必要がある。やり方は様々で回帰分析ツリー,物体検出,回帰学習など,様々な方法があるが,Pythonでランドマークをやる場合,dlibライブラリを用いることでリアルタイムで高精度なランドマーク検出できるようだ。今回はこれのメモをのこす。

必要なライブラリ

pip install dlib
pip install imutils
pip install opencv
pip install libopencv
pip install py-opencv

*どうやらdlibライブラリは,一筋縄ではいかないようだ。方法は下記の通り。

①AIのDL(サイト):「shape_predictor_68_face_landmarks.dat.bz2」
②cmakeソフトのインストール:参照サイト1サイト2
環境変数:「詳細設定タブ→ユーザ環境変数→システム環境変数→環境変数」で,変更後pythonの会話画面でcmakeパスが通っているか確認する。

where cmake
where cmake-gui

ランドマーク&モーフィングの実行
 喜びの場合,参考基となる0%,100%の画像が必要となる。これらの画像と上記のライブラリ,ソフトをc直下のファイル内に入れたうえで下記プログラムを実行する。プロンプトは下記のようにした(作りかけ…)。一先ず,耳と髪をそぎ落とす。

①真顔(画像0:0%)から恐怖の顔(画像8:100%)へ変化するモーフィング画像を7段階で作成する。具体的なモーフィングレベルは画像0=0%、画像1=12.5%、画像2=25.0%、画像3=37.5%、画像4=50.0%、画像5=62.5%、画像6=75.0%、画像7=87.5%、画像8=100%。画像0と画像8は添付してある写真を用いる。
②顔の部分が見えるように楕円形に加工する。その際、髪の毛と耳は入らないように切りとる。
import cv2
import dlib
import numpy as np
import imutils
from imutils import face_utils

# 顔のランドマーク検出器をロード
detector = dlib.get_frontal_face_detector()
predictor = dlib.shape_predictor("shape_predictor_68_face_landmarks.dat")

# Load the images
img0 = cv2.imread(r"C:\ukeno\m01_neu_0.jpg")
img8 = cv2.imread(r"C:\ukeno\m01_fea_0.jpg")

# 顔のランドマークを検出する関数
def get_landmarks(image):
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    rects = detector(gray, 1)
    for rect in rects:
        shape = predictor(gray, rect)
        return face_utils.shape_to_np(shape)
    return None

landmarks0 = get_landmarks(img0)
landmarks8 = get_landmarks(img8)

if landmarks0 is None or landmarks8 is None:
    print("顔のランドマークが検出できませんでした。")
else:
    # 画像をモーフィングする関数
    def morph_images(img1, img2, landmarks1, landmarks2, alpha):
        points = [(int((1 - alpha) * x + alpha * y), int((1 - alpha) * x1 + alpha * y1)) for (x, y), (x1, y1) in zip(landmarks1, landmarks2)]
        img1 = np.float32(img1)
        img2 = np.float32(img2)
        result = np.zeros(img1.shape, dtype=img1.dtype)

        # 中心部分のランドマークインデックスを取得
        # 目、鼻、口の周りの領域
        central_indices = np.concatenate([range(17, 27), range(29, 36), range(48, 68)])
        mask = np.zeros(img1.shape[:2], dtype=np.uint8)

        # 中心部のランドマークの凸包を求めてマスクを作成
        cv2.fillConvexPoly(mask, np.array([points[i] for i in central_indices], dtype=np.int32), 255)

        # モーフィング処理
        for triangle in face_utils.FACIAL_LANDMARKS_IDXS.values():
            pts = np.array([points[i] for i in triangle if i < len(landmarks1)], dtype=np.int32)  # インデックス範囲内のみ使用
            cv2.fillConvexPoly(result, pts, (255, 255, 255))
        
        morphed = cv2.bitwise_and(img1, img1, mask=mask)
        result = cv2.addWeighted(img1, (1 - alpha), img2, alpha, 0, result)

        return result

    for i, alpha in enumerate(np.linspace(0, 1, 10)):  # 0から1まで10ステップ
        morphed_image = morph_images(img0, img8, landmarks0, landmarks8, alpha)
        filename = f"C:\\ukeno\\morphed_image_{i}.jpg"
        cv2.imwrite(filename, morphed_image)

出力結果
 0~9の順番で並べていないが、これはどっからどう見ても失敗だろうな。モーフィングが上がるにつれてボヤケている。おそらく、ランドマークのプログラムがよくないんだろう。そもそも、髪と耳がカットされてないみたいだ。

(著作権でのせられない)

ランドマーク
 やはり,高橋啓治郎先生のつよつよAIの方が,ポイントが多く倍以上あった。これもGithubから入手可能なようで,これを基にできたらやった方がいいかも。

ランドマークのプログラム例(参照サイト)

# coding:utf-8

import dlib
from imutils import face_utils
import cv2

# --------------------------------
# 1.顔ランドマーク検出の前準備
# --------------------------------
# 顔検出ツールの呼び出し
face_detector = dlib.get_frontal_face_detector()

# 顔のランドマーク検出ツールの呼び出し
predictor_path = 'shape_predictor_68_face_landmarks.dat'
face_predictor = dlib.shape_predictor(predictor_path)

# 検出対象の画像の呼び込み
img = cv2.imread('Girl.bmp')
# 処理高速化のためグレースケール化(任意)
img_gry = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# --------------------------------
# 2.顔のランドマーク検出
# --------------------------------
# 顔検出
# ※2番めの引数はupsampleの回数。基本的に1回で十分。
faces = face_detector(img_gry, 1)

# 検出した全顔に対して処理
for face in faces:
    # 顔のランドマーク検出
    landmark = face_predictor(img_gry, face)
    # 処理高速化のためランドマーク群をNumPy配列に変換(必須)
    landmark = face_utils.shape_to_np(landmark)

    # ランドマーク描画
    for (i, (x, y)) in enumerate(landmark):
        cv2.circle(img, (x, y), 1, (255, 0, 0), -1)

# --------------------------------
# 3.結果表示
# --------------------------------
cv2.imshow('sample', img)
cv2.waitKey(0)
cv2.destroyAllWindows()


OBSの最初の設定

OBSの最初の設定についてのまとめ

  1. 画面キャプチャ追加
  2. マイク設定
  3. マイクフィルタ設定
  4. 出力場所
  5. ショートカット
  6. 録画フォーマット変更

1 画面キャプチャ追加

 1 ソースの「+」をクリック

 2 画面キャプチャを選択

 3 画面からキャプチャする画面を選択

2 マイク設定

 ※マイクがない場合は「+」→「音声入力キャプチャ」で追加!

 1 基本的にはマイクは最大値でOK!必要に応じて調整

 2 マイクの「歯車マーク」→「プロパティ」で入力デバイスを選択

3 マイクフィルタ設定

 1 マイクの「歯車マーク」→「フィルタ」を選択

 2 「+」→「ノイズ抑制」→「方式」で好きなほうを選択

4 出力場所設定

 1 画面右下「設定」を選択

 2 「出力」→「録画ファイルのパス」で保存先を選択(デスクトップ推奨!)

5 ショートカット設定

 ☆録画の作業画面を映さないようにするために使える!!

 1 画面右下「設定」を選択

 2 「ホットキー」を選択し好きなように設定(Ctrl+Alt+S推奨)

6 録画フォーマット変更

 1 画面右下「設定」を選択

 2 「出力」→「録画フォーマット」から変更

 ※mkvは動画編集向け。基本はmp4を選択すれば問題なし。

 3 「適用」を押してから「OK」を選択(警告は無視して〇)

MAIA_3因子の考察

北原(2019)
・MAIA「気づき・注意制御・感情への気づき因子」を用いて,①「脱中心化,視点取得,ひいては認知的再評価を説明するという仮説モデルの構築」②「身体感覚の知覚そのものは精神的問題を生じやすい一方で,内受容感覚への気づきによって適応的な感情調整が促された場合には,精神的問題が軽減されるか」について検討。

・結果:身体感覚の単純な知覚は,「抑うつ・不安」を高めるが,身体感覚への「気づき」が「感情への気づき」や「注意制御」につながり,脱中心化に基づいた適応的な感情調整が促されると,「抑うつ・不安」が軽減されるという関連性が示唆された

先行研究
①「内受容感覚MAIA×(マインドフルネス)FFMQ」正の相関(栗野,2022)
 →互いに身体意識に注意を向ける尺度である(Mehling, 2012)
 →マインドフルネスによって,内受容感覚の敏感さ(IS)が向上
 →MAIAと生理指標(HR, SCL):注意制御が高いとHR下降,SCL増大
  SCLの増大は,注意や認知と関連がある。HRは注意を向けると下降
 →「内受容感覚MAIA×FMS ver.a.j(フォーカシング的態度)」負の相関
 →特性不安と有意な相関は認められない

②内受容感覚3種測定(櫻井・清水,2018)
・手続き:MAIA測定後,心拍カウント・心拍弁別課題を実施
・相関:「注意制御因子×気づき・心配しない因子」正の相関,「感情への気づき因子×気づき・注意制御因子」正の相関
・心拍~課題の相関:「心拍カウント成績×自己制御因子」正の相関のみ
→課題間の有意な相関は認められなかった。異なる側面を反映している
→質問紙とも有意な相関は示されなかった。〃
・心拍カウント課題で,「1回も心拍を感じなかった」が多い

③庄司(2017)のMAIAのまとめ
・内受容感覚の低下を修正する試みで,介入群に3か月の瞑想を行った結果,コントロール群と比較して,「attention regulation、emotinal awareness、self regulation、body listening、body trust-ing 」の各因子で改善がみられた。

④田中(2019)
・感情や情動と内受容感覚(IAc)
→脳指標を用いて内受容感覚の正確性を測定することが盛んとなっている。反映されるのが「島皮質(前部)」とされ,正確性の島皮質の灰白質体積が相関することから,島皮質の活動量から正確性が判断されている。「島皮質(前部)」が感情の主観的経験に中心的な働きをしている(心拍数が上がると興奮状態にあるなど)。
・瞑想によって,内受容感覚の正確性っが上昇するという報告も

⑤中島(2021)
・内受容感覚のまとめ

⑥寺澤・梅田(2014)
・BFにおいて,自分の身体内部の変化をどの程度分間に知覚できているかは重要
・内受容感覚の敏感さとBFについて,質問紙(IS)で測定する
*測定された客観的な身体反応と質問紙に反映される身体反応の気づきの関係性は一致せず,敏感さを評定するのに十分な方法ではないという指摘がある

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

MAIA3因子の考察

質問紙の気づきとBFの制御成績は必ずしも関連しているとは言えないのでは(http://protolab.sakura.ne.jp/LAB01/?p=31183)

・MAIAの相関が高い物が本研究でみられた。先行研究でも相関やパスで同じ
・今回用いたものでも相関がみられなかったのが,内受容感覚と関連しているのではないのでは
・質問紙の気づきとBFの制御成績は必ずしも関連しているとは言えないのでは(http://protolab.sakura.ne.jp/LAB01/?p=31183)

気づきと感情は,身体について述べている
→PAの項目多め・ニュートラルの身体状態の気づき,

不快さや痛み,
→3,4因子は不快さ,NAな身体上にフォーカスあててる

皮膚温制御は,身体はリラックスしていないとできないと,本研究で見出した

ゼミ進捗報告_2回目

報告内容
1. 修士論文の研究テーマFitbitについて
(2. FacePoseCap_予備実験の結果)

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

1. 修論の進捗報告
①参加者:「長野先生, 庵袋さん, 重田」+新規「大森・請野・高橋さん」の6人
 ・Fitbit Charge4を2台貸出中。一先ず,今月1か月間の予定。
②データ取得:Pythonプログラムを実施し,先生を除く5人分のデータを取得
 ・「getTokens.py,refreshTokens.py」で、トークン認証完了!
③研究計画書:下記のファイルが研究計画書となります。

2. FacePoseCap_予備実験の結果
①実験概要
 ・参加者:参加者3名
 ・実験刺激:動物タワーバトル(オンライン対戦ゲーム)
 ・実験スケジュール:前安静・課題・後安静を各3分ずつ
 ・生理指標:SC, 顔

②実験結果

課題期間中は、勝っても負けても何回も続けるという内容であったため、参加者によって3分間緊迫した試合を行う人もいれば、すぐに負けてしまい消化不良のまま終わってしまう人もいて力量に個人差があった。そのため、フレンド対戦モードを用いて、実験者と長くプレイするように調節する。

③顔_課題期間中の重田

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

顔データを収集したものの分析方法がわかりません。各行動データの平均値を従属変数,3期間を独立変数とした1要因分散分析の参加者内計画でしょうか。

FacePoseCap_データ取得

はじめに
 ここ最近,時間がなくブログ内にメモ書きが散らばっており,FPCもその一つである。 Fitbit研究を終えたら,こちらの研究に取り掛かるため,ゴールデンウィークを利用してデータの取得方法をまとめる。卒論生にも解説できるようにする。

準備するもの
・機材:「MSI01(PC),iPad,iPadスタンド(板),AnkerWebカメラ」
・ソフト類:「Unity2021.3.11f1,カメラ,OBS,Processing3.5.4」
・保存場所:「デスクトップ→個人フォルダ→SUGAWARA」

フォルダ内
・FPCapDualOffline240302:Processing, date内にProcessingの出力ファイル
・検出結果:?
・SimpleFaceCap:Unityで実行すると得られるデータ(CH1_~~.csv)

計測手順(正しいか微妙)
1. 機材周辺を整えたら,iPad前に参加者を座らせる(iPad画面は注視点で隠す)
2. OBSとUnityを実行し,計測スタート(ほぼ同時に実行で,OBSが最初)。
3. 実験スケジュールに基づき,計測を終えたらOBSとUnityを実行停止する
4. 「SUGAWARA→Simple~-ショトカ→CH1_実験日.csv」をデスクトップに出す
5. OBSから出力したmp4形式の動画フォルダ名をCH1と同じ日付に変更する
6. csv, mp4データをFPCap~のdateフォルダに,ドラック&ドロップ
7. Processing(FPcap~.pde)を立ち上げ,「15行目にmp4; 16,17行目にcsv」を入力
8. 上書きした後,Processingを実行する(1回目はエラーのため,2回実行する)
9. 実行画面に移行したら,(上)動画を基に(下)波形の時刻を合わせる
    (同じ秒数でもいくつかあるため,1秒であれば1秒に切り替わった瞬間に揃える)

ここからが怪しい
10. 時刻を合わせたら,F10,11からデータを出力する
11. 出力後,「FPCap~→dateフォルダ→~.B/~.R」が出力される
12. これらを展開し,折れ線グラフから解釈を行う。以上。

Processing画面でのコマンド
・Ctrl+Shift+←/→:下半分の時刻合わせ
・←/→:動画を10秒スキップ
・Ctrl+←/→:動画の最初/最後に移動
・Shift+←/→:動画をミリ単位(細かく)で移動
・space:一時停止
・F9:波形種類の変更(Smile, Browdown, Blink, Pitch, Yaw, Roll)
・F10:対象の変更(R:上半分の赤丸/青丸,B:(赤青)両方)
・F11:csv出力
・F12:動画の再生速度の変更

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

波形と動画を合わせる際,
・波形:合わせに行く
・動画:合わせてもらう

みたいな解釈だから,OBSを先に実行した方がいいかもしれない。

Copilotでプログラム開発

↓続きの続き

 今やAIあるからプログラム余裕っしょという風潮にある。しかし,ChatGPT3.5でBFプログラム開発で散々な目にあったため,有料版だけの話でしょと思ってた時期もあった…しかし,前回に引き続きCopilot君の成長が著しく高くなったため,試しにProcessingでプログラム開発してみた。

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

プログラム1:「現在時刻・経過時間を表示+任意の.mp4動画を表示」

  • Processing3.5.4の環境で,mp4形式の動画を映し,更に画面右上に現在時刻と経過時間を赤文字で表示するプログラムを書いて。文字サイズは2.5倍のサイズにして。
  • 上記プログラムで,実行後のウィンドウを拡大・縮小を調整できるように変更して。
import processing.video.*;

Movie movie;
int startTime;

void setup() {
  size(640, 360);
  surface.setResizable(true); // ウィンドウのサイズを動的に変更できるように設定
  frameRate(30);
  movie = new Movie(this, "/Users/Nn50g/Desktop/a.mp4");
  movie.loop();
  startTime = millis();
}

void draw() {
  if (movie.available()) {
    movie.read();
  }
  image(movie, 0, 0, width, height);
  
  int elapsedTime = millis() - startTime;
  String currentTime = hour() + ":" + nf(minute(), 2) + ":" + nf(second(), 2);
  String displayText = "現在時刻: " + currentTime + "\n経過時間: " + nf(elapsedTime / 60000, 2) + "分" + nf((elapsedTime / 1000) % 60, 2) + "秒";
  
  fill(255, 0, 0); // 赤色に設定
  textSize(12 * 2.5); // 文字サイズを2.5倍に設定
  textAlign(RIGHT);
  text(displayText, width - 10, 20);
}

void movieEvent(Movie m) {
  m.read();
}

できてるじゃん!ライブラリの問題もあったが,ほぼ初見で,クリアした。

プログラム2:パソコンの内カメラで取得した映像を表示

import processing.video.*;

Capture cam;

void setup() {
  size(640, 480);

  String[] cameras = Capture.list();

  if (cameras.length == 0) {
    println("カメラが見つかりませんでした。");
    exit();
  } else {
    cam = new Capture(this, cameras[0]);
    cam.start();
  }
}

void draw() {
  if (cam.available() == true) {
    cam.read();
  }
  image(cam, 0, 0);
}

プログラム3:「内カメラ+(粗)モーションキャプチャ」

import gab.opencv.*;

import gab.opencv.*;
import processing.video.*;
import java.awt.*;

Capture video;
OpenCV opencv;

void setup() {
  size(640, 480);
  video = new Capture(this, 640/2, 480/2);
  opencv = new OpenCV(this, 640/2, 480/2);
  opencv.startBackgroundSubtraction(5, 3, 0.5);

  video.start();
}

void draw() {
  scale(2);
  opencv.loadImage(video);

  image(video, 0, 0 );

  opencv.updateBackground();
  opencv.dilate();
  opencv.erode();

  noFill();
  stroke(255, 0, 0);
  strokeWeight(3);
  for (Contour contour : opencv.findContours()) {
    contour.draw();
  }
}

void captureEvent(Capture c) {
  c.read();
}

プログラム4:画像を読み取り,描くプログラム

うーん…特徴的 これは,ちゃんとしたものをGit Hubから持ってくれば書けそうだな。疑似スキャナーの役割を果たしそう。Githubリンク

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

もうなんか,こういうことができるってことを知っていれば,プログラム知識がなくてもできるじゃないですか!そして,発想力があればほぼなんでもできるな。これは,知らなかったり,偏見ある人は損だな。