元のアプリケーションでは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 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);
});
今回作成したAPEXアプリケーションのエクスポートを以下に置きました。
https://github.com/ujnak/apexapps/blob/master/exports/tensorflow-js-feature-extraction2.zip
Oracle APEXのアプリケーション作成の参考になれば幸いです。
完