Lahmeri mohamed amine
commited on
Update app.py
Browse files
app.py
CHANGED
@@ -26,6 +26,10 @@ class GradioLettuceAnalysisPipeline:
|
|
26 |
self.growth_model_path = growth_model_path
|
27 |
self.health_classification_model_path = health_classification_model_path
|
28 |
|
|
|
|
|
|
|
|
|
29 |
# Load all models
|
30 |
self.load_models()
|
31 |
|
@@ -48,10 +52,10 @@ class GradioLettuceAnalysisPipeline:
|
|
48 |
# 3. Load health classification model
|
49 |
self.load_health_classification_model()
|
50 |
|
51 |
-
return "All models loaded successfully!"
|
52 |
|
53 |
except Exception as e:
|
54 |
-
return f"Error loading models: {e}"
|
55 |
|
56 |
def load_health_classification_model(self):
|
57 |
"""Load the health classification model (ViT)"""
|
@@ -68,9 +72,9 @@ class GradioLettuceAnalysisPipeline:
|
|
68 |
self.health_classification_model.load_state_dict(checkpoint['model_state_dict'])
|
69 |
self.health_classification_model.eval()
|
70 |
|
71 |
-
def detect_lettuce(self, image_path
|
72 |
"""Stage 1: Detect lettuce in the image"""
|
73 |
-
results = self.detection_model(image_path, conf=
|
74 |
detections = []
|
75 |
|
76 |
for result in results:
|
@@ -90,7 +94,7 @@ class GradioLettuceAnalysisPipeline:
|
|
90 |
|
91 |
return detections
|
92 |
|
93 |
-
def classify_growth_stage(self, image_path, bbox
|
94 |
"""Stage 2: Classify growth stage"""
|
95 |
try:
|
96 |
image = Image.open(image_path)
|
@@ -111,7 +115,7 @@ class GradioLettuceAnalysisPipeline:
|
|
111 |
# Run growth stage classification
|
112 |
results = self.growth_model.predict(
|
113 |
source=temp_crop_path,
|
114 |
-
conf=
|
115 |
save=False,
|
116 |
imgsz=640,
|
117 |
verbose=False
|
@@ -165,12 +169,12 @@ class GradioLettuceAnalysisPipeline:
|
|
165 |
except Exception as e:
|
166 |
return "Unknown", 0.0
|
167 |
|
168 |
-
def process_image_gradio(self, image,
|
169 |
"""
|
170 |
Process image for Gradio interface
|
171 |
"""
|
172 |
if image is None:
|
173 |
-
return None, "
|
174 |
|
175 |
try:
|
176 |
# Save uploaded image temporarily
|
@@ -182,13 +186,13 @@ class GradioLettuceAnalysisPipeline:
|
|
182 |
image = image.convert('RGB')
|
183 |
|
184 |
# Stage 1: Detect lettuce
|
185 |
-
detections = self.detect_lettuce(temp_image_path
|
186 |
|
187 |
if not detections:
|
188 |
# Clean up
|
189 |
if os.path.exists(temp_image_path):
|
190 |
os.remove(temp_image_path)
|
191 |
-
return image, "
|
192 |
|
193 |
# Process each detection
|
194 |
complete_results = []
|
@@ -210,7 +214,7 @@ class GradioLettuceAnalysisPipeline:
|
|
210 |
det_conf = detection['confidence']
|
211 |
|
212 |
# Stage 2: Growth stage
|
213 |
-
growth_stage, growth_conf = self.classify_growth_stage(temp_image_path, bbox
|
214 |
|
215 |
# Stage 3: Health status
|
216 |
health_status, health_conf = self.classify_health(image, bbox)
|
@@ -292,7 +296,7 @@ class GradioLettuceAnalysisPipeline:
|
|
292 |
if not results:
|
293 |
return "No results to display"
|
294 |
|
295 |
-
summary = f"
|
296 |
summary += f"**Summary:**\n"
|
297 |
summary += f"- Total lettuce detected: **{len(results)}**\n"
|
298 |
|
@@ -307,7 +311,7 @@ class GradioLettuceAnalysisPipeline:
|
|
307 |
summary += f"- Health statuses: {dict(health_counts)}\n\n"
|
308 |
|
309 |
# Detailed results
|
310 |
-
summary += f"**Detailed Results:**\n\n"
|
311 |
|
312 |
for result in results:
|
313 |
summary += f"**Lettuce {result['lettuce_id']}:**\n"
|
@@ -348,12 +352,12 @@ except Exception as e:
|
|
348 |
model_status = f"Error loading models: {e}"
|
349 |
pipeline = None
|
350 |
|
351 |
-
def process_image_wrapper(image,
|
352 |
"""Wrapper function for Gradio interface"""
|
353 |
if pipeline is None:
|
354 |
return None, "Models not loaded properly!", None
|
355 |
|
356 |
-
return pipeline.process_image_gradio(image,
|
357 |
|
358 |
def download_results(results):
|
359 |
"""Create downloadable results"""
|
@@ -388,84 +392,127 @@ def download_results(results):
|
|
388 |
|
389 |
return filename
|
390 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
391 |
# Create Gradio interface
|
392 |
-
with gr.Blocks(title="Lettuce Analysis Pipeline", theme=gr.themes.Soft()) as demo:
|
393 |
-
|
394 |
-
# Header
|
395 |
-
gr.Markdown("""
|
396 |
-
# Complete Lettuce Analysis Pipeline
|
397 |
|
398 |
-
|
399 |
-
|
400 |
-
|
401 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
402 |
|
403 |
-
|
404 |
-
""")
|
405 |
|
406 |
# Model status
|
407 |
-
gr.Markdown(f"**
|
408 |
|
409 |
with gr.Row():
|
410 |
# Left column - Input
|
411 |
with gr.Column(scale=1):
|
412 |
-
gr.Markdown("##
|
413 |
|
414 |
# Image input
|
415 |
input_image = gr.Image(
|
416 |
type="pil",
|
417 |
label="Upload Lettuce Image",
|
418 |
sources=["upload"],
|
419 |
-
interactive=True
|
|
|
420 |
)
|
421 |
|
422 |
-
#
|
423 |
-
|
424 |
-
|
425 |
-
|
426 |
-
|
427 |
-
|
428 |
-
|
429 |
-
|
430 |
-
|
431 |
-
|
432 |
-
|
433 |
-
|
434 |
-
# growth_conf = gr.Slider(
|
435 |
-
# minimum=0.1,
|
436 |
-
# maximum=1.0,
|
437 |
-
# value=0.25,
|
438 |
-
# step=0.05,
|
439 |
-
# label="Growth Stage Confidence Threshold",
|
440 |
-
# info="Higher values = more strict growth classification"
|
441 |
-
# )
|
442 |
-
|
443 |
-
with gr.Row():
|
444 |
-
show_boxes = gr.Checkbox(
|
445 |
-
label="Show Bounding Boxes",
|
446 |
-
value=True
|
447 |
-
)
|
448 |
-
show_labels = gr.Checkbox(
|
449 |
-
label="Show Labels",
|
450 |
-
value=True
|
451 |
-
)
|
452 |
|
453 |
# Process button
|
454 |
process_btn = gr.Button(
|
455 |
-
"Analyze Lettuce",
|
456 |
variant="primary",
|
457 |
-
size="lg"
|
|
|
458 |
)
|
|
|
|
|
|
|
459 |
|
460 |
# Right column - Output
|
461 |
with gr.Column(scale=2):
|
462 |
-
gr.Markdown("## Results")
|
463 |
|
464 |
# Output image
|
465 |
output_image = gr.Image(
|
466 |
label="Analysis Results",
|
467 |
type="pil",
|
468 |
-
interactive=False
|
|
|
469 |
)
|
470 |
|
471 |
# Results summary
|
@@ -475,17 +522,19 @@ with gr.Blocks(title="Lettuce Analysis Pipeline", theme=gr.themes.Soft()) as dem
|
|
475 |
)
|
476 |
|
477 |
# Results table
|
478 |
-
gr.Markdown("##
|
479 |
results_table = gr.Dataframe(
|
480 |
-
label="
|
481 |
interactive=False,
|
482 |
wrap=True
|
483 |
)
|
484 |
|
485 |
# Download section
|
486 |
with gr.Row():
|
487 |
-
|
488 |
-
|
|
|
|
|
489 |
|
490 |
# Hidden state to store results
|
491 |
results_state = gr.State()
|
@@ -493,7 +542,7 @@ with gr.Blocks(title="Lettuce Analysis Pipeline", theme=gr.themes.Soft()) as dem
|
|
493 |
# Event handlers
|
494 |
process_btn.click(
|
495 |
fn=process_image_wrapper,
|
496 |
-
inputs=[input_image,
|
497 |
outputs=[output_image, results_summary, results_table, results_state]
|
498 |
)
|
499 |
|
@@ -507,32 +556,36 @@ with gr.Blocks(title="Lettuce Analysis Pipeline", theme=gr.themes.Soft()) as dem
|
|
507 |
)
|
508 |
|
509 |
# Footer
|
510 |
-
|
511 |
-
|
512 |
-
|
513 |
-
|
514 |
-
|
515 |
-
|
516 |
-
|
517 |
-
|
518 |
-
|
519 |
-
|
520 |
-
|
521 |
-
|
522 |
-
|
523 |
-
|
524 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
525 |
""")
|
526 |
|
527 |
# Launch the app
|
528 |
-
demo.launch()
|
529 |
-
|
530 |
-
"""
|
531 |
if __name__ == "__main__":
|
532 |
-
demo.launch(
|
533 |
-
share=True,
|
534 |
-
server_name="0.0.0.0",
|
535 |
-
server_port=7860,
|
536 |
-
debug=True
|
537 |
-
)
|
538 |
-
"""
|
|
|
26 |
self.growth_model_path = growth_model_path
|
27 |
self.health_classification_model_path = health_classification_model_path
|
28 |
|
29 |
+
# Fixed confidence thresholds (no longer adjustable via sliders)
|
30 |
+
self.detection_confidence = 0.5
|
31 |
+
self.growth_confidence = 0.25
|
32 |
+
|
33 |
# Load all models
|
34 |
self.load_models()
|
35 |
|
|
|
52 |
# 3. Load health classification model
|
53 |
self.load_health_classification_model()
|
54 |
|
55 |
+
return "✅ All models loaded successfully!"
|
56 |
|
57 |
except Exception as e:
|
58 |
+
return f"❌ Error loading models: {e}"
|
59 |
|
60 |
def load_health_classification_model(self):
|
61 |
"""Load the health classification model (ViT)"""
|
|
|
72 |
self.health_classification_model.load_state_dict(checkpoint['model_state_dict'])
|
73 |
self.health_classification_model.eval()
|
74 |
|
75 |
+
def detect_lettuce(self, image_path):
|
76 |
"""Stage 1: Detect lettuce in the image"""
|
77 |
+
results = self.detection_model(image_path, conf=self.detection_confidence)
|
78 |
detections = []
|
79 |
|
80 |
for result in results:
|
|
|
94 |
|
95 |
return detections
|
96 |
|
97 |
+
def classify_growth_stage(self, image_path, bbox):
|
98 |
"""Stage 2: Classify growth stage"""
|
99 |
try:
|
100 |
image = Image.open(image_path)
|
|
|
115 |
# Run growth stage classification
|
116 |
results = self.growth_model.predict(
|
117 |
source=temp_crop_path,
|
118 |
+
conf=self.growth_confidence,
|
119 |
save=False,
|
120 |
imgsz=640,
|
121 |
verbose=False
|
|
|
169 |
except Exception as e:
|
170 |
return "Unknown", 0.0
|
171 |
|
172 |
+
def process_image_gradio(self, image, show_boxes, show_labels):
|
173 |
"""
|
174 |
Process image for Gradio interface
|
175 |
"""
|
176 |
if image is None:
|
177 |
+
return None, "Please upload an image first!", None, None
|
178 |
|
179 |
try:
|
180 |
# Save uploaded image temporarily
|
|
|
186 |
image = image.convert('RGB')
|
187 |
|
188 |
# Stage 1: Detect lettuce
|
189 |
+
detections = self.detect_lettuce(temp_image_path)
|
190 |
|
191 |
if not detections:
|
192 |
# Clean up
|
193 |
if os.path.exists(temp_image_path):
|
194 |
os.remove(temp_image_path)
|
195 |
+
return image, "No lettuce detected in the image!", None, None
|
196 |
|
197 |
# Process each detection
|
198 |
complete_results = []
|
|
|
214 |
det_conf = detection['confidence']
|
215 |
|
216 |
# Stage 2: Growth stage
|
217 |
+
growth_stage, growth_conf = self.classify_growth_stage(temp_image_path, bbox)
|
218 |
|
219 |
# Stage 3: Health status
|
220 |
health_status, health_conf = self.classify_health(image, bbox)
|
|
|
296 |
if not results:
|
297 |
return "No results to display"
|
298 |
|
299 |
+
summary = f"**LETTUCE ANALYSIS RESULTS**\n\n"
|
300 |
summary += f"**Summary:**\n"
|
301 |
summary += f"- Total lettuce detected: **{len(results)}**\n"
|
302 |
|
|
|
311 |
summary += f"- Health statuses: {dict(health_counts)}\n\n"
|
312 |
|
313 |
# Detailed results
|
314 |
+
summary += f"📋 **Detailed Results:**\n\n"
|
315 |
|
316 |
for result in results:
|
317 |
summary += f"**Lettuce {result['lettuce_id']}:**\n"
|
|
|
352 |
model_status = f"Error loading models: {e}"
|
353 |
pipeline = None
|
354 |
|
355 |
+
def process_image_wrapper(image, show_boxes, show_labels):
|
356 |
"""Wrapper function for Gradio interface"""
|
357 |
if pipeline is None:
|
358 |
return None, "Models not loaded properly!", None
|
359 |
|
360 |
+
return pipeline.process_image_gradio(image, show_boxes, show_labels)
|
361 |
|
362 |
def download_results(results):
|
363 |
"""Create downloadable results"""
|
|
|
392 |
|
393 |
return filename
|
394 |
|
395 |
+
# Custom CSS for styling and logo
|
396 |
+
custom_css = """
|
397 |
+
.logo-container {
|
398 |
+
text-align: center;
|
399 |
+
margin-bottom: 20px;
|
400 |
+
}
|
401 |
+
|
402 |
+
.logo-container img {
|
403 |
+
max-height: 100px;
|
404 |
+
width: auto;
|
405 |
+
}
|
406 |
+
|
407 |
+
.company-header {
|
408 |
+
text-align: center;
|
409 |
+
margin-bottom: 30px;
|
410 |
+
padding: 20px;
|
411 |
+
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
412 |
+
border-radius: 10px;
|
413 |
+
color: white;
|
414 |
+
}
|
415 |
+
|
416 |
+
.analyze-button {
|
417 |
+
background: linear-gradient(45deg, #4CAF50, #45a049) !important;
|
418 |
+
color: white !important;
|
419 |
+
border: none !important;
|
420 |
+
padding: 15px 30px !important;
|
421 |
+
font-size: 16px !important;
|
422 |
+
font-weight: bold !important;
|
423 |
+
border-radius: 8px !important;
|
424 |
+
cursor: pointer !important;
|
425 |
+
transition: all 0.3s ease !important;
|
426 |
+
}
|
427 |
+
|
428 |
+
.analyze-button:hover {
|
429 |
+
transform: translateY(-2px) !important;
|
430 |
+
box-shadow: 0 4px 8px rgba(0,0,0,0.2) !important;
|
431 |
+
}
|
432 |
+
|
433 |
+
.settings-container {
|
434 |
+
background: #f8f9fa;
|
435 |
+
padding: 20px;
|
436 |
+
border-radius: 10px;
|
437 |
+
margin-bottom: 20px;
|
438 |
+
}
|
439 |
+
|
440 |
+
.footer-info {
|
441 |
+
background: #f1f3f4;
|
442 |
+
padding: 20px;
|
443 |
+
border-radius: 10px;
|
444 |
+
margin-top: 20px;
|
445 |
+
}
|
446 |
+
"""
|
447 |
+
|
448 |
# Create Gradio interface
|
449 |
+
with gr.Blocks(title="Lettuce Analysis Pipeline", theme=gr.themes.Soft(), css=custom_css) as demo:
|
|
|
|
|
|
|
|
|
450 |
|
451 |
+
# Company Header with Logo
|
452 |
+
with gr.Row():
|
453 |
+
gr.HTML("""
|
454 |
+
<div class="company-header"><div class="logo-container">
|
455 |
+
<img src="./GB_logo.jpg" alt="Garden Of Babylon" />
|
456 |
+
</div>
|
457 |
+
<h1>Advanced Lettuce Analysis Platform</h1>
|
458 |
+
<p>Powered by AI • Precision Agriculture Solutions</p>
|
459 |
+
</div>
|
460 |
+
""")
|
461 |
|
462 |
+
# Main content
|
463 |
+
# gr.Markdown("""## Professional Lettuce Analysis Pipeline Our advanced AI system performs comprehensive lettuce analysis in three automated stages: - **Detection**: Automatically locates lettuce in your images - **Growth Stage Classification**: Determines the growth stage of each lettuce plant- **Health Assessment**: Evaluates the health condition of each plant Simply upload an image and let our AI do the rest!""")
|
464 |
|
465 |
# Model status
|
466 |
+
gr.Markdown(f"**System Status:** {model_status}")
|
467 |
|
468 |
with gr.Row():
|
469 |
# Left column - Input
|
470 |
with gr.Column(scale=1):
|
471 |
+
gr.Markdown("## Upload Image")
|
472 |
|
473 |
# Image input
|
474 |
input_image = gr.Image(
|
475 |
type="pil",
|
476 |
label="Upload Lettuce Image",
|
477 |
sources=["upload"],
|
478 |
+
interactive=True,
|
479 |
+
height=300
|
480 |
)
|
481 |
|
482 |
+
# Simplified settings
|
483 |
+
with gr.Group():
|
484 |
+
gr.Markdown("### Display Options")
|
485 |
+
with gr.Row():
|
486 |
+
show_boxes = gr.Checkbox(
|
487 |
+
label="Show Bounding Boxes",
|
488 |
+
value=True
|
489 |
+
)
|
490 |
+
show_labels = gr.Checkbox(
|
491 |
+
label="Show Labels",
|
492 |
+
value=True
|
493 |
+
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
494 |
|
495 |
# Process button
|
496 |
process_btn = gr.Button(
|
497 |
+
"🚀 Analyze Lettuce",
|
498 |
variant="primary",
|
499 |
+
size="lg",
|
500 |
+
elem_classes="analyze-button"
|
501 |
)
|
502 |
+
|
503 |
+
# Info box
|
504 |
+
#gr.Markdown("""<div class="settings-container"><h4>ℹ️ Analysis Settings</h4><ul><li><strong>Detection Confidence:</strong> Optimized at 50%</li><li><strong>Growth Classification:</strong> Optimized at 25%</li><li><strong>Processing Time:</strong> ~5-15 seconds per image</li></ul></div>""")
|
505 |
|
506 |
# Right column - Output
|
507 |
with gr.Column(scale=2):
|
508 |
+
gr.Markdown("## Analysis Results")
|
509 |
|
510 |
# Output image
|
511 |
output_image = gr.Image(
|
512 |
label="Analysis Results",
|
513 |
type="pil",
|
514 |
+
interactive=False,
|
515 |
+
height=400
|
516 |
)
|
517 |
|
518 |
# Results summary
|
|
|
522 |
)
|
523 |
|
524 |
# Results table
|
525 |
+
gr.Markdown("##Detailed Results")
|
526 |
results_table = gr.Dataframe(
|
527 |
+
label="Comprehensive Analysis Data",
|
528 |
interactive=False,
|
529 |
wrap=True
|
530 |
)
|
531 |
|
532 |
# Download section
|
533 |
with gr.Row():
|
534 |
+
with gr.Column(scale=1):
|
535 |
+
download_btn = gr.Button("Download Results (JSON)", variant="secondary")
|
536 |
+
with gr.Column(scale=2):
|
537 |
+
download_file = gr.File(label="Download Analysis Report", visible=False)
|
538 |
|
539 |
# Hidden state to store results
|
540 |
results_state = gr.State()
|
|
|
542 |
# Event handlers
|
543 |
process_btn.click(
|
544 |
fn=process_image_wrapper,
|
545 |
+
inputs=[input_image, show_boxes, show_labels],
|
546 |
outputs=[output_image, results_summary, results_table, results_state]
|
547 |
)
|
548 |
|
|
|
556 |
)
|
557 |
|
558 |
# Footer
|
559 |
+
gr.HTML("""
|
560 |
+
<div class="footer-info">
|
561 |
+
<h3>🔧 System Features</h3>
|
562 |
+
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 20px;">
|
563 |
+
<div>
|
564 |
+
<h4>Precision Detection</h4>
|
565 |
+
<p>Advanced YOLO-based detection with optimized confidence thresholds</p>
|
566 |
+
</div>
|
567 |
+
<div>
|
568 |
+
<h4> Growth Analysis</h4>
|
569 |
+
<p>Multi-stage classification for accurate growth assessment</p>
|
570 |
+
</div>
|
571 |
+
<div>
|
572 |
+
<h4>Health Monitoring</h4>
|
573 |
+
<p>Vision Transformer (ViT) powered health status evaluation</p>
|
574 |
+
</div>
|
575 |
+
<div>
|
576 |
+
<h4>Comprehensive Reports</h4>
|
577 |
+
<p>Detailed analysis with downloadable JSON reports</p>
|
578 |
+
</div>
|
579 |
+
</div>
|
580 |
+
<hr style="margin: 20px 0;">
|
581 |
+
<p style="text-align: center; color: #666;">
|
582 |
+
<strong>Developed for Precision Agriculture</strong> |
|
583 |
+
Optimized confidence thresholds for maximum accuracy |
|
584 |
+
Support for multiple lettuce detection
|
585 |
+
</p>
|
586 |
+
</div>
|
587 |
""")
|
588 |
|
589 |
# Launch the app
|
|
|
|
|
|
|
590 |
if __name__ == "__main__":
|
591 |
+
demo.launch()
|
|
|
|
|
|
|
|
|
|
|
|