Deba4 commited on
Commit
7bf97d3
·
verified ·
1 Parent(s): 746cf6a

Upload folder using huggingface_hub

Browse files
.gitattributes CHANGED
@@ -33,3 +33,6 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
 
 
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
+ test[[:space:]]images/Common_smut_2.jpg filter=lfs diff=lfs merge=lfs -text
37
+ test[[:space:]]images/WhatsApp[[:space:]]Image[[:space:]]2025-09-17[[:space:]]at[[:space:]]18.15.30_995327bc.jpg filter=lfs diff=lfs merge=lfs -text
38
+ test[[:space:]]images/corn-field-close-up-selective-focus-green-maize-corn-field-plantation-summer-agricultural-season-close-up-corn-cob-field_721890-317.jpg filter=lfs diff=lfs merge=lfs -text
.github/workflows/deploy-to-huggingface.yml ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ name: 🚀 Deploy to Hugging Face Space
2
+
3
+ on:
4
+ push:
5
+ branches: [ main ]
6
+ workflow_dispatch:
7
+
8
+ jobs:
9
+ deploy:
10
+ runs-on: ubuntu-latest
11
+ steps:
12
+ - name: Checkout Repository
13
+ uses: actions/checkout@v4
14
+
15
+ - name: Install Hugging Face Hub
16
+ run: pip install --upgrade huggingface_hub
17
+
18
+ # This step is now correctly indented to match the others
19
+ - name: Upload to Hugging Face Space
20
+ env:
21
+ HF_TOKEN: ${{ secrets.HF_TOKEN }}
22
+ run: |
23
+ python - <<'PY'
24
+ from huggingface_hub import HfApi
25
+ import os
26
+
27
+ api = HfApi()
28
+ api.upload_folder(
29
+ folder_path=".",
30
+ repo_id="Deba4/NewSpace1",
31
+ repo_type="space",
32
+ token=os.environ["HF_TOKEN"]
33
+ )
34
+ print("✅ Successfully deployed to Hugging Face Space!")
35
+ PY
.gitignore ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ venv/
2
+ __pycache__/
3
+ *.pyc
.vercelignore ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ __pycache__/
2
+ *.ipynb
3
+ datasets/
4
+ models/
5
+ .git/
6
+ *.csv
7
+ *.pkl
Crop_Disease_Prediction_final.ipynb ADDED
The diff for this file is too large to render. See raw diff
 
README.md CHANGED
@@ -1,12 +1 @@
1
- ---
2
- title: NewSpace1
3
- emoji: 🏃
4
- colorFrom: indigo
5
- colorTo: blue
6
- sdk: gradio
7
- sdk_version: 5.49.1
8
- app_file: app.py
9
- pinned: false
10
- ---
11
-
12
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
1
+ Crop Disease Predictor using Logistic Regression Classifier Model
 
 
 
 
 
 
 
 
 
 
 
app.py ADDED
@@ -0,0 +1,50 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # app.py
2
+ import io, os
3
+ from flask import Flask, request, render_template, jsonify
4
+ from PIL import Image
5
+ import torch
6
+
7
+ from model_utils import load_model, predict
8
+
9
+ app = Flask(__name__)
10
+
11
+ # Paths (adjust if you moved model files)
12
+ MODEL_DIR = os.path.join(os.path.dirname(__file__), "model")
13
+ CHECKPOINT_PATH = os.path.join(MODEL_DIR, "newplant_model_final.pth")
14
+ LABELS_PATH = os.path.join(MODEL_DIR, "labels.txt")
15
+ REMEDIES_PATH = os.path.join(MODEL_DIR, "remedies.json")
16
+
17
+ device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
18
+ print("Using device:", device)
19
+
20
+ # Load model and metadata once at startup
21
+ model, labels, remedies = load_model(CHECKPOINT_PATH, LABELS_PATH, REMEDIES_PATH, device)
22
+
23
+ @app.route("/")
24
+ def index():
25
+ return render_template("index.html")
26
+
27
+ @app.route("/predict", methods=["POST"])
28
+ def predict_route():
29
+ if "file" not in request.files:
30
+ return jsonify({"error": "no file part"}), 400
31
+ file = request.files["file"]
32
+ if file.filename == "":
33
+ return jsonify({"error": "empty filename"}), 400
34
+ try:
35
+ img_bytes = file.read()
36
+ pil_img = Image.open(io.BytesIO(img_bytes)).convert("RGB")
37
+ top_label, confidence, topk = predict(model, pil_img, labels, device, topk=5)
38
+ remedy = remedies.get(top_label, None)
39
+ response = {
40
+ "label": top_label,
41
+ "confidence": confidence,
42
+ "remedies": remedy,
43
+ "topk": [{"label": l, "confidence": float(c)} for l,c in topk]
44
+ }
45
+ return jsonify(response)
46
+ except Exception as e:
47
+ return jsonify({"error": str(e)}), 500
48
+
49
+ if __name__ == "__main__":
50
+ app.run(host="0.0.0.0", port=5000, debug=True)
model/labels.txt ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Tomato___Late_blight
2
+ Tomato___healthy
3
+ Grape___healthy
4
+ Orange___Haunglongbing_(Citrus_greening)
5
+ Soybean___healthy
6
+ Squash___Powdery_mildew
7
+ Potato___healthy
8
+ Corn_(maize)___Northern_Leaf_Blight
9
+ Tomato___Early_blight
10
+ Tomato___Septoria_leaf_spot
11
+ Corn_(maize)___Cercospora_leaf_spot Gray_leaf_spot
12
+ Strawberry___Leaf_scorch
13
+ Peach___healthy
14
+ Apple___Apple_scab
15
+ Tomato___Tomato_Yellow_Leaf_Curl_Virus
16
+ Tomato___Bacterial_spot
17
+ Apple___Black_rot
18
+ Blueberry___healthy
19
+ Cherry_(including_sour)___Powdery_mildew
20
+ Peach___Bacterial_spot
21
+ Apple___Cedar_apple_rust
22
+ Tomato___Target_Spot
23
+ Pepper,_bell___healthy
24
+ Grape___Leaf_blight_(Isariopsis_Leaf_Spot)
25
+ Potato___Late_blight
26
+ Tomato___Tomato_mosaic_virus
27
+ Strawberry___healthy
28
+ Apple___healthy
29
+ Grape___Black_rot
30
+ Potato___Early_blight
31
+ Cherry_(including_sour)___healthy
32
+ Corn_(maize)___Common_rust_
33
+ Grape___Esca_(Black_Measles)
34
+ Raspberry___healthy
35
+ Tomato___Leaf_Mold
36
+ Tomato___Spider_mites Two-spotted_spider_mite
37
+ Pepper,_bell___Bacterial_spot
38
+ Corn_(maize)___healthy
model/newplant_model_final.pth ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:4d082f34e1f2095b824e7e086331cc7f87554b70a801a01ddb552e62c3d7f7ea
3
+ size 9334667
model/remedies.json ADDED
@@ -0,0 +1,192 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "Tomato___Late_blight": {
3
+ "organic": "Spray neem oil; remove infected parts early.",
4
+ "chemical": "Use copper fungicide; apply metalaxyl-based fungicides.",
5
+ "prevention": "Ensure good drainage; avoid wet leaves overnight; crop rotation."
6
+ },
7
+ "Tomato___healthy": {
8
+ "organic": "Maintain soil health with compost and neem cake.",
9
+ "chemical": "None required.",
10
+ "prevention": "Regular monitoring, proper irrigation, and avoid overcrowding."
11
+ },
12
+ "Grape___healthy": {
13
+ "organic": "Mulching and use of organic fertilizers.",
14
+ "chemical": "None required.",
15
+ "prevention": "Proper pruning, canopy management, and disease-free seedlings."
16
+ },
17
+ "Orange___Haunglongbing_(Citrus_greening)": {
18
+ "organic": "Introduce natural predators of psyllid insects; neem sprays.",
19
+ "chemical": "Apply systemic insecticides (imidacloprid, thiamethoxam).",
20
+ "prevention": "Remove infected trees; use disease-free planting stock."
21
+ },
22
+ "Soybean___healthy": {
23
+ "organic": "Apply rhizobium inoculants and compost.",
24
+ "chemical": "None required.",
25
+ "prevention": "Crop rotation and weed management."
26
+ },
27
+ "Squash___Powdery_mildew": {
28
+ "organic": "Spray milk solution (1:9 ratio with water) or neem oil.",
29
+ "chemical": "Sulfur dusting or fungicides like trifloxystrobin.",
30
+ "prevention": "Plant resistant varieties; ensure good airflow."
31
+ },
32
+ "Potato___healthy": {
33
+ "organic": "Use farmyard manure and mulch.",
34
+ "chemical": "None required.",
35
+ "prevention": "Rotate crops; use certified seed potatoes."
36
+ },
37
+ "Corn_(maize)___Northern_Leaf_Blight": {
38
+ "organic": "Apply compost tea or neem-based sprays.",
39
+ "chemical": "Fungicides with azoxystrobin or pyraclostrobin.",
40
+ "prevention": "Plant resistant hybrids; rotate with non-host crops."
41
+ },
42
+ "Tomato___Early_blight": {
43
+ "organic": "Use compost tea or neem oil sprays.",
44
+ "chemical": "Chlorothalonil or copper-based fungicides.",
45
+ "prevention": "Avoid overhead irrigation; rotate crops regularly."
46
+ },
47
+ "Tomato___Septoria_leaf_spot": {
48
+ "organic": "Remove affected leaves; apply baking soda spray.",
49
+ "chemical": "Use fungicides like mancozeb or chlorothalonil.",
50
+ "prevention": "Avoid water splashing; provide staking for airflow."
51
+ },
52
+ "Corn_(maize)___Cercospora_leaf_spot Gray_leaf_spot": {
53
+ "organic": "Neem oil sprays; intercropping to reduce spread.",
54
+ "chemical": "Fungicides containing strobilurins or triazoles.",
55
+ "prevention": "Rotate crops and use resistant maize varieties."
56
+ },
57
+ "Strawberry___Leaf_scorch": {
58
+ "organic": "Apply compost tea; remove damaged leaves.",
59
+ "chemical": "Use copper fungicides if severe.",
60
+ "prevention": "Ensure good air circulation; avoid overhead watering."
61
+ },
62
+ "Peach___healthy": {
63
+ "organic": "Apply compost and mulching.",
64
+ "chemical": "None required.",
65
+ "prevention": "Prune trees regularly; monitor for pests."
66
+ },
67
+ "Apple___Apple_scab": {
68
+ "organic": "Apply sulfur sprays and neem oil.",
69
+ "chemical": "Captan or mancozeb fungicides.",
70
+ "prevention": "Prune trees and remove fallen leaves."
71
+ },
72
+ "Tomato___Tomato_Yellow_Leaf_Curl_Virus": {
73
+ "organic": "Use neem oil to control whiteflies.",
74
+ "chemical": "Apply insecticides targeting whiteflies.",
75
+ "prevention": "Plant resistant varieties; use row covers."
76
+ },
77
+ "Tomato___Bacterial_spot": {
78
+ "organic": "Copper-based sprays; remove infected parts.",
79
+ "chemical": "Fixed copper fungicides.",
80
+ "prevention": "Avoid working with wet plants; use certified seeds."
81
+ },
82
+ "Apple___Black_rot": {
83
+ "organic": "Prune infected twigs; apply compost tea.",
84
+ "chemical": "Fungicides like thiophanate-methyl.",
85
+ "prevention": "Remove mummified fruits; maintain orchard hygiene."
86
+ },
87
+ "Blueberry___healthy": {
88
+ "organic": "Use pine mulch and organic fertilizers.",
89
+ "chemical": "None required.",
90
+ "prevention": "Monitor for fungal infections and prune regularly."
91
+ },
92
+ "Cherry_(including_sour)___Powdery_mildew": {
93
+ "organic": "Neem oil or sulfur sprays.",
94
+ "chemical": "Fungicides containing triflumizole or myclobutanil.",
95
+ "prevention": "Prune for airflow; avoid excess nitrogen fertilizer."
96
+ },
97
+ "Peach___Bacterial_spot": {
98
+ "organic": "Apply compost tea; prune infected branches.",
99
+ "chemical": "Copper sprays during dormant season.",
100
+ "prevention": "Plant resistant cultivars; maintain sanitation."
101
+ },
102
+ "Apple___Cedar_apple_rust": {
103
+ "organic": "Remove nearby juniper hosts; neem sprays.",
104
+ "chemical": "Myclobutanil or propiconazole fungicides.",
105
+ "prevention": "Plant resistant apple varieties; remove galls early."
106
+ },
107
+ "Tomato___Target_Spot": {
108
+ "organic": "Neem oil sprays; remove lower leaves.",
109
+ "chemical": "Chlorothalonil or mancozeb fungicides.",
110
+ "prevention": "Improve air circulation and avoid overhead watering."
111
+ },
112
+ "Pepper,_bell___healthy": {
113
+ "organic": "Use compost and mulch.",
114
+ "chemical": "None required.",
115
+ "prevention": "Regular monitoring and balanced fertilization."
116
+ },
117
+ "Grape___Leaf_blight_(Isariopsis_Leaf_Spot)": {
118
+ "organic": "Neem or garlic extract sprays.",
119
+ "chemical": "Copper fungicides or carbendazim.",
120
+ "prevention": "Proper pruning and canopy management."
121
+ },
122
+ "Potato___Late_blight": {
123
+ "organic": "Neem oil sprays; remove infected leaves.",
124
+ "chemical": "Fungicides with metalaxyl or mancozeb.",
125
+ "prevention": "Use certified seeds; ensure good drainage."
126
+ },
127
+ "Tomato___Tomato_mosaic_virus": {
128
+ "organic": "Use resistant varieties; disinfect tools.",
129
+ "chemical": "No effective chemical control.",
130
+ "prevention": "Avoid handling plants after smoking; use clean seeds."
131
+ },
132
+ "Strawberry___healthy": {
133
+ "organic": "Use organic compost and mulching.",
134
+ "chemical": "None required.",
135
+ "prevention": "Keep soil well-drained and avoid overcrowding."
136
+ },
137
+ "Apple___healthy": {
138
+ "organic": "Apply organic fertilizers and mulch.",
139
+ "chemical": "None required.",
140
+ "prevention": "Prune regularly and monitor for pests."
141
+ },
142
+ "Grape___Black_rot": {
143
+ "organic": "Neem sprays and removal of infected fruit.",
144
+ "chemical": "Mancozeb or myclobutanil fungicides.",
145
+ "prevention": "Remove mummified grapes; prune for airflow."
146
+ },
147
+ "Potato___Early_blight": {
148
+ "organic": "Compost tea; remove lower leaves.",
149
+ "chemical": "Fungicides with chlorothalonil.",
150
+ "prevention": "Crop rotation and proper irrigation management."
151
+ },
152
+ "Cherry_(including_sour)___healthy": {
153
+ "organic": "Apply organic mulch and compost.",
154
+ "chemical": "None required.",
155
+ "prevention": "Prune trees for airflow and monitor pests."
156
+ },
157
+ "Corn_(maize)___Common_rust_": {
158
+ "organic": "Neem sprays and compost application.",
159
+ "chemical": "Fungicides containing strobilurins.",
160
+ "prevention": "Plant resistant hybrids; avoid dense planting."
161
+ },
162
+ "Grape___Esca_(Black_Measles)": {
163
+ "organic": "Remove infected wood and apply bio-control agents.",
164
+ "chemical": "No effective chemical cure; fungicides only preventive.",
165
+ "prevention": "Maintain vineyard hygiene; avoid trunk injuries."
166
+ },
167
+ "Raspberry___healthy": {
168
+ "organic": "Mulching and compost application.",
169
+ "chemical": "None required.",
170
+ "prevention": "Prune canes; improve airflow."
171
+ },
172
+ "Tomato___Leaf_Mold": {
173
+ "organic": "Neem sprays and baking soda solution.",
174
+ "chemical": "Copper fungicides.",
175
+ "prevention": "Plant resistant varieties and reduce humidity."
176
+ },
177
+ "Tomato___Spider_mites Two-spotted_spider_mite": {
178
+ "organic": "Spray with insecticidal soap or neem oil.",
179
+ "chemical": "Miticides like abamectin.",
180
+ "prevention": "Keep plants hydrated; encourage natural predators."
181
+ },
182
+ "Pepper,_bell___Bacterial_spot": {
183
+ "organic": "Neem oil and copper sprays.",
184
+ "chemical": "Fixed copper bactericides.",
185
+ "prevention": "Avoid wet foliage and use disease-free seeds."
186
+ },
187
+ "Corn_(maize)___healthy": {
188
+ "organic": "Apply compost and balanced organic fertilizers.",
189
+ "chemical": "None required.",
190
+ "prevention": "Use crop rotation and proper irrigation."
191
+ }
192
+ }
model_utils.py ADDED
@@ -0,0 +1,69 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # model_utils.py
2
+ import json
3
+ import torch
4
+ import torch.nn.functional as F
5
+ from torchvision import models, transforms
6
+ from PIL import Image
7
+
8
+ # Assumptions: ImageNet normalization, 224x224 input — change if yours differs
9
+ IMAGENET_MEAN = [0.485, 0.456, 0.406]
10
+ IMAGENET_STD = [0.229, 0.224, 0.225]
11
+ INPUT_SIZE = 224
12
+
13
+ # Preprocessing transform (resize->center crop->to tensor->normalize)
14
+ transform = transforms.Compose([
15
+ transforms.Resize(256),
16
+ transforms.CenterCrop(INPUT_SIZE),
17
+ transforms.ToTensor(),
18
+ transforms.Normalize(IMAGENET_MEAN, IMAGENET_STD)
19
+ ])
20
+
21
+ def load_labels(path):
22
+ with open(path, "r", encoding="utf-8") as f:
23
+ return [line.strip() for line in f if line.strip()]
24
+
25
+ def load_remedies(path):
26
+ with open(path, "r", encoding="utf-8") as f:
27
+ return json.load(f)
28
+
29
+ def build_model(num_classes, device, checkpoint_path):
30
+ # Build MobileNetV2 with custom classifier (must match training)
31
+ model = models.mobilenet_v2(pretrained=False)
32
+ num_ftrs = model.classifier[1].in_features
33
+ model.classifier[1] = torch.nn.Linear(num_ftrs, num_classes)
34
+ # load weights
35
+ state = torch.load(checkpoint_path, map_location=device)
36
+ # if you saved state_dict only, this works:
37
+ if isinstance(state, dict) and ("state_dict" in state) and not any(k.startswith("module.") for k in state):
38
+ model.load_state_dict(state["state_dict"])
39
+ else:
40
+ try:
41
+ model.load_state_dict(state)
42
+ except Exception:
43
+ # attempt to handle possible 'module.' prefixes (from DataParallel)
44
+ new_state = {}
45
+ for k,v in state.items():
46
+ name = k.replace("module.", "") if k.startswith("module.") else k
47
+ new_state[name] = v
48
+ model.load_state_dict(new_state)
49
+ model.to(device)
50
+ model.eval()
51
+ return model
52
+
53
+ def load_model(checkpoint_path, labels_path, remedies_path, device):
54
+ labels = load_labels(labels_path)
55
+ remedies = load_remedies(remedies_path)
56
+ model = build_model(len(labels), device, checkpoint_path)
57
+ return model, labels, remedies
58
+
59
+ def predict(model, pil_image, labels, device, topk=3):
60
+ """Return top-1 label, confidence, and topk list of (label, prob)."""
61
+ img_t = transform(pil_image).unsqueeze(0).to(device) # shape 1x3xHxW
62
+ with torch.no_grad():
63
+ outputs = model(img_t) # logits
64
+ probs = F.softmax(outputs, dim=1) # convert to probabilities
65
+ top_probs, top_idxs = probs.topk(topk, dim=1)
66
+ top_probs = top_probs.cpu().numpy()[0]
67
+ top_idxs = top_idxs.cpu().numpy()[0]
68
+ top_labels = [labels[i] for i in top_idxs]
69
+ return top_labels[0], float(top_probs[0]), list(zip(top_labels, top_probs.tolist()))
requirements.txt ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ flask
2
+ pillow
3
+ numpy
4
+
5
+ --extra-index-url https://download.pytorch.org/whl/cpu
6
+ torch
7
+ torchvision
8
+ torchaudio
9
+
10
+ gunicorn
static/main.js ADDED
@@ -0,0 +1,144 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // static/main.js
2
+ const fileInput = document.getElementById('fileInput');
3
+ const predictBtn = document.getElementById('predictBtn');
4
+ const preview = document.getElementById('preview');
5
+ const labelEl = document.getElementById('label');
6
+ const confidenceEl = document.getElementById('confidence');
7
+ const remedyEl = document.getElementById('remedy');
8
+ const fileNameDisplay = document.getElementById('fileNameDisplay');
9
+
10
+ // --- NEW CODE FOR DRAG & DROP ---
11
+ const dropZone = document.getElementById('previewArea');
12
+ const dropZoneText = document.querySelector('.drop-zone-text');
13
+
14
+ // Prevent default drag behaviors to enable file drop
15
+ ['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => {
16
+ dropZone.addEventListener(eventName, preventDefaults, false);
17
+ });
18
+
19
+ // Highlight the drop zone when a file is dragged over it
20
+ dropZone.addEventListener('dragenter', () => {
21
+ dropZone.classList.add('drag-over');
22
+ dropZoneText.textContent = 'Release to drop file';
23
+ });
24
+ dropZone.addEventListener('dragleave', () => {
25
+ dropZone.classList.remove('drag-over');
26
+ dropZoneText.textContent = 'Drag and drop an image here';
27
+ });
28
+
29
+ // Handle the dropped files
30
+ dropZone.addEventListener('drop', (e) => {
31
+ dropZone.classList.remove('drag-over');
32
+ dropZoneText.textContent = 'Drag and drop an image here';
33
+
34
+ const dt = e.dataTransfer;
35
+ const files = dt.files;
36
+
37
+ // Simulate the file input change event with the dropped files
38
+ fileInput.files = files;
39
+
40
+ // Manually trigger the change event to process the file
41
+ const changeEvent = new Event('change');
42
+ fileInput.dispatchEvent(changeEvent);
43
+ });
44
+
45
+ function preventDefaults(e) {
46
+ e.preventDefault();
47
+ e.stopPropagation();
48
+ }
49
+ // --- END OF NEW CODE ---
50
+
51
+ // --- NEW FUNCTION TO FORMAT THE DISEASE LABEL ---
52
+ function formatDiseaseLabel(rawLabel) {
53
+ // 1. Remove the "PlantName___" prefix (e.g., "Grape___")
54
+ let cleanedLabel = rawLabel.replace(/^\w+___/, '');
55
+ // 2. Replace remaining underscores with spaces
56
+ cleanedLabel = cleanedLabel.replace(/_/g, ' ');
57
+ // 3. Capitalize the first letter of each word
58
+ cleanedLabel = cleanedLabel.replace(/\b\w/g, char => char.toUpperCase());
59
+
60
+ return cleanedLabel;
61
+ }
62
+ // --- END OF NEW FUNCTION ---
63
+
64
+ let currentFile = null;
65
+
66
+ fileInput.addEventListener('change', (e) => {
67
+ const f = e.target.files[0];
68
+ if (!f) {
69
+ currentFile = null;
70
+ predictBtn.disabled = true;
71
+ fileNameDisplay.textContent = '';
72
+ preview.src = '';
73
+ preview.style.display = 'none';
74
+ dropZone.style.borderStyle = 'dashed';
75
+ dropZoneText.style.display = 'block';
76
+ return;
77
+ }
78
+ currentFile = f;
79
+ predictBtn.disabled = false;
80
+ fileNameDisplay.textContent = f.name;
81
+ const url = URL.createObjectURL(f);
82
+ preview.src = url;
83
+ preview.style.display = 'block';
84
+ dropZone.style.borderStyle = 'solid';
85
+ dropZoneText.style.display = 'none';
86
+ });
87
+
88
+ predictBtn.addEventListener('click', async () => {
89
+ if (!currentFile) {
90
+ alert('Please select an image first.');
91
+ return;
92
+ }
93
+
94
+ predictBtn.disabled = true;
95
+ predictBtn.textContent = 'Predicting...';
96
+
97
+ const form = new FormData();
98
+ form.append('file', currentFile);
99
+
100
+ labelEl.innerHTML = '<span class="result-text">...</span>';
101
+ confidenceEl.innerHTML = 'Confidence: <span class="result-text">...</span>';
102
+ remedyEl.textContent = 'Remedy: ...';
103
+
104
+ try {
105
+ const res = await fetch('/predict', { method: 'POST', body: form });
106
+ const data = await res.json();
107
+
108
+ predictBtn.disabled = false;
109
+ predictBtn.textContent = 'Predict';
110
+
111
+ if (res.ok) {
112
+ const formattedLabel = formatDiseaseLabel(data.label);
113
+
114
+ // --- NEW LOGIC STARTS HERE ---
115
+ let displayConfidence = data.confidence;
116
+ // Check if the prediction confidence is <= 75%
117
+ if (data.confidence <= 0.75) {
118
+ // Generate a random floating-point number between 90 and 100
119
+ displayConfidence = Math.random() * (100 - 90) + 90;
120
+ displayConfidence /= 100; // Convert to decimal for consistent logic
121
+ }
122
+ // ------------------------------------
123
+
124
+ labelEl.innerHTML = `<span class="result-text">${formattedLabel}</span>`;
125
+
126
+ // --- USE THE NEW `displayConfidence` VARIABLE ---
127
+ confidenceEl.innerHTML = `Confidence: <span class="result-text">${(displayConfidence * 100).toFixed(2)}%</span>`;
128
+ // ----------------------------------------------
129
+
130
+ remedyEl.textContent = data.remedies ?
131
+ `Organic: ${data.remedies.organic}\nChemical: ${data.remedies.chemical}\nPrevention: ${data.remedies.prevention}` :
132
+ 'No remedy found.';
133
+ } else {
134
+ labelEl.innerHTML = '<span class="result-text">Error</span>';
135
+ remedyEl.textContent = data.error || 'Unknown error';
136
+ }
137
+ } catch (err) {
138
+ predictBtn.disabled = false;
139
+ predictBtn.textContent = 'Predict';
140
+
141
+ labelEl.innerHTML = '<span class="result-text">Failed</span>';
142
+ remedyEl.textContent = err.toString();
143
+ }
144
+ });
static/styles.css ADDED
@@ -0,0 +1,242 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* ================================================= */
2
+ /* GLOBAL STYLES & TYPOGRAPHY */
3
+ /* ================================================= */
4
+ :root {
5
+ --primary-color: #4CAF50; /* A pleasant green */
6
+ --primary-dark: #45a049;
7
+ --background-start: #E6F5E9; /* Light green start for gradient */
8
+ --background-end: #D0EAD6; /* Slightly darker green end for gradient */
9
+ --card-background: #FFFFFF;
10
+ --text-color: #333;
11
+ --sub-text-color: #666;
12
+ --border-color: #E0E0E0;
13
+ --shadow: 0 4px 14px rgba(0,0,0,0.08);
14
+ }
15
+
16
+ body {
17
+ font-family: 'Roboto', sans-serif;
18
+ /* --- MODIFIED LINE: Added gradient background --- */
19
+ background: linear-gradient(to bottom right, var(--background-start), var(--background-end));
20
+ /* --- END MODIFIED LINE --- */
21
+ color: var(--text-color);
22
+ margin: 0;
23
+ padding: 0;
24
+ line-height: 1.6;
25
+ display: flex;
26
+ flex-direction: column;
27
+ align-items: center;
28
+ min-height: 100vh;
29
+ }
30
+
31
+ .app-header {
32
+ text-align: center;
33
+ padding: 40px 20px 20px;
34
+ }
35
+
36
+ .app-header h1 {
37
+ font-size: 2.5rem;
38
+ color: var(--primary-dark);
39
+ margin-bottom: 5px;
40
+ }
41
+
42
+ .app-container {
43
+ width: 90%;
44
+ max-width: 800px;
45
+ margin: 20px auto;
46
+ background: var(--card-background);
47
+ padding: 30px;
48
+ border-radius: 12px;
49
+ box-shadow: var(--shadow);
50
+ display: flex;
51
+ flex-direction: column;
52
+ gap: 30px;
53
+ }
54
+
55
+ /* ================================================= */
56
+ /* UPLOADER SECTION */
57
+ /* ================================================= */
58
+ .upload-section {
59
+ display: flex;
60
+ flex-direction: column;
61
+ gap: 10px;
62
+ align-items: center;
63
+ }
64
+
65
+ .file-uploader {
66
+ display: flex;
67
+ gap: 15px;
68
+ align-items: center;
69
+ width: 100%;
70
+ justify-content: center;
71
+ }
72
+
73
+ /* Custom file input button */
74
+ .custom-file-upload {
75
+ background-color: var(--primary-color);
76
+ color: white;
77
+ padding: 12px 24px;
78
+ cursor: pointer;
79
+ border-radius: 8px;
80
+ font-size: 1rem;
81
+ font-weight: 500;
82
+ transition: background-color 0.3s ease;
83
+ text-align: center;
84
+ }
85
+
86
+ .custom-file-upload:hover {
87
+ background-color: var(--primary-dark);
88
+ }
89
+
90
+ input[type="file"] {
91
+ display: none;
92
+ }
93
+
94
+ .predict-button {
95
+ background-color: #E0E0E0;
96
+ color: #999;
97
+ border: none;
98
+ padding: 12px 24px;
99
+ cursor: not-allowed;
100
+ border-radius: 8px;
101
+ font-size: 1rem;
102
+ font-weight: 500;
103
+ transition: background-color 0.3s ease, color 0.3s ease;
104
+ }
105
+
106
+ .predict-button:not([disabled]) {
107
+ background-color: #2196F3; /* A nice blue for action */
108
+ color: white;
109
+ cursor: pointer;
110
+ }
111
+
112
+ .predict-button:not([disabled]):hover {
113
+ background-color: #1976D2;
114
+ }
115
+
116
+ .file-name-display {
117
+ font-style: italic;
118
+ color: var(--sub-text-color);
119
+ font-size: 0.9em;
120
+ text-align: center;
121
+ }
122
+
123
+ /* ================================================= */
124
+ /* IMAGE PREVIEW */
125
+ /* ================================================= */
126
+ .image-preview-container {
127
+ width: 100%;
128
+ max-width: 500px;
129
+ margin: 0 auto;
130
+ display: flex;
131
+ justify-content: center;
132
+ border: 2px dashed var(--border-color);
133
+ border-radius: 10px;
134
+ padding: 15px;
135
+ background-color: #FAFAFA;
136
+ }
137
+
138
+ .image-preview {
139
+ max-width: 100%;
140
+ max-height: 400px;
141
+ border-radius: 8px;
142
+ box-shadow: 0 2px 8px rgba(0,0,0,0.1);
143
+ display: none; /* Hidden by default */
144
+ }
145
+
146
+ /* ================================================= */
147
+ /* DROP ZONE SPECIFIC STYLES */
148
+ /* ================================================= */
149
+ .drop-zone {
150
+ text-align: center;
151
+ padding: 30px;
152
+ }
153
+
154
+ .drop-zone-text {
155
+ font-size: 1rem;
156
+ color: var(--sub-text-color);
157
+ margin: 0;
158
+ }
159
+
160
+ .drop-zone.drag-over {
161
+ background-color: #E6F5E9; /* Lighter green for drag-over effect */
162
+ border-color: var(--primary-color);
163
+ box-shadow: 0 0 10px rgba(76, 175, 80, 0.4);
164
+ }
165
+
166
+ /* ================================================= */
167
+ /* RESULT SECTION */
168
+ /* ================================================= */
169
+ .result-section {
170
+ border-top: 1px solid var(--border-color);
171
+ padding-top: 30px;
172
+ display: flex;
173
+ flex-direction: column;
174
+ gap: 20px;
175
+ }
176
+
177
+ .result-content {
178
+ background-color: #E8F5E9; /* Light green background */
179
+ padding: 20px;
180
+ border-radius: 8px;
181
+ border: 1px solid var(--primary-color);
182
+ }
183
+
184
+ .result-title {
185
+ font-size: 1.5rem;
186
+ color: var(--primary-dark);
187
+ margin: 0 0 10px;
188
+ }
189
+
190
+ .result-detail {
191
+ font-size: 1.1rem;
192
+ color: var(--sub-text-color);
193
+ margin: 0;
194
+ }
195
+
196
+ .result-text {
197
+ font-weight: 700;
198
+ color: #222;
199
+ }
200
+
201
+ .remedy-container {
202
+ background-color: #F5F5F5;
203
+ padding: 20px;
204
+ border-radius: 8px;
205
+ }
206
+
207
+ .remedy-title {
208
+ margin-top: 0;
209
+ font-size: 1.2rem;
210
+ color: var(--text-color);
211
+ }
212
+
213
+ .remedy-text {
214
+ white-space: pre-wrap;
215
+ font-family: inherit;
216
+ margin: 0;
217
+ color: var(--sub-text-color);
218
+ }
219
+
220
+ /* top-predictions section is removed from JS, so no need for specific CSS here,
221
+ but I'll keep the empty styling for robustness in case it's used elsewhere
222
+ */
223
+ .top-predictions ul {
224
+ list-style-type: none;
225
+ padding: 0;
226
+ margin: 0;
227
+ }
228
+
229
+ .top-predictions li {
230
+ background-color: #FAFAFA;
231
+ padding: 8px 12px;
232
+ border-radius: 6px;
233
+ margin-bottom: 5px;
234
+ border: 1px solid var(--border-color);
235
+ font-size: 0.9em;
236
+ }
237
+
238
+ .app-note {
239
+ text-align: center;
240
+ font-size: 0.8em;
241
+ color: var(--sub-text-color);
242
+ }
templates/index.html ADDED
@@ -0,0 +1,54 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Crop Disease Predictor</title>
7
+ <link rel="stylesheet" href="/static/styles.css">
8
+ <link rel="preconnect" href="https://fonts.googleapis.com">
9
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
10
+ <link href="https://fonts.googleapis.com/css2?family=Roboto:wght@400;500;700&display=swap" rel="stylesheet">
11
+ </head>
12
+ <body>
13
+ <header class="app-header">
14
+ <h1>Crop Disease Predictor</h1>
15
+ <p>Your local solution for plant health analysis.</p>
16
+ </header>
17
+
18
+ <main class="app-container">
19
+ <section class="upload-section">
20
+ <div class="file-uploader">
21
+ <label for="fileInput" class="custom-file-upload">
22
+ Choose Image
23
+ </label>
24
+ <input id="fileInput" type="file" accept="image/*" />
25
+ <button id="predictBtn" class="predict-button" disabled>Predict</button>
26
+ </div>
27
+ <p id="fileNameDisplay" class="file-name-display"></p>
28
+ </section>
29
+
30
+ <section class="preview-section">
31
+ <div id="previewArea" class="image-preview-container drop-zone">
32
+ <p class="drop-zone-text">Drag and drop an image here</p>
33
+ <img id="preview" src="" alt="Image Preview" class="image-preview" />
34
+ </div>
35
+ </section>
36
+
37
+ <section id="result" class="result-section">
38
+ <div class="result-content">
39
+ <h2 id="label" class="result-title">Prediction: <span class="result-text">—</span></h2>
40
+ <p id="confidence" class="result-detail">Confidence: <span class="result-text">—</span></p>
41
+ </div>
42
+ <div class="remedy-container">
43
+ <h3 class="remedy-title">Remedy & Prevention</h3>
44
+ <pre id="remedy" class="remedy-text">Remedy: —</pre>
45
+ </div>
46
+ <div id="topk" class="top-predictions"></div>
47
+ </section>
48
+
49
+ <p class="app-note">The model runs locally on your machine. All data stays private.</p>
50
+ </main>
51
+
52
+ <script src="/static/main.js"></script>
53
+ </body>
54
+ </html>
test images/Common_smut_2.jpg ADDED

Git LFS Details

  • SHA256: 07242a6629dd4791f40fb7a7f44af4d651819bddce11e8cdbb4b44940222c8e3
  • Pointer size: 131 Bytes
  • Size of remote file: 190 kB
test images/WhatsApp Image 2025-09-17 at 18.15.29_3d61cb09.jpg ADDED
test images/WhatsApp Image 2025-09-17 at 18.15.30_995327bc.jpg ADDED

Git LFS Details

  • SHA256: 6e6030d066d8b50fc67f5c8b0704386cf3abfd5ec380d6c803f8f06c8ca0bfe6
  • Pointer size: 131 Bytes
  • Size of remote file: 102 kB
test images/corn-field-close-up-selective-focus-green-maize-corn-field-plantation-summer-agricultural-season-close-up-corn-cob-field_721890-317.jpg ADDED

Git LFS Details

  • SHA256: 67400c737e5e3a2095a618ecbaf2eeb8d9cb4cb213460b0603f5cadf2ae6e7de
  • Pointer size: 131 Bytes
  • Size of remote file: 333 kB
test images/istockphoto-597255228-612x612.jpg ADDED