# 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", ]; ```