ラベル ML の投稿を表示しています。 すべての投稿を表示
ラベル ML の投稿を表示しています。 すべての投稿を表示

2024年11月15日金曜日

Transformers.jsを使ってブラウザでWhisperによる文字起こしを実行する

Hugging FaceのTransformers.jsのページに掲載されているExamplesのひとつに、Whisperがありました。デモのサイトおよびコードもGitHubから公開されているのですが、Reactベースです。この例をそのままOracle APEXのアプリーションに組み込むというのは難しいのですが、Transformers.jsを使えばブラウザでWhisperを実行できる、というのは間違いありません。

とういうことで、Transformers.jsを使ってブラウザでWhisperを動かすOracle APEXアプリケーションを作ってみました。可能であればWebGPUも使用します。

作成したアプリケーションは以下のように動作します。長さが23秒の日本語の音声ファイルの処理に、WebGPUを使って3.6秒かかっています。


WebGPUを使わない場合は10.4秒なので、WebGPUが使えると1/3程度の処理時間になっています。WebGPUの有無や処理の短縮度合いなどは、ブラウザが動作しているPCに依存するかと思います。


作成したAPEXアプリケーションについて紹介します。

空のアプリケーションを作成し、ホーム・ページにすべての機能を実装しています。

ページ・プロパティJavaScriptファンクションおよびグローバル変数の宣言に、以下を記述しています。Whisperによる文字起こしを行なうオブジェクトtranscriberを、ページのどこからでも呼び出せるようにしています。

var transcriber;


WhisperをロードするJavaScriptのコードは、ページに静的コンテンツのリージョンを作成し、そのリージョンのソースHTMLコードに記述します。

最初にP1_USE_GPUのスイッチを確認します。スイッチがオン(つまりP1_USE_GPUの値がY)で、かつ、ブラウザでWebGPUが有効であればWebGPUを使用します。それ以外の場合は、WebGPUは使用しません。

続いてWhisperのモデルを読み込みます。ここではonnx-community/whisper-smallを決め打ちでロードしています。

画面には表示しないため、外観テンプレートなしにしています。


ページ・プロパティP1_GPUにはGPUの使用の有無P1_STATUSには、Whisperの状態を表示します。その他、P1_ELAPSED_TIMEには、文字起こしに要した時間をミリ秒単位で表示します。

ページ・アイテムP1_AUDIOで文字起こしをする音声ファイルを選択します。P1_OUTOUTに音声ファイルから起こした文字列を出力します。

ボタンTRANSCRIBEをクリックしたときに、ページ・アイテムP1_AUDIOで選択済みの音声ファイルの文字起こしを実行します。これは、以下のJavaScriptを実行する動的アクションで実装しています。



以上で実装は完了です。

今回作成したAPEXアプリケーションのエクスポートを以下に置きました。
https://github.com/ujnak/apexapps/blob/master/exports/transformers-js-whisper-webgpu.zip

Hugging Faceのモデルの説明によると(Long-Form Transcriptionの章)、処理できる音声の長さは30秒が上限のようです。そのため、長い音声の場合は30秒以下のチャンクに分割して、それぞれのチャンクごとに文字起こしをする必要がありそうです。

今回の記事は以上になります。

Oracle APEXのアプリケーション作成の参考になれば幸いです。

2024年11月13日水曜日

Learning TensorFlow.jsのChapter 5で紹介されているペットの顔を検出するアプリを作成する

O'Reillyから出版されている亀が表紙の本「Learning TensorFlow.js」のChapter 5、Introducing Modelsで紹介されている、ペットの顔を検出するアプリをOracle APEXで作成してみました。

元のアプリケーションではIMG要素にCANVAS要素を重ねて表示させ、CANVAS要素に矩形を表示させています。同じ仕組みで矩形を表示させるとコードがほとんど同じになります。今回は少しコードを変更し、選択した画像をCANVAS要素に描画し、そのCANVAS要素を解析した上で、矩形の描画もCANVAS要素に直接行なうようしています。

今回作成したAPEXアプリケーションは以下のように動作します。


ホーム・ページにすべての機能を実装しています。

ページ・プロパティJavaScriptファイルURLに以下を記述しています。

https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@4.22.0/dist/tf.min.js

ファンクションおよびグローバル変数の宣言に以下を記述しています。

var model;

ページ・ロード時に実行に以下を記述し、Learning TensorFlow.jsのChapter 5で使用しているモデルをロードしています。
tf.ready().then(() => {
    /*
     * Learning TensorFlow.js, Grant Laborde, O'Reilly Media, Inc.
     * Chapter 5: Introducing Model
     * ISBN-13: 978-1492090793
     */
    const modelPath = "https://raw.githubusercontent.com/GantMan/learn-tfjs/refs/heads/master/chapter5/simple/simple-object-localization/model/tfjs_quant_uint8/model.json";
    
    apex.items.P1_STATUS.setValue("TensorFlow.js is Ready, Loading Model...");
    tf.loadLayersModel(modelPath, { fromTFHub: true }).then((m) => {
        model = m;
        apex.items.P1_STATUS.setValue("Model is Loaded");
    });
});

画像を表示するCANVAS要素は、静的コンテンツのリージョンのソースHTMLコードに記述します。

<canvas id="detection" class="w50p"><canvas/>


TensorFlow.jsのステータスは、タイプ表示のみのページ・アイテムP1_STATUSに表示します。


解析する画像はページ・アイテムP1_IMAGEで選択します。タイプイメージ・アップロードですが、このアプリケーションはページを送信しないため、選択した画像がサーバーに送信されることはありません。


解析する画像を選択したときに実行される動的アクションにより、選択した画像をCANVAS要素へ書き出します。

以下のJavaScriptコードを実行します。
// get image file and its URL for img src.
const imageFile = this.triggeringElement.files[0];
const imageUrl = URL.createObjectURL(imageFile);
// load image into virtual img element.
const img = new Image();
img.src = imageUrl;
// draw image to canvas.
img.onload = function() {
    const detection = document.getElementById("detection");
    const ctx = detection.getContext("2d");
    // Clear Canvas
    ctx.clearRect(0, 0, detection.width, detection.height);
    // set new height then draw
    detection.height = Math.ceil(img.height * ( detection.width / img.width ));
    ctx.drawImage(this, 0, 0, detection.width, detection.height);
    // Reset Status
    apex.items.P1_STATUS.setValue("Ready for Detection");
}

顔の検出はボタンDETECTを押した時に実行される動的アクションで処理します。

ボタンDETECTを押した時に、以下のJavaScriptコードを実行します。
tf.tidy(() => {
    const detection = document.getElementById("detection");
    const myTensor = tf.browser.fromPixels(detection);
    // Model expects 256x256 0-1 value 3D tensor
    const readyfied = tf.image
        .resizeNearestNeighbor(myTensor, [256,256], true)
        .div(255)
        .reshape([1,256,256,3]);
    apex.items.P1_STATUS.setValue("Start prediction !");
    // predict.
    const result = model.predict(readyfied);
    result.print();
    apex.items.P1_STATUS.setValue("Prediction Done !");
    // Draw box on canvas
    const box = result.dataSync();
    const startX = box[0] * detection.width;
    const startY = box[1] * detection.height;
    const width = (box[2] - box[0]) * detection.width;
    const height = (box[3] - box[1]) * detection.height;
    const ctx = detection.getContext("2d");
    ctx.strokeStyle = "#0F0";
    ctx.lineWidth = 4;
    ctx.strokeRect(startX, startY, width, height);
});

以上でアプリケーションは完成です。アプリケーションを実行すると、記事の先頭のGIF動画のように動作します。

今回作成したAPEXアプリケーションのエクスポートを以下に置きました。
https://github.com/ujnak/apexapps/blob/master/exports/tensorflow-js-feature-extraction2.zip

Oracle APEXのアプリケーション作成の参考になれば幸いです。

Hugging Face Transformers.jsのObject detectionをOracle APEXで実装してみる

Hugging FaceのTransformers.jsのExamplesに含まれているIn-browser object detectionを、Oracle APEXのアプリケーションとして実装してみます。この例の名前がVanilla JavaScriptであることから分かるように、APEXに組み込みやすいサンプルになっています。GitHubのリポジトリへのリンクはこちらです。

作成したアプリケーションは以下のように動作します。

タヌキはdog、シマウマはzebraとして認識されました。


空のAPEXアプリケーションを作成し、ホーム・ページに機能を実装しています。

ホーム・ページのページ・プロパティCSSインラインに、以下を記述します。サンプルに含まれているstyle.cssの定義を、ほぼそのまま貼り付けています。



解析する画像を選択するページ・アイテムとしてP1_IMAGEを作成しています。タイプイメージ・アップロードです。


ページ・アイテムP1_STATUSに設定した文字列をステータスとして表示します。タイプ表示のみです。


画像を表示する要素およびオブジェクトを検出するJavaScriptコードは、すべて静的コンテンツのリージョンに記述します。サンプルに含まれているindex.jsのコードを、ほぼそのまま貼り付けています。今回はimportmapの定義を省略しています。


以上でObject detectorのアプリケーションは完成です。

今回作成したAPEXアプリケーションのエクスポートを以下に置きました。
https://github.com/ujnak/apexapps/blob/master/exports/transformers-js-object-detector.zip

Oracle APEXのアプリケーション作成の参考になれば幸いです。