Skip to content

Commit

Permalink
[Tizen/Web] Refactoring ImageClassificationOffloading example
Browse files Browse the repository at this point in the history
- Create utility module
- Functionalization of duplicated part
- Remove unused variables
- Change var variables to use let type
- Declare variables closer to where they are used

Signed-off-by: Yelin Jeong <[email protected]>
  • Loading branch information
niley7464 authored and wooksong committed Jun 12, 2024
1 parent 99c07f7 commit c2b7e9e
Show file tree
Hide file tree
Showing 3 changed files with 190 additions and 165 deletions.
3 changes: 2 additions & 1 deletion Tizen.web/ImageClassificationOffloading/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
<meta name="description" content="Tizen Image Classification SingleShot Example" />
<title>Tizen Image Classification Offloading Example</title>
<link rel="stylesheet" type="text/css" href="css/style.css" />
<script src="js/main.js"></script>
<script src="js/util.js" type="module"></script>
<script src="js/main.js" type="module"></script>
</head>
<body>
<h1 align="center" margin-bottom="50px">Image Classification</h1>
Expand Down
278 changes: 114 additions & 164 deletions Tizen.web/ImageClassificationOffloading/js/main.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* SPDX-License-Identifier: Apache-2.0-only */
/* SPDX-License-Identifier: Apache-2.0 */

/**
* @file main.js
Expand All @@ -7,56 +7,67 @@
* @author Yelin Jeong <[email protected]>
*/

var localSrc;
var remoteSrc;
var labels;
var startTime;
var ctx;
var label;
import {
getNetworkType,
getIpAddress,
GetMaxIdx,
GetImgPath,
loadLabelInfo,
} from './utils.js';

/**
* Find the index of maximum value in the given array
* @param array the score list of each class
* @returns the index of the maximum value
*/
function GetMaxIdx(array) {
if (array.length === 0) {
console.log('array length zero')
return -1;
let fHandle = null;
let tensorsData = null;
let tensorsInfo = null;

function disposeData() {
if (fHandle != null) {
fHandle.close();
}

var max = array[0];
var maxIdx = 0;
if (tensorsData != null) {
tensorsData.dispose();
}

for (var i = 0; i < array.length; ++i) {
if (array[i] > max) {
maxIdx = i;
max = array[i];
}
if (tensorsInfo != null) {
tensorsInfo.dispose();
}
return maxIdx;
}

/**
* Get the jpeg image path
* @returns image path
*/
function GetImgPath() {
const MAX_IMG_CNT = 2;
var imgsrc = GetImgPath.count++ % MAX_IMG_CNT;
imgsrc = imgsrc.toString().concat('.jpg');
return '/res/'.concat(imgsrc);
let localHandle;
let offloadingHandle;

function createPipelineDescription(isLocal, filter) {
return (
'appsrc caps=image/jpeg name=srcx_' + (isLocal ? 'local' : 'offloading') + ' ! jpegdec ! ' +
'videoconvert ! video/x-raw,format=RGB,framerate=0/1,width=224,height=224 ! tensor_converter ! ' +
'other/tensor,format=static,dimension=(string)3:224:224:1,type=uint8,framerate=0/1 ! ' + filter + ' ! ' +
'other/tensor,format=static,dimension=(string)1001:1,type=uint8,framerate=0/1 ! ' +
'tensor_sink name=sinkx_' + (isLocal ? 'local' : 'offloading')
);
}
GetImgPath.count = 0;

/**
* Load the label from the text file and return the string array
* @returns string array
* Callback function for pipeline sink listener
*/
function loadLabelInfo() {
var fHandle = tizen.filesystem.openFile('wgt-package/res/labels.txt', 'r');
var labelList = fHandle.readString();
return labelList.split('\n');
function sinkListenerCallback(sinkName, data) {
const endTime = performance.now();

const tensorsRetData = data.getTensorRawData(0);
const maxIdx = GetMaxIdx(tensorsRetData.data);

let type;
if (sinkName.endsWith('local')) {
type = 'local';
}
else {
type = 'offloading';
}

const label = document.getElementById('label_' + type);
label.innerText = labels[maxIdx];

const time = document.getElementById('time_' + type);
time.innerText = type + ' : ' + (endTime - startTime) + ' ms';
}

/**
Expand All @@ -66,109 +77,37 @@ function runLocal() {
const modelPath = 'wgt-package/res/mobilenet_v1_1.0_224_quant.tflite';
const URI_PREFIX = 'file://';
const absModelPath = tizen.filesystem.toURI(modelPath).substr(URI_PREFIX.length);
const filter = 'tensor_filter framework=tensorflow-lite model=' + absModelPath;

const pipelineDescription = 'appsrc caps=image/jpeg name=srcx_local ! jpegdec ! ' +
'videoconvert ! video/x-raw,format=RGB,framerate=0/1,width=224,height=224 ! tensor_converter ! ' +
'tensor_filter framework=tensorflow-lite model=' + absModelPath + ' ! ' +
'appsink name=sinkx_local';

const pHandle = tizen.ml.pipeline.createPipeline(pipelineDescription);
pHandle.start();

localSrc = pHandle.getSource('srcx_local');

pHandle.registerSinkListener('sinkx_local', function(sinkName, data) {
const endTime = performance.now();
const label = document.getElementById('label_local')
const tensorsRetData = data.getTensorRawData(0);
const maxIdx = GetMaxIdx(tensorsRetData.data);
label.innerText = labels[maxIdx];

const time = document.getElementById('time_local');
time.innerText = 'local : ' + (endTime - startTime) + ' ms'
});
}
const pipelineDescription = createPipelineDescription(true,filter);

let ip;
async function getNetworkType() {
return new Promise((resolve, reject) => {
tizen.systeminfo.getPropertyValue("NETWORK", function (data) {
resolve(data.networkType);
});
});
}

async function getIpAddress(networkType) {
return new Promise((resolve, reject) => {
tizen.systeminfo.getPropertyValue(
networkType + "_NETWORK",
function (property) {
resolve(property.ipAddress);
},
);
});
}

async function setIpAddress() {
try {
const networkType = await getNetworkType();
ip = await getIpAddress(networkType);
console.log(ip);
}
catch (e) {
console.error("Error getting IP address:", error);
}
localHandle = tizen.ml.pipeline.createPipeline(pipelineDescription);
localHandle.start();
localHandle.registerSinkListener('sinkx_local', sinkListenerCallback);
}

/**
* Run a pipeline that uses other device's resources
*/
async function runRemote() {
await setIpAddress();

const pipelineDescription = 'appsrc caps=image/jpeg name=srcx_remote ! jpegdec ! ' +
'videoconvert ! video/x-raw,format=RGB,framerate=0/1,width=224,height=224 ! tensor_converter ! ' +
'other/tensor,format=static,dimension=(string)3:224:224:1,type=uint8,framerate=0/1 ! ' +
'tensor_query_client host='+ ip +' port=' + document.getElementById('port').value + ' dest-host=' + document.getElementById('ip').value + ' ' +
'dest-port=' + document.getElementById('port').value + ' timeout=1000 ! ' +
'other/tensor,format=static,dimension=(string)1001:1,type=uint8,framerate=0/1 ! tensor_sink name=sinkx_remote';

const pHandle = tizen.ml.pipeline.createPipeline(pipelineDescription);
pHandle.start();

remoteSrc = pHandle.getSource('srcx_remote');

pHandle.registerSinkListener('sinkx_remote', function(sinkName, data) {
const endTime = performance.now();
const label = document.getElementById('label_offloading');
const tensorsRetData = data.getTensorRawData(0);
const maxIdx = GetMaxIdx(tensorsRetData.data);
label.innerText = labels[maxIdx];

const time = document.getElementById('time_offloading');
time.innerText = 'offloading : ' + (endTime - startTime) + ' ms'
});
}
function runOffloading() {
const filter = 'tensor_query_client host=' + ip + ' port=' + document.getElementById('port').value +
' dest-host=' + document.getElementById('ip').value +
' dest-port=' + document.getElementById('port').value +
' timeout=1000';

let fHandle = null;
let tensorsData = null;
let tensorsInfo = null;
const pipelineDescription = createPipelineDescription(false,filter);

function disposeData() {
if (fHandle != null) {
fHandle.close();
}

if (tensorsData != null) {
tensorsData.dispose();
}

if (tensorsInfo != null) {
tensorsInfo.dispose();
}
offloadingHandle = tizen.ml.pipeline.createPipeline(pipelineDescription);
offloadingHandle.start();
offloadingHandle.registerSinkListener('sinkx_offloading', sinkListenerCallback);
}

function inference(src, canvas) {
let startTime;

/**
* Run a pipeline that uses other device's resources
*/
function inference(isLocal) {
const img_path = GetImgPath();
let img = new Image();
img.src = img_path;
Expand All @@ -183,52 +122,63 @@ function inference(src, canvas) {
tensorsData = tensorsInfo.getTensorsData();
tensorsData.setTensorRawData(0, imgUInt8Array);

startTime = performance.now()
src.inputData(tensorsData);
startTime = performance.now();

if (isLocal) {
localHandle.getSource('srcx_local').inputData(tensorsData);
} else {
offloadingHandle.getSource('srcx_offloading').inputData(tensorsData);
}

const canvasName = 'canvas_' + (isLocal ? 'local' : 'offloading');
const canvas = document.getElementById(canvasName);
const ctx = canvas.getContext('2d');
ctx.drawImage(img, 0, 0);
}
ctx.drawImage(img, 0, 0);
};
}

window.onload = function() {
labels = loadLabelInfo();

const btnLocal = document.getElementById('start_local');

btnLocal.addEventListener('click', function() {
runLocal();
});

const btnOffloading = document.getElementById('start_offloading');
let ip;
let labels;

btnOffloading.addEventListener('click', function() {
runRemote();
});
window.onload = async function () {
const networkType = await getNetworkType();
ip = await getIpAddress(networkType);
labels = loadLabelInfo();

const localPage = document.getElementById('local');
document
.getElementById('start_local')
.addEventListener('click', function () {
runLocal();
});

localPage.addEventListener('click', function() {
if (localSrc) {
inference(localSrc, document.getElementById('canvas_local'));
}
});
document
.getElementById('start_offloading')
.addEventListener('click', function () {
runOffloading();
});

const offloadingPage = document.getElementById('offloading');
document
.getElementById('local')
.addEventListener('click', function () {
inference(true);
});

offloadingPage.addEventListener('click', function() {
if (remoteSrc) {
inference(remoteSrc, document.getElementById('canvas_offloading'));
}
});
document
.getElementById('offloading')
.addEventListener('click', function () {
inference(false);
});

/* add eventListener for tizenhwkey */
document.addEventListener('tizenhwkey', function(e) {
document.addEventListener('tizenhwkey', function (e) {
if (e.keyName === 'back') {
try {
console.log('Pipeline is disposed!!');
pHandle.stop();
pHandle.dispose();
localHandle.stop();
localHandle.dispose();

offloadingHandle.stop();
offloadingHandle.dispose();

disposeData();

Expand Down
Loading

0 comments on commit c2b7e9e

Please sign in to comment.