Randi-Palguna commited on
Commit
3bab7f4
·
1 Parent(s): 11672f5

style: change language to Indonesian

Browse files
Files changed (1) hide show
  1. src/streamlit_app.py +51 -58
src/streamlit_app.py CHANGED
@@ -4,33 +4,37 @@ from PIL import Image
4
  import numpy as np
5
  import os
6
 
7
- # --- CONFIGURATION ---
8
  SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
9
  MODEL_PATH = os.path.join(SCRIPT_DIR, "best.pt")
10
 
11
- # --- KNOWLEDGE BASE ---
12
  SYMPTOM_QUESTIONS = {
13
  "G1": "Daun berwana putih kecoklatan memanjang seperti mengering pada bagian tepi daun?",
14
- "G2": "Pada pagi hari, ditemukan cairan bakteri (seperti butiran air) pada bagian terinfeksi?",
15
- "G3": "Luka terlihat seperti anak panah di antara urat daun?",
16
- "G4": "Luka berwarna kuning kecoklatan?",
17
- "G5": "Pada daun terlihat transparan bila dihadapkan cahaya matahari?",
18
- "G6": "Bercak berbentuk belah ketupat (Diamond shape)?",
19
- "G7": "Bagian tengah bercak abu-abu/putih, tepi berwarna kecoklatan?",
20
  "G8": "Infeksi pada malai/leher berwarna abu-abu?",
21
- "G13": "Tanaman kerdil dan daun berubah warna (hijau -> jingga/kemerahan)?",
22
- "G025": "Daun menguning, menggulung, mengering dan menjadi layu?",
23
- "G026": "Bibit menjadi layu (kresek) tapi sulit dicabut?",
24
- "G027": "Warna luka bercak jingga kekuningan dari ujung ke pangkal?",
25
- "G028": "Ada bulatan kecil berwarna kuning pada pelepah daun?"
 
 
 
 
 
 
26
  }
27
 
28
  YOLO_PROMPTS = {
29
- "bacterial_leaf_blight": ["G1", "G2"],
30
- "bacterial_leaf_streak": ["G3", "G4", "G5"],
31
  "blast": ["G6", "G7", "G8"],
32
- "tungro": ["G13"],
33
- "brown_spot": [],
34
  "downy_mildew": [],
35
  "dead_heart": [],
36
  "hispa": [],
@@ -38,15 +42,17 @@ YOLO_PROMPTS = {
38
  }
39
 
40
  PRODUCTION_RULES = [
41
- {"disease": "Bacterial Leaf Blight (Hawar Daun Bakteri)", "symptoms": ["G1", "G2"], "source": "Literatur 1"},
42
- {"disease": "Bacterial Leaf Streak (Bakteri Daun Bergaris)", "symptoms": ["G3", "G4", "G5"], "source": "Literatur 1"},
43
- {"disease": "Blast (Blas)", "symptoms": ["G6", "G7"], "source": "Literatur 1"},
44
- {"disease": "Neck Blast (Blas Leher)", "symptoms": ["G8"], "source": "Literatur 1"},
45
- {"disease": "Tungro", "symptoms": ["G13"], "source": "Literatur 1"},
46
- {"disease": "Bacterial Leaf Blight (Alt. Definition)", "symptoms": ["G025", "G026", "G027", "G028"], "source": "Literatur 2"}
 
 
 
47
  ]
48
 
49
- # --- MODEL LOADING (Cached so it doesn't reload every click) ---
50
  @st.cache_resource
51
  def load_model():
52
  try:
@@ -57,14 +63,12 @@ def load_model():
57
 
58
  model = load_model()
59
 
60
- # --- APP LAYOUT ---
61
- st.title("🌾 Rice Doctor: Hybrid AI System")
62
  st.markdown("""
63
- 1. **AI Inference**: Detects disease from image.
64
- 2. **Expert System**: Verifies diagnosis using Forward Chaining logic.
65
  """)
66
 
67
- # Initialize Session State to keep data across re-runs
68
  if 'prediction' not in st.session_state:
69
  st.session_state['prediction'] = None
70
  if 'priority_codes' not in st.session_state:
@@ -72,77 +76,66 @@ if 'priority_codes' not in st.session_state:
72
  if 'analyzed' not in st.session_state:
73
  st.session_state['analyzed'] = False
74
 
75
- # --- STEP 1: UPLOAD AND ANALYZE ---
76
- uploaded_file = st.file_uploader("Step 1: Upload Leaf Image", type=["jpg", "png", "jpeg"])
77
 
78
  if uploaded_file is not None:
79
- # Display image
80
  image = Image.open(uploaded_file)
81
- st.image(image, caption="Uploaded Image", use_container_width=True)
82
 
83
- if st.button("Analyze & Generate Questions", type="primary"):
84
  if model:
85
- with st.spinner("Analyzing..."):
86
- # Run Inference
87
  results = model.predict(image, imgsz=640)
88
  raw_name = results[0].names[results[0].probs.top1]
89
  top_class_name = raw_name.lower().strip()
90
 
91
- # Save to session state
92
  st.session_state['prediction'] = top_class_name
93
  st.session_state['priority_codes'] = YOLO_PROMPTS.get(top_class_name, [])
94
  st.session_state['analyzed'] = True
95
 
96
- # Force rerun to show step 2
97
  st.rerun()
98
 
99
- # --- STEP 2: DYNAMIC QUESTIONS ---
100
  if st.session_state['analyzed']:
101
  st.divider()
102
- st.subheader("Step 2: Symptom Verification")
103
 
104
  pred = st.session_state['prediction']
105
  codes = st.session_state['priority_codes']
106
 
107
- st.info(f"🔍 **AI Prediction:** `{pred}`")
108
 
109
  if not codes:
110
- st.warning("⚠️ No specific verification questions defined for this disease. Please check the **Full Knowledge Base** below.")
111
  else:
112
- st.write("Please verify this diagnosis by answering the specific symptoms below:")
113
 
114
- # Dynamic Yes/No Questions
115
  user_answers = {}
116
  for code in codes:
117
  question = SYMPTOM_QUESTIONS.get(code, "Unknown")
118
- # Unique key is important in Streamlit
119
  ans = st.radio(
120
  f"**({code})** {question}",
121
- options=["No", "Yes"],
122
- index=0, # Default to No
123
  key=f"q_{code}"
124
  )
125
- if ans == "Yes":
126
  user_answers[code] = True
127
 
128
  st.divider()
129
- st.markdown("**Are there other symptoms?** (If the AI missed something, check it here)")
130
 
131
- # Full Checklist
132
  all_symptoms_list = [f"{k}: {v}" for k,v in SYMPTOM_QUESTIONS.items()]
133
- other_checks = st.multiselect("Full Knowledge Base", all_symptoms_list)
134
 
135
- # Process "Other" inputs
136
  for item in other_checks:
137
  code = item.split(":")[0].strip()
138
  user_answers[code] = True
139
 
140
- # --- STEP 3: FORWARD CHAINING ---
141
- if st.button("Step 3: Run Forward Chaining", type="primary"):
142
  user_facts = set(user_answers.keys())
143
 
144
  if not user_facts:
145
- st.error("⚠️ **Inconclusive:** You selected 'No' for everything.")
146
  else:
147
  matches = []
148
  for rule in PRODUCTION_RULES:
@@ -151,7 +144,7 @@ if st.session_state['analyzed']:
151
  matches.append(rule)
152
 
153
  if matches:
154
- st.success("**Disease Confirmed!**")
155
  for m in matches:
156
  st.markdown(f"""
157
  ### {m['disease']}
@@ -159,5 +152,5 @@ if st.session_state['analyzed']:
159
  - **Logic:** Found all required symptoms {m['symptoms']}
160
  """)
161
  else:
162
- st.error("**No Exact Match Found**")
163
- st.write("The symptoms you selected do not perfectly fit any strict rule in the knowledge base.")
 
4
  import numpy as np
5
  import os
6
 
 
7
  SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
8
  MODEL_PATH = os.path.join(SCRIPT_DIR, "best.pt")
9
 
 
10
  SYMPTOM_QUESTIONS = {
11
  "G1": "Daun berwana putih kecoklatan memanjang seperti mengering pada bagian tepi daun?",
12
+ "G2": "Pada pagi hari, dapat ditemukan cairan bakteri terlihat seperti butiran air pada bagian terinfeksi",
13
+ "G3": "Gejala terlihat seperti anak panah terdapat di antara urat daun?",
14
+ "G4": "Daun Berwarna kuning kecoklatan?",
15
+ "G5": "Luka pada daun terlihat transparan bila dihadapkan cahaya matahari?",
16
+ "G6": "Daun berbentuk belah ketupat?",
17
+ "G7": "Pada daun bagian tengah berwarna abu-abu atau berwarna putih dengan bagian tepi berwarna kecoklatan?",
18
  "G8": "Infeksi pada malai/leher berwarna abu-abu?",
19
+ "G9": "Tanaman kerdil dan Gejala pada daun terjadi perubahan warna dari hijau menjadi jingga atau kemerahan?",
20
+ "G10": "Daun menguning, menggulung, mengering dan menjadi layu?",
21
+ "G11": "Bibit menjadi layu (kresek) tapi sulit dicabut?",
22
+ "G12": "Warna luka bercak menjadi jingga kekuningan dari ujung daun ke pangkal daun?",
23
+ "G13": "Ada bulatan kecil berwarna kuning pada pelepah daun?",
24
+ "G14": "Bercak cokelat pada daun, pelepah, dan bulir gabah?",
25
+ "G15": "Bercak daun sering menutupi permukaan daun, menyebabkan daun menjadi layu?",
26
+ "G16": "Bercak cokelat pada batang/leher malai?",
27
+ "G17": "Terdapat bercak berbentuk oval berwarna abu-abu kehijauan pada pelepah (tulang daun)?",
28
+ "G18": "Batang tanaman padi menjadi rapuh dan mudah rebah/jatuh?",
29
+ "G19": "Bibit yang sakit menjadi layu dan akhirnya mati?"
30
  }
31
 
32
  YOLO_PROMPTS = {
33
+ "bacterial_leaf_blight": ["G1", "G2", "G3"],
34
+ "bacterial_leaf_streak": ["G4", "G5"],
35
  "blast": ["G6", "G7", "G8"],
36
+ "tungro": ["G9"],
37
+ "brown_spot": ["G14", "G15", "G16"],
38
  "downy_mildew": [],
39
  "dead_heart": [],
40
  "hispa": [],
 
42
  }
43
 
44
  PRODUCTION_RULES = [
45
+ {"disease": "Bacterial Leaf Blight (Hawar Daun Bakteri)", "symptoms": ["G1", "G2", "G3"], "source": "Literatur 1"},
46
+ {"disease": "Bakteri Daun Bergaris (Bacterial Leaf Streak)", "symptoms": ["G4", "G5"], "source": "Literatur 1"},
47
+ {"disease": "Blas (Blast)", "symptoms": ["G6", "G7", "G8"], "source": "Literatur 1"},
48
+ {"disease": "Tungro", "symptoms": ["G9"], "source": "Literatur 1"},
49
+
50
+ {"disease": "Hawar Daun Bakteri (Bacterial Leaf Blight)", "symptoms": ["G10", "G11", "G12", "G13"], "source": "Literatur 2"},
51
+
52
+ {"disease": "Bercak Daun Coklat (Brown Spot)", "symptoms": ["G14", "G15", "G16"], "source": "Literatur 3"},
53
+ {"disease": "Hawar Pelepah (Sheath Blight)", "symptoms": ["G17", "G18", "G19"], "source": "Literatur 3"},
54
  ]
55
 
 
56
  @st.cache_resource
57
  def load_model():
58
  try:
 
63
 
64
  model = load_model()
65
 
66
+ st.title("🌾 Rice Doctor: Sistem Pakar Penyakit Padi")
 
67
  st.markdown("""
68
+ 1. **Inferensi AI**: Mendeteksi penyakit dari gambar.
69
+ 2. **Sistem Pakar**: Memverifikasi diagnosis menggunakan logika Forward Chaining.
70
  """)
71
 
 
72
  if 'prediction' not in st.session_state:
73
  st.session_state['prediction'] = None
74
  if 'priority_codes' not in st.session_state:
 
76
  if 'analyzed' not in st.session_state:
77
  st.session_state['analyzed'] = False
78
 
79
+ uploaded_file = st.file_uploader("Langkah 1: Unggah Gambar Daun", type=["jpg", "png", "jpeg"])
 
80
 
81
  if uploaded_file is not None:
 
82
  image = Image.open(uploaded_file)
83
+ st.image(image, caption="Gambar yang Diunggah", use_container_width=True)
84
 
85
+ if st.button("Analisis Penyakit", type="primary"):
86
  if model:
87
+ with st.spinner("Menganalisis..."):
 
88
  results = model.predict(image, imgsz=640)
89
  raw_name = results[0].names[results[0].probs.top1]
90
  top_class_name = raw_name.lower().strip()
91
 
 
92
  st.session_state['prediction'] = top_class_name
93
  st.session_state['priority_codes'] = YOLO_PROMPTS.get(top_class_name, [])
94
  st.session_state['analyzed'] = True
95
 
 
96
  st.rerun()
97
 
 
98
  if st.session_state['analyzed']:
99
  st.divider()
100
+ st.subheader("Langkah 2: Verifikasi Gejala")
101
 
102
  pred = st.session_state['prediction']
103
  codes = st.session_state['priority_codes']
104
 
105
+ st.info(f"🔍 **Prediksi AI:** `{pred}`")
106
 
107
  if not codes:
108
+ st.warning("Tidak ada pertanyaan verifikasi khusus untuk penyakit ini. Silakan periksa **Basis Pengetahuan Lengkap** di bawah ini.")
109
  else:
110
+ st.write("Silakan verifikasi diagnosis ini dengan menjawab gejala spesifik di bawah ini:")
111
 
 
112
  user_answers = {}
113
  for code in codes:
114
  question = SYMPTOM_QUESTIONS.get(code, "Unknown")
 
115
  ans = st.radio(
116
  f"**({code})** {question}",
117
+ options=["Tidak", "Ya"],
118
+ index=0,
119
  key=f"q_{code}"
120
  )
121
+ if ans == "Ya":
122
  user_answers[code] = True
123
 
124
  st.divider()
125
+ st.markdown("**Apakah ada gejala lain?**")
126
 
 
127
  all_symptoms_list = [f"{k}: {v}" for k,v in SYMPTOM_QUESTIONS.items()]
128
+ other_checks = st.multiselect("Basis Pengetahuan Lengkap", all_symptoms_list)
129
 
 
130
  for item in other_checks:
131
  code = item.split(":")[0].strip()
132
  user_answers[code] = True
133
 
134
+ if st.button("Langkah 3: Jalankan Forward Chaining", type="primary"):
 
135
  user_facts = set(user_answers.keys())
136
 
137
  if not user_facts:
138
+ st.error("**Tidak Meyakinkan:** Anda memilih 'Tidak' untuk semuanya.")
139
  else:
140
  matches = []
141
  for rule in PRODUCTION_RULES:
 
144
  matches.append(rule)
145
 
146
  if matches:
147
+ st.success("**Penyakit Terkonfirmasi!**")
148
  for m in matches:
149
  st.markdown(f"""
150
  ### {m['disease']}
 
152
  - **Logic:** Found all required symptoms {m['symptoms']}
153
  """)
154
  else:
155
+ st.error("**Tidak Ditemukan Kecocokan Pasti**")
156
+ st.write("Gejala yang Anda pilih tidak sepenuhnya sesuai dengan aturan ketat mana pun dalam basis pengetahuan.")