krushimitravit commited on
Commit
ddef594
·
verified ·
1 Parent(s): fe86712

Upload 7 files

Browse files
.gitattributes CHANGED
@@ -33,3 +33,5 @@ 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
+ geodata.csv filter=lfs diff=lfs merge=lfs -text
37
+ static/images/img.png filter=lfs diff=lfs merge=lfs -text
Dockerfile ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Use an official Python runtime as a parent image
2
+ FROM python:3.9-slim
3
+
4
+ # Set the working directory
5
+ WORKDIR /app
6
+
7
+ # Copy the application files to the container
8
+ COPY . /app
9
+
10
+ # Install Python dependencies
11
+ RUN pip install --no-cache-dir -r requirements.txt
12
+
13
+
14
+ # Expose the Flask port (Hugging Face Spaces uses port 7860 by default)
15
+ EXPOSE 7860
16
+
17
+ # Command to run the Flask app
18
+ CMD ["python", "app.py"]
app.py ADDED
@@ -0,0 +1,83 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from flask import Flask, render_template, request, jsonify
2
+ import pandas as pd
3
+ import joblib
4
+
5
+ app = Flask(__name__)
6
+
7
+ # Load your trained model
8
+ model = joblib.load('crop_price_model (1).pkl')
9
+
10
+ # Load the geospatial data
11
+ geo_data = pd.read_csv('geodata.csv') # Update with your actual CSV file path
12
+ states = geo_data['State'].unique().tolist()
13
+
14
+ # Sample crop list for demonstration; replace with actual crop data if needed
15
+ crops = ['Apple', 'Banana', 'Bhindi', 'Bitter Gourd', 'Brinjal', 'Cabbage', 'Capsicum',
16
+ 'Carrot', 'Cauliflower', 'Cluster Beans', 'Colacasia', 'Cucumbar', 'Dry Fodder',
17
+ 'French Beans', 'Grapes', 'Green Chilli', 'Green Fodder', 'Guava', 'Leafy Vegetable',
18
+ 'Lemon', 'Maize', 'Mango', 'Methi(Leaves)', 'Mousambi', 'Onion', 'Pear',
19
+ 'Pomegranate', 'Potato', 'Pumpkin', 'Raddish', 'Sponge Gourd', 'Sweet Potato',
20
+ 'Tinda', 'Tomato', 'Wheat', 'blackgram', 'chickpea', 'coconut', 'coffee',
21
+ 'cotton', 'jute', 'kidneybeans', 'lentil', 'mothbeans', 'mungbean',
22
+ 'muskmelon', 'orange', 'papaya', 'pigeonbeans', 'rice', 'watermelon']
23
+
24
+ # Create a LabelEncoder for the 'crop' column
25
+ crop_mapping = {
26
+ 'Apple': 0, 'Banana': 1, 'Bhindi': 2, 'Bitter Gourd': 3, 'Brinjal': 4,
27
+ 'Cabbage': 5, 'Capsicum': 6, 'Carrot': 7, 'Cauliflower': 8,
28
+ 'Cluster Beans': 9, 'Colacasia': 10, 'Cucumbar': 11,
29
+ 'Dry Fodder': 12, 'French Beans': 13, 'Grapes': 14,
30
+ 'Green Chilli': 15, 'Green Fodder': 16, 'Guava': 17,
31
+ 'Leafy Vegetable': 18, 'Lemon': 19, 'Maize': 20,
32
+ 'Mango': 21, 'Methi(Leaves)': 22, 'Mousambi': 23,
33
+ 'Onion': 24, 'Pear': 25, 'Pomegranate': 26, 'Potato': 27,
34
+ 'Pumpkin': 28, 'Raddish': 29, 'Sponge Gourd': 30,
35
+ 'Sweet Potato': 31, 'Tinda': 32, 'Tomato': 33, 'Wheat': 34,
36
+ 'blackgram': 35, 'chickpea': 36, 'coconut': 37, 'coffee': 38,
37
+ 'cotton': 39, 'jute': 40, 'kidneybeans': 41, 'lentil': 42,
38
+ 'mothbeans': 43, 'mungbean': 44, 'muskmelon': 45, 'orange': 46,
39
+ 'papaya': 47, 'pigeonbeans': 48, 'rice': 49, 'watermelon': 50
40
+ }
41
+
42
+
43
+ @app.route('/')
44
+ def index():
45
+ return render_template('index.html', states=states, crops=crops)
46
+
47
+
48
+ @app.route('/districts', methods=['POST'])
49
+ def get_districts():
50
+ state = request.form.get('state')
51
+ districts = geo_data[geo_data['State'] == state]['District '].unique().tolist()
52
+ return jsonify({'districts': districts})
53
+
54
+
55
+ @app.route('/predict', methods=['POST'])
56
+ def predict():
57
+ state = request.form.get('state')
58
+ district = request.form.get('district')
59
+ date = request.form.get('date')
60
+ crop = request.form.get('crop')
61
+ production = float(request.form.get('production'))
62
+
63
+ # Convert date to year
64
+ year = pd.to_datetime(date).year
65
+
66
+ # Encode the crop using the mapping
67
+ crop_encoded = crop_mapping[crop]
68
+
69
+ # Prepare input for model prediction
70
+ input_data = pd.DataFrame({
71
+ 'year': [year],
72
+ 'crop': [crop_encoded], # Use the encoded crop
73
+ 'production': [production]
74
+ })
75
+
76
+ # Use the model to make predictions
77
+ predicted_price = model.predict(input_data)[0] # Get the predicted price
78
+
79
+ return jsonify({'predicted_price': predicted_price})
80
+
81
+
82
+ if __name__ == '__main__':
83
+ app.run(port=7860,host='0.0.0.0')
crop_price_model (1).pkl ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:30d5108f1a987100e6471583148d15e4379a1a44c2fa8527761ab0ac9e8ee782
3
+ size 912
geodata.csv ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:8da3428b4169b7aebfd043ff2d30afe34f9421a4b0949e40c4b375859e53843e
3
+ size 21143323
requirements.txt ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ gunicorn
2
+ flask
3
+ pandas
4
+ scikit-learn==1.5.2
5
+ joblib==1.4.2
static/images/img.png ADDED

Git LFS Details

  • SHA256: 01970b95c76af1f963cb6e1a8aed5417c2db33c29d92d9cc0a0be01950d47a40
  • Pointer size: 132 Bytes
  • Size of remote file: 4.49 MB
templates/index.html ADDED
@@ -0,0 +1,436 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 Price Prediction</title>
7
+
8
+ <!-- Bootstrap CSS -->
9
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css">
10
+ <!-- Bootstrap Icons -->
11
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.0/font/bootstrap-icons.css">
12
+ <!-- Google Fonts - Outfit -->
13
+ <link rel="preconnect" href="https://fonts.googleapis.com">
14
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
15
+ <link href="https://fonts.googleapis.com/css2?family=Outfit:wght@300;400;500;600;700&display=swap" rel="stylesheet">
16
+
17
+ <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
18
+
19
+ <style>
20
+ /* ===== GLOBAL STYLES ===== */
21
+ * {
22
+ margin: 0;
23
+ padding: 0;
24
+ box-sizing: border-box;
25
+ }
26
+
27
+ body {
28
+ font-family: 'Outfit', sans-serif;
29
+ background-color: #f8f9fa;
30
+ color: #212529;
31
+ font-weight: 400;
32
+ line-height: 1.6;
33
+ }
34
+
35
+ /* ===== CURVED BOTTOM HERO HEADER ===== */
36
+ .hero-header {
37
+ background-color: #1a5d3a;
38
+ color: white;
39
+ padding: 3rem 0 5rem 0;
40
+ border-bottom-left-radius: 50% 20px;
41
+ border-bottom-right-radius: 50% 20px;
42
+ margin-bottom: -3rem;
43
+ position: relative;
44
+ z-index: 1;
45
+ }
46
+
47
+ .hero-header h1 {
48
+ font-size: 2.5rem;
49
+ font-weight: 700;
50
+ text-align: center;
51
+ margin: 0;
52
+ }
53
+
54
+ .hero-header p {
55
+ text-align: center;
56
+ font-size: 1.1rem;
57
+ font-weight: 300;
58
+ margin-top: 0.5rem;
59
+ opacity: 0.95;
60
+ }
61
+
62
+ /* ===== PROCESS VISUAL (3-STEP ICONS) ===== */
63
+ .process-steps {
64
+ display: flex;
65
+ justify-content: center;
66
+ align-items: center;
67
+ gap: 2rem;
68
+ margin: 2rem 0 4rem 0;
69
+ position: relative;
70
+ z-index: 2;
71
+ }
72
+
73
+ .process-step {
74
+ text-align: center;
75
+ color: white;
76
+ }
77
+
78
+ .process-step i {
79
+ font-size: 2.5rem;
80
+ display: block;
81
+ margin-bottom: 0.5rem;
82
+ }
83
+
84
+ .process-step span {
85
+ font-size: 0.9rem;
86
+ font-weight: 500;
87
+ }
88
+
89
+ .process-arrow {
90
+ font-size: 1.5rem;
91
+ color: rgba(255, 255, 255, 0.6);
92
+ }
93
+
94
+ /* ===== MAIN CONTAINER ===== */
95
+ .main-container {
96
+ max-width: 1200px;
97
+ margin: 0 auto;
98
+ padding: 0 1rem;
99
+ position: relative;
100
+ z-index: 2;
101
+ }
102
+
103
+ /* ===== CARD STYLES ===== */
104
+ .prediction-card {
105
+ background: #ffffff;
106
+ border-radius: 20px;
107
+ box-shadow: 0 10px 40px rgba(0, 0, 0, 0.08);
108
+ padding: 3rem;
109
+ margin-bottom: 2rem;
110
+ }
111
+
112
+ /* ===== FORM STYLES ===== */
113
+ .form-label {
114
+ font-weight: 500;
115
+ color: #212529;
116
+ margin-bottom: 0.5rem;
117
+ font-size: 0.95rem;
118
+ }
119
+
120
+ .form-control, .form-select {
121
+ background-color: #f8f9fa;
122
+ border: 1px solid #dee2e6;
123
+ border-radius: 8px;
124
+ padding: 0.75rem 1rem;
125
+ font-size: 1rem;
126
+ font-weight: 400;
127
+ transition: all 0.3s ease;
128
+ }
129
+
130
+ .form-control:focus, .form-select:focus {
131
+ background-color: #ffffff;
132
+ border-color: #198754;
133
+ box-shadow: 0 0 0 4px rgba(25, 135, 84, 0.1);
134
+ outline: none;
135
+ }
136
+
137
+ .form-group {
138
+ margin-bottom: 1.5rem;
139
+ }
140
+
141
+ /* ===== BUTTON STYLES ===== */
142
+ .btn-primary-action {
143
+ background-color: #1a5d3a;
144
+ color: white;
145
+ border: none;
146
+ border-radius: 8px;
147
+ padding: 0.875rem 2rem;
148
+ font-size: 1rem;
149
+ font-weight: 500;
150
+ display: inline-flex;
151
+ align-items: center;
152
+ gap: 0.5rem;
153
+ transition: all 0.3s ease;
154
+ width: 100%;
155
+ justify-content: center;
156
+ }
157
+
158
+ .btn-primary-action:hover {
159
+ background-color: #143d2e;
160
+ transform: translateY(-2px);
161
+ box-shadow: 0 4px 12px rgba(26, 93, 58, 0.3);
162
+ }
163
+
164
+ .btn-primary-action i {
165
+ font-size: 1.2rem;
166
+ }
167
+
168
+ /* ===== RESULT BOX ===== */
169
+ .result-box {
170
+ background: linear-gradient(135deg, #198754 0%, #1a5d3a 100%);
171
+ color: white;
172
+ border-radius: 20px;
173
+ padding: 2rem;
174
+ margin-top: 2rem;
175
+ box-shadow: 0 10px 40px rgba(25, 135, 84, 0.2);
176
+ display: none;
177
+ animation: slideIn 0.5s ease;
178
+ }
179
+
180
+ @keyframes slideIn {
181
+ from {
182
+ opacity: 0;
183
+ transform: translateY(-20px);
184
+ }
185
+ to {
186
+ opacity: 1;
187
+ transform: translateY(0);
188
+ }
189
+ }
190
+
191
+ .result-box h4 {
192
+ font-size: 1.5rem;
193
+ font-weight: 600;
194
+ margin: 0;
195
+ display: flex;
196
+ align-items: center;
197
+ gap: 0.75rem;
198
+ }
199
+
200
+ .result-box h4 i {
201
+ font-size: 2rem;
202
+ }
203
+
204
+ .result-price {
205
+ font-size: 2.5rem;
206
+ font-weight: 700;
207
+ margin-top: 1rem;
208
+ text-align: center;
209
+ }
210
+
211
+ /* ===== IMAGE SECTION ===== */
212
+ .image-preview {
213
+ border-radius: 20px;
214
+ overflow: hidden;
215
+ box-shadow: 0 10px 40px rgba(0, 0, 0, 0.08);
216
+ height: 100%;
217
+ min-height: 400px;
218
+ }
219
+
220
+ .image-preview img {
221
+ width: 100%;
222
+ height: 100%;
223
+ object-fit: cover;
224
+ }
225
+
226
+ /* ===== RESPONSIVE DESIGN ===== */
227
+ @media (max-width: 768px) {
228
+ .hero-header h1 {
229
+ font-size: 2rem;
230
+ }
231
+
232
+ .hero-header p {
233
+ font-size: 1rem;
234
+ }
235
+
236
+ .process-steps {
237
+ gap: 1rem;
238
+ }
239
+
240
+ .process-step i {
241
+ font-size: 2rem;
242
+ }
243
+
244
+ .process-step span {
245
+ font-size: 0.8rem;
246
+ }
247
+
248
+ .prediction-card {
249
+ padding: 2rem 1.5rem;
250
+ }
251
+
252
+ .image-preview {
253
+ min-height: 250px;
254
+ margin-top: 2rem;
255
+ }
256
+ }
257
+ </style>
258
+ </head>
259
+ <body>
260
+ <!-- Hero Header with Curved Bottom -->
261
+ <div class="hero-header">
262
+ <div class="container">
263
+ <h1><i class="bi bi-graph-up-arrow"></i> Crop Price Prediction</h1>
264
+ <p>Get accurate price predictions for your crops based on location and production data</p>
265
+
266
+ <!-- Process Steps -->
267
+ <div class="process-steps">
268
+ <div class="process-step">
269
+ <i class="bi bi-geo-alt-fill"></i>
270
+ <span>Select Location</span>
271
+ </div>
272
+ <i class="bi bi-arrow-right process-arrow"></i>
273
+ <div class="process-step">
274
+ <i class="bi bi-clipboard-data-fill"></i>
275
+ <span>Enter Details</span>
276
+ </div>
277
+ <i class="bi bi-arrow-right process-arrow"></i>
278
+ <div class="process-step">
279
+ <i class="bi bi-currency-rupee"></i>
280
+ <span>Get Price</span>
281
+ </div>
282
+ </div>
283
+ </div>
284
+ </div>
285
+
286
+ <!-- Main Content -->
287
+ <div class="main-container">
288
+ <div class="prediction-card">
289
+ <div class="row">
290
+ <!-- Form Section -->
291
+ <div class="col-lg-7">
292
+ <form id="prediction-form">
293
+ <div class="form-group">
294
+ <label for="state" class="form-label">
295
+ <i class="bi bi-map"></i> Select State
296
+ </label>
297
+ <select class="form-select" id="state" name="state" required>
298
+ <option value="">Choose your state...</option>
299
+ {% for state in states %}
300
+ <option value="{{ state }}">{{ state }}</option>
301
+ {% endfor %}
302
+ </select>
303
+ </div>
304
+
305
+ <div class="form-group">
306
+ <label for="district" class="form-label">
307
+ <i class="bi bi-pin-map"></i> Select District
308
+ </label>
309
+ <select class="form-select" id="district" name="district" required>
310
+ <option value="">Choose your district...</option>
311
+ </select>
312
+ </div>
313
+
314
+ <div class="form-group">
315
+ <label for="date" class="form-label">
316
+ <i class="bi bi-calendar-event"></i> Select Date
317
+ </label>
318
+ <input type="date" class="form-control" id="date" name="date" required>
319
+ </div>
320
+
321
+ <div class="form-group">
322
+ <label for="crop" class="form-label">
323
+ <i class="bi bi-flower3"></i> Select Crop
324
+ </label>
325
+ <select class="form-select" id="crop" name="crop" required>
326
+ <option value="">Choose your crop...</option>
327
+ {% for crop in crops %}
328
+ <option value="{{ crop }}">{{ crop }}</option>
329
+ {% endfor %}
330
+ </select>
331
+ </div>
332
+
333
+ <div class="form-group">
334
+ <label for="production" class="form-label">
335
+ <i class="bi bi-box-seam"></i> Production (in quintals)
336
+ </label>
337
+ <input type="number" class="form-control" id="production" name="production" min="0" placeholder="Enter production quantity" required>
338
+ </div>
339
+
340
+ <button type="submit" class="btn-primary-action">
341
+ <i class="bi bi-calculator"></i>
342
+ Predict Price
343
+ </button>
344
+ </form>
345
+
346
+ <!-- Result Box -->
347
+ <div id="result" class="result-box">
348
+ <h4>
349
+ <i class="bi bi-check-circle-fill"></i>
350
+ Predicted Price
351
+ </h4>
352
+ <div class="result-price">
353
+ ₹<span id="predicted-price"></span>
354
+ </div>
355
+ <p style="text-align: center; margin-top: 0.5rem; opacity: 0.9;">per quintal</p>
356
+ </div>
357
+ </div>
358
+
359
+ <!-- Image Section -->
360
+ <div class="col-lg-5">
361
+ <div class="image-preview">
362
+ <img src="static/images/img.png" alt="Agricultural Crops">
363
+ </div>
364
+ </div>
365
+ </div>
366
+ </div>
367
+ </div>
368
+
369
+ <!-- Bootstrap JS -->
370
+ <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
371
+
372
+ <script>
373
+ $(document).ready(function () {
374
+ // Handle state selection to populate districts
375
+ $('#state').on('change', function () {
376
+ const state = $(this).val();
377
+ if (state) {
378
+ $.ajax({
379
+ type: 'POST',
380
+ url: '/districts',
381
+ data: { state: state },
382
+ success: function (response) {
383
+ $('#district').empty();
384
+ $('#district').append('<option value="">Choose your district...</option>');
385
+ response.districts.forEach(function (district) {
386
+ $('#district').append('<option value="' + district + '">' + district + '</option>');
387
+ });
388
+ },
389
+ error: function() {
390
+ alert('Error loading districts. Please try again.');
391
+ }
392
+ });
393
+ } else {
394
+ $('#district').empty();
395
+ $('#district').append('<option value="">Choose your district...</option>');
396
+ }
397
+ });
398
+
399
+ // Handle form submission
400
+ $('#prediction-form').on('submit', function (e) {
401
+ e.preventDefault();
402
+
403
+ // Show loading state
404
+ const submitBtn = $(this).find('button[type="submit"]');
405
+ const originalText = submitBtn.html();
406
+ submitBtn.html('<i class="bi bi-hourglass-split"></i> Calculating...');
407
+ submitBtn.prop('disabled', true);
408
+
409
+ $.ajax({
410
+ type: 'POST',
411
+ url: '/predict',
412
+ data: $(this).serialize(),
413
+ success: function (response) {
414
+ $('#predicted-price').text(response.predicted_price.toFixed(2));
415
+ $('#result').slideDown(400);
416
+
417
+ // Scroll to result
418
+ $('html, body').animate({
419
+ scrollTop: $('#result').offset().top - 100
420
+ }, 500);
421
+
422
+ // Reset button
423
+ submitBtn.html(originalText);
424
+ submitBtn.prop('disabled', false);
425
+ },
426
+ error: function() {
427
+ alert('Error predicting price. Please check your inputs and try again.');
428
+ submitBtn.html(originalText);
429
+ submitBtn.prop('disabled', false);
430
+ }
431
+ });
432
+ });
433
+ });
434
+ </script>
435
+ </body>
436
+ </html>