作成したアプリケーションは以下のように動作します。
タヌキはdog、シマウマはzebraとして認識されました。
空のAPEXアプリケーションを作成し、ホーム・ページに機能を実装しています。
ホーム・ページのページ・プロパティのCSSのインラインに、以下を記述します。サンプルに含まれているstyle.cssの定義を、ほぼそのまま貼り付けています。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
.container { | |
margin: 40px auto; | |
width: max(50vw, 400px); | |
display: flex; | |
flex-direction: column; | |
align-items: center; | |
} | |
#image-container { | |
width: 100%; | |
margin-top: 20px; | |
position: relative; | |
} | |
#image-container>img { | |
width: 100%; | |
} | |
.bounding-box { | |
position: absolute; | |
box-sizing: border-box; | |
border-width: 2px; | |
border-style: solid; | |
} | |
.bounding-box-label { | |
color: white; | |
position: absolute; | |
font-size: 12px; | |
margin-top: -16px; | |
margin-left: -2px; | |
padding: 1px; | |
} |
解析する画像を選択するページ・アイテムとしてP1_IMAGEを作成しています。タイプはイメージ・アップロードです。
ページ・アイテムP1_STATUSに設定した文字列をステータスとして表示します。タイプは表示のみです。
画像を表示する要素およびオブジェクトを検出するJavaScriptコードは、すべて静的コンテンツのリージョンに記述します。サンプルに含まれているindex.jsのコードを、ほぼそのまま貼り付けています。今回はimportmapの定義を省略しています。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<div class="container"> | |
<div id="image-container" class="w80p"></div> | |
</div> | |
<script type="module" defer> | |
import { pipeline, env } from 'https://cdn.jsdelivr.net/npm/@xenova/transformers@2.6.0'; | |
// Since we will download the model from the Hugging Face Hub, we can skip the local model check | |
env.allowLocalModels = false; | |
// Reference the elements that we will need | |
const fileUpload = document.getElementById('P1_IMAGE'); | |
const imageContainer = document.getElementById('image-container'); | |
// Create a new object detection pipeline | |
apex.item("P1_STATUS").setValue('Loading model...'); | |
const detector = await pipeline('object-detection', 'Xenova/detr-resnet-50'); | |
apex.item("P1_STATUS").setValue('Ready'); | |
fileUpload.addEventListener('change', function (e) { | |
const file = e.target.files[0]; | |
if (!file) { | |
return; | |
} | |
const reader = new FileReader(); | |
// Set up a callback when the file is loaded | |
reader.onload = function (e2) { | |
imageContainer.innerHTML = ''; | |
const image = document.createElement('img'); | |
image.src = e2.target.result; | |
imageContainer.appendChild(image); | |
detect(image); | |
}; | |
reader.readAsDataURL(file); | |
}); | |
// Detect objects in the image | |
async function detect(img) { | |
apex.item("P1_STATUS").setValue('Analysing...'); | |
const output = await detector(img.src, { | |
threshold: 0.5, | |
percentage: true, | |
}); | |
apex.item("P1_STATUS").setValue(''); | |
output.forEach(renderBox); | |
} | |
// Render a bounding box and label on the image | |
function renderBox({ box, label }) { | |
const { xmax, xmin, ymax, ymin } = box; | |
// Generate a random color for the box | |
const color = '#' + Math.floor(Math.random() * 0xFFFFFF).toString(16).padStart(6, 0); | |
// Draw the box | |
const boxElement = document.createElement('div'); | |
boxElement.className = 'bounding-box'; | |
Object.assign(boxElement.style, { | |
borderColor: color, | |
left: 100 * xmin + '%', | |
top: 100 * ymin + '%', | |
width: 100 * (xmax - xmin) + '%', | |
height: 100 * (ymax - ymin) + '%', | |
}) | |
// Draw label | |
const labelElement = document.createElement('span'); | |
labelElement.textContent = label; | |
labelElement.className = 'bounding-box-label'; | |
labelElement.style.backgroundColor = color; | |
boxElement.appendChild(labelElement); | |
imageContainer.appendChild(boxElement); | |
} | |
</script> |
以上でObject detectorのアプリケーションは完成です。
今回作成したAPEXアプリケーションのエクスポートを以下に置きました。
https://github.com/ujnak/apexapps/blob/master/exports/transformers-js-object-detector.zip
Oracle APEXのアプリケーション作成の参考になれば幸いです。
完