MSU576 commited on
Commit
4a41844
·
verified ·
1 Parent(s): 1b293ff

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +56 -81
app.py CHANGED
@@ -453,98 +453,73 @@ if __name__ == "__main__":
453
  # - GSD Curve Page (CSV upload + plotting + parameter calc)
454
  # -------------------------------------------------------
455
 
456
- import numpy as np
457
- import pandas as pd
458
- from PIL import Image
459
 
460
- # -------------------------------------------------------
461
- # Soil Recognizer
462
- # -------------------------------------------------------
463
- import torch
464
- import torch.nn as nn
465
- import torchvision.models as models
466
- import torchvision.transforms as transforms
467
- import streamlit as st
468
 
469
- # ----------------------------
470
- # Define SoilNet Architecture
471
- # ----------------------------
472
- class SoilNet(nn.Module):
473
- def __init__(self, num_classes=5):
474
- super(SoilNet, self).__init__()
475
- # Example: ResNet18 backbone (adjust if you trained differently)
476
- self.model = models.resnet18(weights=None) # no pretrained weights
477
- in_features = self.model.fc.in_features
478
- self.model.fc = nn.Linear(in_features, num_classes)
479
-
480
- def forward(self, x):
481
- return self.model(x)
482
-
483
- # ----------------------------
484
- # Load Soil Recognition Model
485
- # ----------------------------
486
- @st.cache_resource
487
- def load_soil_model():
488
- try:
489
- model = SoilNet(num_classes=5) # adjust num_classes if needed
490
- state_dict = torch.load("soil_best_model.pth", map_location="cpu")
491
- model.load_state_dict(state_dict)
492
- model.eval()
493
- return model
494
- except Exception as e:
495
- st.error(f"⚠️ Could not load soil model: {e}")
496
- return None
497
 
498
- soil_model = load_soil_model()
 
499
 
500
- # Define soil classes (adjust to your training labels)
501
- SOIL_CLASSES = ["Sand", "Silt", "Clay", "Gravel", "Peat"]
 
 
 
502
 
503
- # Image preprocessing pipeline
504
- transform = transforms.Compose([
505
- transforms.Resize((224, 224)), # match training input size
506
- transforms.ToTensor(),
507
- transforms.Normalize([0.485, 0.456, 0.406], # ImageNet normalization
508
- [0.229, 0.224, 0.225])
509
- ])
 
510
 
511
- # ----------------------------
512
- # Soil Recognizer UI
513
- # ----------------------------
514
- def soil_recognizer_ui():
515
- st.header("🖼️ Soil Recognizer (Image / OCR)")
516
- site = get_active_site()
517
 
518
- col1, col2 = st.columns(2)
 
 
519
 
520
- with col1:
521
- uploaded = st.file_uploader("Upload soil image", type=["jpg", "jpeg", "png"])
522
- if uploaded is not None:
523
- img = Image.open(uploaded).convert("RGB")
524
- st.image(img, caption="Uploaded soil image", use_column_width=True)
525
 
526
- if soil_model:
527
- try:
528
- # Preprocess
529
- img_t = transform(img).unsqueeze(0) # add batch dimension
530
- with torch.no_grad():
531
- outputs = soil_model(img_t)
532
- probs = torch.softmax(outputs, dim=1)
533
- conf, pred = torch.max(probs, 1)
534
- predicted_class = SOIL_CLASSES[pred.item()]
535
- confidence = conf.item()
536
-
537
- # Save to site
538
- site["Soil Profile"] = predicted_class
539
- site.setdefault("classifier_inputs", {})["image_confidence"] = confidence
540
- save_sites(SITES)
541
-
542
- st.success(f"✅ Predicted: **{predicted_class}** ({confidence:.2%} confidence)")
543
 
544
- except Exception as e:
545
- st.error(f"❌ Inference error: {e}")
 
 
 
 
 
 
 
 
546
  else:
547
- st.warning("⚠️ Soil model not loaded. Please check `soil_best_model.pth`.")
 
 
 
 
 
 
 
548
  # -------------------------------------------------------
549
  # Soil Classifier
550
  # -------------------------------------------------------
 
453
  # - GSD Curve Page (CSV upload + plotting + parameter calc)
454
  # -------------------------------------------------------
455
 
456
+ def soil_recognizer_page():
457
+ st.header("🖼️ Soil Recognizer")
458
+ idx = st.session_state["active_site_idx"]
459
 
460
+ st.write("Upload a soil sample photo. If a trained model is available, it will infer the soil class.")
 
 
 
 
 
 
 
461
 
462
+ uploaded = st.file_uploader(
463
+ "Upload sample photo",
464
+ type=["png", "jpg", "jpeg"],
465
+ key=mk("sr_upload", idx)
466
+ )
467
+
468
+ if uploaded:
469
+ img = Image.open(uploaded).convert("RGB")
470
+ st.image(img, use_column_width=True)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
471
 
472
+ if torch and os.path.exists("soil_best_model.pth"):
473
+ st.info("✅ Model found — running inference (CPU).")
474
 
475
+ try:
476
+ # --- Load model safely ---
477
+ model = torch.load("soil_best_model.pth", map_location="cpu")
478
+ if hasattr(model, "eval"):
479
+ model.eval()
480
 
481
+ # --- Preprocess ---
482
+ transform = T.Compose([
483
+ T.Resize((224, 224)),
484
+ T.ToTensor(),
485
+ T.Normalize([0.485, 0.456, 0.406],
486
+ [0.229, 0.224, 0.225])
487
+ ])
488
+ inp = transform(img).unsqueeze(0)
489
 
490
+ with st.spinner("Running model..."):
491
+ logits = model(inp)
492
+ probs = torch.softmax(logits, dim=-1).detach().cpu().numpy()[0]
 
 
 
493
 
494
+ labels = ["Sand", "Silt", "Clay", "Gravel", "Peat"]
495
+ best = labels[int(np.argmax(probs))]
496
+ conf = float(np.max(probs))
497
 
498
+ st.success(f"Predicted: **{best}** (confidence {conf:.2%})")
 
 
 
 
499
 
500
+ if st.button("Save to site", key=mk("sr_save_btn", idx)):
501
+ st.session_state["sites"][idx]["Soil Profile"] = best
502
+ st.success("✅ Saved soil profile to site.")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
503
 
504
+ except Exception as e:
505
+ st.error(f"❌ Model inference failed: {e}")
506
+
507
+ else:
508
+ # --- Heuristic Fallback ---
509
+ st.warning("⚠️ No trained model file found — running heuristic fallback.")
510
+ arr = np.array(img.resize((50, 50))).mean(axis=(0, 1))
511
+ r, g, b = arr
512
+ if r > 120 and g > 110:
513
+ pred = "Sand"
514
  else:
515
+ pred = "Silt"
516
+
517
+ st.success(f"Fallback prediction: **{pred}**")
518
+
519
+ if st.button("Save fallback to site", key=mk("sr_save_fallback", idx)):
520
+ st.session_state["sites"][idx]["Soil Profile"] = pred
521
+ st.success("✅ Saved fallback result to site.")
522
+
523
  # -------------------------------------------------------
524
  # Soil Classifier
525
  # -------------------------------------------------------