Integrasi Model Klasifikasi Gambar (Gunting Batu Kertas)
Kita akan membuat API untuk model Paper Rock Scrissors
Pendahuluan
Kita akan melanjutkan aplikasi flask-diabetes yang telah kamu buat sebelumnya. Fokus kita hari ini adalah menambahkan kemampuan Machine Learning untuk pengolahan citra (gambar).
Secara sederhana, kita akan mengimplementasikan fitur yang mampu mengenali foto tangan dan mengklasifikasikannya menjadi simbol "Gunting", "Batu", atau "Kertas".
Prasyarat:
- Project
flask-diabetesdari pertemuan sebelumnya. - File model
RPS.kerasyang sudah dilatih (tersedia di Materi ini).
Langkah 1: Persiapan Model dan Virtual Environment
Pastikan semua aset dan library sudah disiapkan.
1.1 Folder Model
Download file model dengan ekstensi .keras. Pindahkan file tersebut ke dalam folder models/ di dalam struktur direktori project kamu agar rapi dan mudah diakses.
1.2 Instalasi Dependensi
Kita memerlukan library keras dan tensorflow untuk memuat dan menjalankan model Deep Learning tersebut. Silakan jalankan perintah berikut di terminal kamu:
uv add keras==3.10.0
uv add tensorflow==2.20.0Catatan: Jika kamu mengalami kendala instalasi dengan tensorflow versi 2.20.0, kamu dapat mencoba versi 2.19.0 sebagai alternatif agar sama dengan versi yang digunakan oleh google colab.
Langkah 2: Import Library
Buka file main.py. Kita perlu memanggil fungsi-fungsi dari TensorFlow untuk memproses gambar sebelum gambar tersebut dapat dibaca oleh model.
Tambahkan kode berikut di bagian atas file, bergabung dengan import lainnya:
import joblib
import pandas as pd
import tensorflow as tf
import numpy as np
import io
from flask_cors import CORS
from flask import Flask, jsonify, request
from tensorflow.keras.preprocessing import image
from tensorflow.keras.applications.mobilenet_v3 import preprocess_inputPenjelasan Kode:
from tensorflow.keras.preprocessing import image: Modul ini menyediakan alat bantu untuk memuat gambar dari file dan mengubahnya menjadi format array (susunan angka) yang bisa dipahami komputer.from tensorflow.keras.applications.mobilenet_v3 import preprocess_input: Ini adalah fungsi khusus untuk menormalisasi data gambar agar sesuai dengan standar format model MobileNetV3 yang kita gunakan.
Langkah 3: Memuat Model dan Definisi Kelas
Masih di dalam main.py, kita akan memuat model ke dalam memori aplikasi. Tujuannya agar model siap digunakan kapan saja tanpa perlu dimuat ulang setiap kali ada permintaan (request) dari pengguna, yang akan memperlambat aplikasi.
Tambahkan kode ini di bawah inisialisasi aplikasi Flask atau di tempat kamu memuat model diabetes sebelumnya:
# Memuat model yang telah dilatih
loaded_model = joblib.load("models/model_diabetes.pkl")
loaded_model_rps = tf.keras.models.load_model("models/RPS.keras")
columns = [
'Pregnancies',
'Glucose',
'BloodPressure',
'SkinThickness',
'Insulin',
'BMI',
'DiabetesPedigreeFunction',
'Age'
]
# Mendefinisikan label kelas (Wajib berurutan sesuai saat training)
rps_class_names = ['Paper', 'Rock', 'Scissors']Penjelasan Kode:
tf.keras.models.load_model(...): Fungsi ini membaca struktur dan bobot (weights) dari file.keraslalu merekonstruksinya menjadi objek model Python yang siap melakukan prediksi.rps_class_names: Model Deep Learning biasanya hanya mengembalikan hasil berupa angka indeks (misalnya 0, 1, atau 2). List ini berfungsi menerjemahkan angka tersebut menjadi label teks. Penting: Urutannya harus sama persis dengan urutan saat model dilatih (0='Paper', 1='Rock', 2='Scissors').
Langkah 4: Membuat Endpoint Prediksi
Sekarang kita masuk ke pembuatan endpoint. Kita akan membuat rute (route) API baru yang bertugas menerima file gambar dari pengguna, memprosesnya, meminta model melakukan prediksi, dan mengembalikan hasilnya dalam format JSON.
Tambahkan fungsi berikut di bagian bawah file main.py:
@app.route("/api/predict", methods=["POST"])
def predict():
# Code prediksi diabetes (sebelumnya)
@app.route("/api/predict-rps", methods=["POST"])
def predict_rps():
# 1. Validasi request file
if 'file' not in request.files:
return jsonify({
"meta": {
"status": 400,
"message": "No file in the request"
}
})
# 2. Membaca File Gambar
file = request.files['file']
img_bytes = io.BytesIO(file.read())
# 3. Preprocessing Gambar
img = image.load_img(img_bytes, target_size=(150, 150))
img_array = image.img_to_array(img)
img_array = preprocess_input(img_array)
img_batch = np.expand_dims(img_array, axis=0)
# 4. Proses Prediksi (Inferensi)
prediction = loaded_model_rps.predict(img_batch)
predicted_class_index = np.argmax(prediction)
# 5. Mengembalikan Respons
return jsonify({
"meta": {
"status": 200,
"message": "Prediction successful"
},
"data": {
"prediction": rps_class_names[predicted_class_index],
"probability": f"{np.max(prediction) * 100:.2f}%"
}
})Penjelasan Detail Langkah demi Langkah:
Bagian 1: Validasi
Kita memeriksa apakah pengirim benar-benar menyertakan data dengan nama kunci file. Jika tidak, server akan merespons dengan status 400 Bad Request untuk mencegah error pada proses selanjutnya.
Bagian 2: Membaca File
file.read(): Membaca isi file yang diunggah.io.BytesIO(...): Kita menyimpan file tersebut sementara di memori RAM sebagai aliran byte, bukan menyimpannya ke harddisk server. Ini membuat proses lebih cepat dan efisien.
Bagian 3: Preprocessing (Sangat Penting) Agar model bisa bekerja, gambar input harus disesuaikan dengan format saat model tersebut dilatih:
- Resize:
target_size=(150, 150)mengubah ukuran gambar menjadi 150x150 piksel secara otomatis. - To Array: Mengubah gambar visual menjadi matriks angka.
- Preprocess Input: Menyesuaikan rentang nilai piksel agar sesuai dengan standar MobileNetV3.
- Expand Dims: Menambahkan satu dimensi ekstra karena TensorFlow mengharapkan input dalam bentuk tumpukan (batch), meskipun kita hanya memprediksi satu gambar. Dimensi berubah dari
(150, 150, 3)menjadi(1, 150, 150, 3).
Bagian 4: Prediksi
predict(img_batch): Model menghitung probabilitas untuk setiap kemungkinan kelas. Hasilnya berupa array, contoh:[0.1, 0.8, 0.1].np.argmax(...): Fungsi ini mencari posisi (indeks) yang memiliki nilai probabilitas tertinggi. Dari contoh di atas, nilai tertinggi ada di indeks ke-1.
Bagian 5: Response Kita menyusun hasil akhir dalam format JSON standar.
rps_class_names[...]: Mengubah indeks angka (hasilargmax) menjadi nama kelas (misal: "Rock").probability: Mengambil nilai keyakinan model dan memformatnya menjadi persentase.
Uji Coba
Silakan uji coba endpoint /api/predict-rps ini menggunakan aplikasi seperti Postman:
- Set method ke POST.
- Masuk ke tab Body lalu pilih form-data.
- Isi Key dengan
file(ubah tipe dari Text menjadi File). - Upload gambar tangan (Gunting, Batu, atau Kertas) dan kirim (Send).