Merge branch 'main' into bawah
29
app.py
|
|
@ -13,7 +13,7 @@ from dotenv import load_dotenv
|
||||||
load_dotenv()
|
load_dotenv()
|
||||||
|
|
||||||
from utils.helpers import load_model, estimate_prediction_confidence
|
from utils.helpers import load_model, estimate_prediction_confidence
|
||||||
from utils.preprocessing import preprocess_image, preprocess_pipeline, validate_cattle_image
|
from utils.preprocessing import preprocess_image, preprocess_pipeline, validate_cattle_image, detect_udder
|
||||||
from utils.feature_extraction import FeatureExtractor
|
from utils.feature_extraction import FeatureExtractor
|
||||||
from expert_system import ForwardChaining, KnowledgeBase # Import sistem pakar
|
from expert_system import ForwardChaining, KnowledgeBase # Import sistem pakar
|
||||||
|
|
||||||
|
|
@ -422,6 +422,20 @@ def _predict_single(filepath, original_filename):
|
||||||
multi_enc = multiclass_model.predict(multi_scaled)[0]
|
multi_enc = multiclass_model.predict(multi_scaled)[0]
|
||||||
pmk_type = multiclass_label_encoder.inverse_transform([multi_enc])[0]
|
pmk_type = multiclass_label_encoder.inverse_transform([multi_enc])[0]
|
||||||
|
|
||||||
|
# Fallback heuristic: jika model menandai 'sehat' tapi gambar mengandung ciri ambing/puting,
|
||||||
|
# anggap sebagai laktasi (pmk_laktasi) dan ubah prediksi agar sistem pakar terpicu.
|
||||||
|
if prediction.lower() == 'sehat':
|
||||||
|
try:
|
||||||
|
udder_detected, udder_score = detect_udder(filepath)
|
||||||
|
if udder_detected:
|
||||||
|
prediction = 'sakit'
|
||||||
|
pmk_type = 'pmk_laktasi'
|
||||||
|
# update confidence minimal berdasarkan score heuristik
|
||||||
|
confidence = max(confidence, min(udder_score * 100.0, 95.0))
|
||||||
|
print(f"[HEURISTIC] Udder heuristic triggered for {original_filename} | score={udder_score:.2f}")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"[HEURISTIC] Udder heuristic error: {e}")
|
||||||
|
|
||||||
features_dict = {name: float(features[i]) for i, name in enumerate(extractor.feature_names)}
|
features_dict = {name: float(features[i]) for i, name in enumerate(extractor.feature_names)}
|
||||||
features_table = list(zip(extractor.feature_names, [round(float(x), 4) for x in features]))
|
features_table = list(zip(extractor.feature_names, [round(float(x), 4) for x in features]))
|
||||||
|
|
||||||
|
|
@ -584,6 +598,10 @@ def predict():
|
||||||
pmk_to_symptoms = {
|
pmk_to_symptoms = {
|
||||||
'pmk_oral': ['G02', 'G03', 'G04', 'G10', 'G14', 'G18', 'G19', 'G20', 'G21'],
|
'pmk_oral': ['G02', 'G03', 'G04', 'G10', 'G14', 'G18', 'G19', 'G20', 'G21'],
|
||||||
'pmk_podal': ['G05', 'G06', 'G15', 'G22', 'G23', 'G24'],
|
'pmk_podal': ['G05', 'G06', 'G15', 'G22', 'G23', 'G24'],
|
||||||
|
# Udder (laktasi) — gunakan hanya gejala spesifik ambing/puting
|
||||||
|
'pmk_laktasi': ['G07', 'G08', 'G09', 'G26', 'G27'],
|
||||||
|
# General akut: kombinasi gejala yang menunjukkan PMK akut/menular luas
|
||||||
|
'pmk_akut_general': ['G01', 'G02', 'G03', 'G04', 'G05', 'G06', 'G07', 'G09', 'G11', 'G12', 'G14', 'G18', 'G20', 'G22', 'G23', 'G24', 'G26']
|
||||||
}
|
}
|
||||||
|
|
||||||
preselected = set()
|
preselected = set()
|
||||||
|
|
@ -592,6 +610,15 @@ def predict():
|
||||||
if key in pmk_to_symptoms:
|
if key in pmk_to_symptoms:
|
||||||
preselected.update(pmk_to_symptoms[key])
|
preselected.update(pmk_to_symptoms[key])
|
||||||
|
|
||||||
|
# Jika lebih dari satu body-part berbeda terdeteksi sakit (misal: mulut+kaki, mulut+puting, kaki+puting),
|
||||||
|
# anggap kemungkinan PMK akut/general dan preselect gejala umum akut juga.
|
||||||
|
body_part_keys = {k for k in sick_pmk_types if k in {'pmk_oral', 'pmk_podal', 'pmk_laktasi'}}
|
||||||
|
if len(body_part_keys) >= 2:
|
||||||
|
# tambahkan gejala PMK akut general
|
||||||
|
preselected.update(pmk_to_symptoms.get('pmk_akut_general', []))
|
||||||
|
# juga tambahkan tipe pmk_akut_general ke hasil sehingga UI/riwayat menampilkan tipe ini
|
||||||
|
sick_pmk_types.add('pmk_akut_general')
|
||||||
|
|
||||||
# Store all images in session for expert system display
|
# Store all images in session for expert system display
|
||||||
session['last_prediction'] = {
|
session['last_prediction'] = {
|
||||||
'db_id': pred_id,
|
'db_id': pred_id,
|
||||||
|
|
|
||||||
|
Before Width: | Height: | Size: 105 KiB After Width: | Height: | Size: 105 KiB |
|
Before Width: | Height: | Size: 382 KiB After Width: | Height: | Size: 382 KiB |
|
Before Width: | Height: | Size: 498 KiB After Width: | Height: | Size: 498 KiB |
|
Before Width: | Height: | Size: 390 KiB After Width: | Height: | Size: 390 KiB |
|
Before Width: | Height: | Size: 282 KiB After Width: | Height: | Size: 282 KiB |
|
Before Width: | Height: | Size: 287 KiB After Width: | Height: | Size: 287 KiB |
|
Before Width: | Height: | Size: 242 KiB After Width: | Height: | Size: 242 KiB |
|
Before Width: | Height: | Size: 340 KiB After Width: | Height: | Size: 340 KiB |
|
Before Width: | Height: | Size: 174 KiB After Width: | Height: | Size: 174 KiB |
|
Before Width: | Height: | Size: 298 KiB After Width: | Height: | Size: 298 KiB |
|
Before Width: | Height: | Size: 321 KiB After Width: | Height: | Size: 321 KiB |
|
Before Width: | Height: | Size: 418 KiB After Width: | Height: | Size: 418 KiB |
|
Before Width: | Height: | Size: 362 KiB After Width: | Height: | Size: 362 KiB |
|
Before Width: | Height: | Size: 407 KiB After Width: | Height: | Size: 407 KiB |
|
Before Width: | Height: | Size: 98 KiB After Width: | Height: | Size: 98 KiB |
|
Before Width: | Height: | Size: 297 KiB After Width: | Height: | Size: 297 KiB |
|
Before Width: | Height: | Size: 290 KiB After Width: | Height: | Size: 290 KiB |
|
Before Width: | Height: | Size: 39 KiB After Width: | Height: | Size: 39 KiB |
|
Before Width: | Height: | Size: 288 KiB After Width: | Height: | Size: 288 KiB |
|
Before Width: | Height: | Size: 269 KiB After Width: | Height: | Size: 269 KiB |
|
Before Width: | Height: | Size: 263 KiB After Width: | Height: | Size: 263 KiB |
|
Before Width: | Height: | Size: 397 KiB After Width: | Height: | Size: 397 KiB |
|
Before Width: | Height: | Size: 467 KiB After Width: | Height: | Size: 467 KiB |
|
Before Width: | Height: | Size: 224 KiB After Width: | Height: | Size: 224 KiB |
|
Before Width: | Height: | Size: 642 KiB After Width: | Height: | Size: 642 KiB |
|
Before Width: | Height: | Size: 325 KiB After Width: | Height: | Size: 325 KiB |
|
Before Width: | Height: | Size: 271 KiB After Width: | Height: | Size: 271 KiB |
|
Before Width: | Height: | Size: 345 KiB After Width: | Height: | Size: 345 KiB |
|
Before Width: | Height: | Size: 258 KiB After Width: | Height: | Size: 258 KiB |
|
Before Width: | Height: | Size: 439 KiB After Width: | Height: | Size: 439 KiB |
|
Before Width: | Height: | Size: 293 KiB After Width: | Height: | Size: 293 KiB |
|
Before Width: | Height: | Size: 343 KiB After Width: | Height: | Size: 343 KiB |
|
Before Width: | Height: | Size: 388 KiB After Width: | Height: | Size: 388 KiB |
|
Before Width: | Height: | Size: 314 KiB After Width: | Height: | Size: 314 KiB |
|
Before Width: | Height: | Size: 265 KiB After Width: | Height: | Size: 265 KiB |
|
Before Width: | Height: | Size: 217 KiB After Width: | Height: | Size: 217 KiB |
|
Before Width: | Height: | Size: 371 KiB After Width: | Height: | Size: 371 KiB |
|
Before Width: | Height: | Size: 466 KiB After Width: | Height: | Size: 466 KiB |
|
Before Width: | Height: | Size: 273 KiB After Width: | Height: | Size: 273 KiB |
|
Before Width: | Height: | Size: 224 KiB After Width: | Height: | Size: 224 KiB |
|
Before Width: | Height: | Size: 265 KiB After Width: | Height: | Size: 265 KiB |
|
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 17 KiB |
|
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 17 KiB |
|
Before Width: | Height: | Size: 270 KiB After Width: | Height: | Size: 270 KiB |
|
Before Width: | Height: | Size: 284 KiB After Width: | Height: | Size: 284 KiB |
|
Before Width: | Height: | Size: 290 KiB After Width: | Height: | Size: 290 KiB |
|
Before Width: | Height: | Size: 274 KiB After Width: | Height: | Size: 274 KiB |
|
Before Width: | Height: | Size: 390 KiB After Width: | Height: | Size: 390 KiB |
|
Before Width: | Height: | Size: 732 KiB After Width: | Height: | Size: 732 KiB |
|
Before Width: | Height: | Size: 394 KiB After Width: | Height: | Size: 394 KiB |
|
Before Width: | Height: | Size: 230 KiB After Width: | Height: | Size: 230 KiB |
|
Before Width: | Height: | Size: 77 KiB After Width: | Height: | Size: 77 KiB |
|
Before Width: | Height: | Size: 276 KiB After Width: | Height: | Size: 276 KiB |
|
Before Width: | Height: | Size: 250 KiB After Width: | Height: | Size: 250 KiB |
|
Before Width: | Height: | Size: 440 KiB After Width: | Height: | Size: 440 KiB |
|
Before Width: | Height: | Size: 338 KiB After Width: | Height: | Size: 338 KiB |
|
Before Width: | Height: | Size: 307 KiB After Width: | Height: | Size: 307 KiB |
|
Before Width: | Height: | Size: 313 KiB After Width: | Height: | Size: 313 KiB |
|
Before Width: | Height: | Size: 312 KiB After Width: | Height: | Size: 312 KiB |
|
Before Width: | Height: | Size: 431 KiB After Width: | Height: | Size: 431 KiB |
|
Before Width: | Height: | Size: 253 KiB After Width: | Height: | Size: 253 KiB |
|
Before Width: | Height: | Size: 203 KiB After Width: | Height: | Size: 203 KiB |
|
Before Width: | Height: | Size: 384 KiB After Width: | Height: | Size: 384 KiB |
|
Before Width: | Height: | Size: 231 KiB After Width: | Height: | Size: 231 KiB |
|
Before Width: | Height: | Size: 512 KiB After Width: | Height: | Size: 512 KiB |
|
Before Width: | Height: | Size: 291 KiB After Width: | Height: | Size: 291 KiB |
|
Before Width: | Height: | Size: 428 KiB After Width: | Height: | Size: 428 KiB |
|
Before Width: | Height: | Size: 271 KiB After Width: | Height: | Size: 271 KiB |
|
Before Width: | Height: | Size: 240 KiB After Width: | Height: | Size: 240 KiB |
|
Before Width: | Height: | Size: 335 KiB After Width: | Height: | Size: 335 KiB |
|
Before Width: | Height: | Size: 161 KiB After Width: | Height: | Size: 161 KiB |
|
Before Width: | Height: | Size: 293 KiB After Width: | Height: | Size: 293 KiB |
|
Before Width: | Height: | Size: 330 KiB After Width: | Height: | Size: 330 KiB |
|
Before Width: | Height: | Size: 402 KiB After Width: | Height: | Size: 402 KiB |
|
Before Width: | Height: | Size: 371 KiB After Width: | Height: | Size: 371 KiB |
|
Before Width: | Height: | Size: 211 KiB After Width: | Height: | Size: 211 KiB |
|
Before Width: | Height: | Size: 399 KiB After Width: | Height: | Size: 399 KiB |
|
Before Width: | Height: | Size: 256 KiB After Width: | Height: | Size: 256 KiB |
|
Before Width: | Height: | Size: 298 KiB After Width: | Height: | Size: 298 KiB |
|
Before Width: | Height: | Size: 266 KiB After Width: | Height: | Size: 266 KiB |
|
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 17 KiB |
|
Before Width: | Height: | Size: 272 KiB After Width: | Height: | Size: 272 KiB |
|
Before Width: | Height: | Size: 280 KiB After Width: | Height: | Size: 280 KiB |
|
Before Width: | Height: | Size: 274 KiB After Width: | Height: | Size: 274 KiB |
|
Before Width: | Height: | Size: 392 KiB After Width: | Height: | Size: 392 KiB |
|
Before Width: | Height: | Size: 704 KiB After Width: | Height: | Size: 704 KiB |
|
Before Width: | Height: | Size: 219 KiB After Width: | Height: | Size: 219 KiB |
|
Before Width: | Height: | Size: 226 KiB After Width: | Height: | Size: 226 KiB |
|
Before Width: | Height: | Size: 209 KiB After Width: | Height: | Size: 209 KiB |
|
Before Width: | Height: | Size: 385 KiB After Width: | Height: | Size: 385 KiB |
|
Before Width: | Height: | Size: 246 KiB After Width: | Height: | Size: 246 KiB |
|
Before Width: | Height: | Size: 444 KiB After Width: | Height: | Size: 444 KiB |
|
Before Width: | Height: | Size: 298 KiB After Width: | Height: | Size: 298 KiB |
|
Before Width: | Height: | Size: 404 KiB After Width: | Height: | Size: 404 KiB |
|
Before Width: | Height: | Size: 264 KiB After Width: | Height: | Size: 264 KiB |
|
Before Width: | Height: | Size: 196 KiB After Width: | Height: | Size: 196 KiB |
|
Before Width: | Height: | Size: 354 KiB After Width: | Height: | Size: 354 KiB |
|
Before Width: | Height: | Size: 464 KiB After Width: | Height: | Size: 464 KiB |
|
Before Width: | Height: | Size: 213 KiB After Width: | Height: | Size: 213 KiB |