「AI」カテゴリーアーカイブ

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()


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を先に実行した方がいいかもしれない。