# Hướng dẫn sử dụng Mô hình AI trên web
## Yêu cầu:
- Cài đặt dependency: [@tensorflow/tfjs]('https://www.npmjs.com/package/@tensorflow/tfjs')
- Import method: `import * as tf from "@tensorflow/tfjs"`
## Cách sử dụng:
### Cách khởi động mô hình AI
- Folder gốc là public nên hãy đưa file mô hinh AI và folder public:
```jsx
const model = await tf.loadGraphModel('Đường dẫn đến mô hình ')
```
- Ví dụ:
```jsx=
const modelUrl = "/model.json";
const [model, setModel] = useState<tf.GraphModel<string | tf.io.IOHandler>>();
const loadModel = async (): Promise<void> => {
try {
const model = await tf.loadGraphModel(modelUrl);
setModel(model);
console.log("loaded Model");
} catch (err) {
console.log(err);
console.log("failed load model");
}
};
```
### Cách đưa hình ảnh qua mô hình AI
- Tuỳ vào mỗi mô hình AI thì bên CoTAI sẽ cung cấp các function cụ thể để xử lý hình ảnh và trả về kết quả cụ thể.
Ví dụ:
```typescript=
let input : any
// predictModel chính là function CoTAI sẽ cung cấp
let output = await predictModel(input)
```
#### Mô hình nhận diện góc xe và tem
- Hình ảnh đưa vào mô hình cần phải là canvas: `HTMLCanvasElement`
```typescript=
type ModelOutput = Float32Array | Int32Array | Uint8Array;
const prediction = async (canv: HTMLCanvasElement) => {
let boxesData: ModelOutput | undefined;
let scoresData: ModelOutput | undefined;
let classesData: ModelOutput | undefined;
let validDetectionsData: number | undefined;
if (model === undefined || model.inputs[0].shape === undefined) return;
let [modelWidth, modelHeight] = model.inputs[0].shape.slice(1, 3);
const input = tf.tidy(() => {
return tf.image
.resizeBilinear(tf.browser.fromPixels(canv), [modelWidth, modelHeight])
.div(255.0)
.expandDims(0);
});
if (input === undefined) {
console.log("didnt have input");
setTimeout(() => prediction(canv), 1);
return;
}
await model.executeAsync(input).then((res) => {
const [boxes, scores, classes, valid_detections] =
res as tf.Tensor<tf.Rank>[];
boxesData = boxes.dataSync();
scoresData = scores.dataSync();
classesData = classes.dataSync();
validDetectionsData = valid_detections.dataSync()[0];
// Set guide Text
tf.disposeVariables();
tf.dispose(res);
tf.dispose(input);
});
return {
boxesData,
scoresData,
classesData,
validDetectionsData,
};
};
```
### Cách xử lí dữ liệu đầu ra của mô hình AI
- Tuỳ vào mỗi mô hình sẽ có các đầu ra khác nhau.
#### Mô hình nhận diện góc xe và tem
- `boundingBox` là dữ liệu của bounding box của chiếc xe, gồm 4 dữ liệu `[x1, y1, x2, y2]` tượng trưng cho `[xMin, yMin, xMax, yMax]` có kiểu dữ liệu là `number[]` và trong khoảng `0-1` của chiếc xe. Xử dụng dữ liệu này so sánh. Nếu `x1 >= 0.05 && x2 <= 0.95 && y1 >= 0.05 && y2 <= 0.95` (lưu ý: giá trị này chỉ là giá trị tham khảo, CoTAI sẽ cung cấp giá trị so sánh) có nghĩa là chiếc xe nằm trong khung hình và ngược lại.
- `validDetectionsData` là số lượng xe nhận diện được, có kiểu dữ liệu là `number`. Xử dụng hàm để xử lý trường hợp nhận diện được nhiều hơn 1 xe và không nhận diện được xe. Nếu nhận diện được 1 chiếc xe thì hiện bảng hướng dẫn.
- `classesData` là dữ liệu đại diện cho ID của Label có độ tự tin cao nhất, có kiểu dữ liệu là `number[]`. Vì điều kiện chỉ nhận một chiếc xe nên ta sẽ lấy giá trị đầu tiên trong danh sách `classesData[0]`
- `scoresData` là dữ liệu đại diện cho độ tự tin cao nhất, có kiểu dữ liệu là `number[]`. Vì điều kiện chỉ nhận một chiếc xe nên ta sẽ lấy giá trị đầu tiên trong danh sách `scoresData[0]`
```jsx=
let imageClass: string = "";
const boundingBox: number[] = Array.prototype.slice.call(boxesData?.slice(0, 4));
let [x1, y1, x2, y2] = boundingBox;
if (validDetectionsData === 0) {
imageClass = "Không nhận diện được xe";
} else if (validDetectionsData === 0) {
imageClass = "Có nhiều hơn một xe trong khung hình";
} else if (x1 >= 0.05 && x2 <= 0.95 && y1 >= 0.05 && y2 <= 0.95) {
const klass = modelLabels[classesData[0]];
const score = scoresData[0].toFixed(2);
imageClass = `${klass}: ${score}`;
} else {
imageClass = `Xe không nằm trong khung hình, ${x1} , ${x2}, ${x2}, ${y2}`;
}
```
***Label***
```jsx=
const modelLabels = [
"back",
"backLeft",
"backRight",
"front",
"frontLeft",
"frontRight",
"left",
"right",
"stamp",
];
```