rana1926 commited on
Commit
afdcc28
·
verified ·
1 Parent(s): ce6aafd

Upload 4 files

Browse files
.gitattributes CHANGED
@@ -34,3 +34,4 @@ saved_model/**/* 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
  app/models/SatCoverClassifier.keras 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
  app/models/SatCoverClassifier.keras filter=lfs diff=lfs merge=lfs -text
37
+ models/SatCoverClassifier.keras filter=lfs diff=lfs merge=lfs -text
app.py ADDED
@@ -0,0 +1,67 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import numpy as np
3
+ import cv2
4
+ import tensorflow as tf
5
+ from flask import Flask, request, render_template, jsonify
6
+ from tensorflow.keras.models import load_model
7
+
8
+ app = Flask(__name__)
9
+
10
+ # Load the trained model
11
+ MODEL_PATH = os.path.join('models', 'SatCoverClassifier.keras')
12
+ model = load_model(MODEL_PATH)
13
+
14
+ class_mapping = {
15
+ 0: 'AnnualCrop', 1: 'Forest', 2: 'HerbaceousVegetation',
16
+ 3: 'Highway', 4: 'Industrial', 5: 'Pasture',
17
+ 6: 'PermanentCrop', 7: 'Residential', 8: 'River',
18
+ 9: 'SeaLake'
19
+ }
20
+
21
+ @app.route('/')
22
+ def index():
23
+ return render_template('index.html')
24
+
25
+ @app.route('/predict', methods=['POST'])
26
+ def predict():
27
+ if 'file' not in request.files:
28
+ return jsonify({'error': 'No file part'})
29
+
30
+ file = request.files['file']
31
+ if file.filename == '':
32
+ return jsonify({'error': 'No selected file'})
33
+
34
+ # Read and preprocess the image
35
+ img_bytes = file.read()
36
+ nparr = np.frombuffer(img_bytes, np.uint8)
37
+ img = cv2.imdecode(nparr, cv2.IMREAD_COLOR)
38
+ img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
39
+
40
+ # Resize to match model input
41
+ resized_img = tf.image.resize(img_rgb, (64, 64))
42
+
43
+ # Normalize and expand dims for batch
44
+ normalized_img = resized_img / 255.0
45
+ input_data = np.expand_dims(normalized_img, 0)
46
+
47
+ # Make prediction
48
+ predictions = model.predict(input_data)
49
+
50
+ # Get top 3 predictions
51
+ top3_indices = np.argsort(predictions[0])[-3:][::-1]
52
+ results = []
53
+
54
+ for idx in top3_indices:
55
+ results.append({
56
+ 'class': class_mapping[idx],
57
+ 'confidence': float(predictions[0][idx] * 100)
58
+ })
59
+
60
+ return jsonify({
61
+ 'prediction': results[0]['class'],
62
+ 'confidence': results[0]['confidence'],
63
+ 'top3': results
64
+ })
65
+
66
+ if __name__ == '__main__':
67
+ app.run(debug=True)
models/SatCoverClassifier.keras ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:c8555ae35fa182f3630d202f68885c3389f639510736ec2445c16643711541e3
3
+ size 26390483
requirements.txt CHANGED
@@ -1,4 +1,144 @@
1
- Flask==2.0.1
2
- Werkzeug==2.0.1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3
  opencv-python==4.11.0.86
4
- numpy==1.26.4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ absl-py==2.2.2
2
+ affine==2.4.0
3
+ anyio==4.9.0
4
+ appnope==0.1.4
5
+ argon2-cffi==23.1.0
6
+ argon2-cffi-bindings==21.2.0
7
+ arrow==1.3.0
8
+ asttokens==3.0.0
9
+ astunparse==1.6.3
10
+ async-lru==2.0.5
11
+ attrs==25.3.0
12
+ babel==2.17.0
13
+ beautifulsoup4==4.13.4
14
+ bleach==6.2.0
15
+ blinker==1.9.0
16
+ certifi==2025.1.31
17
+ cffi==1.17.1
18
+ charset-normalizer==3.4.1
19
+ click==8.1.8
20
+ click-plugins==1.1.1
21
+ cligj==0.7.2
22
+ comm==0.2.2
23
+ contourpy==1.3.2
24
+ cycler==0.12.1
25
+ debugpy==1.8.14
26
+ decorator==5.2.1
27
+ defusedxml==0.7.1
28
+ exceptiongroup==1.2.2
29
+ executing==2.2.0
30
+ fastjsonschema==2.21.1
31
+ Flask==3.1.0
32
+ flatbuffers==25.2.10
33
+ fonttools==4.57.0
34
+ fqdn==1.5.1
35
+ gast==0.6.0
36
+ google-pasta==0.2.0
37
+ grpcio==1.71.0
38
+ h11==0.16.0
39
+ h5py==3.13.0
40
+ httpcore==1.0.9
41
+ httpx==0.28.1
42
+ idna==3.10
43
+ ipykernel==6.29.5
44
+ ipython==8.35.0
45
+ isoduration==20.11.0
46
+ itsdangerous==2.2.0
47
+ jedi==0.19.2
48
+ Jinja2==3.1.6
49
+ joblib==1.4.2
50
+ json5==0.12.0
51
+ jsonpointer==3.0.0
52
+ jsonschema==4.23.0
53
+ jsonschema-specifications==2025.4.1
54
+ jupyter-events==0.12.0
55
+ jupyter-lsp==2.2.5
56
+ jupyter_client==8.6.3
57
+ jupyter_core==5.7.2
58
+ jupyter_server==2.15.0
59
+ jupyter_server_terminals==0.5.3
60
+ jupyterlab==4.4.1
61
+ jupyterlab_pygments==0.3.0
62
+ jupyterlab_server==2.27.3
63
+ keras==3.9.2
64
+ kiwisolver==1.4.8
65
+ libclang==18.1.1
66
+ Markdown==3.8
67
+ markdown-it-py==3.0.0
68
+ MarkupSafe==3.0.2
69
+ matplotlib==3.10.1
70
+ matplotlib-inline==0.1.7
71
+ mdurl==0.1.2
72
+ mistune==3.1.3
73
+ ml-dtypes==0.3.2
74
+ namex==0.0.9
75
+ nbclient==0.10.2
76
+ nbconvert==7.16.6
77
+ nbformat==5.10.4
78
+ nest-asyncio==1.6.0
79
+ notebook_shim==0.2.4
80
+ numpy==1.26.4
81
  opencv-python==4.11.0.86
82
+ opt_einsum==3.4.0
83
+ optree==0.15.0
84
+ overrides==7.7.0
85
+ packaging==25.0
86
+ pandas==2.2.3
87
+ pandocfilters==1.5.1
88
+ parso==0.8.4
89
+ pexpect==4.9.0
90
+ pillow==11.2.1
91
+ platformdirs==4.3.7
92
+ prometheus_client==0.21.1
93
+ prompt_toolkit==3.0.51
94
+ protobuf==4.25.7
95
+ psutil==7.0.0
96
+ ptyprocess==0.7.0
97
+ pure_eval==0.2.3
98
+ pycparser==2.22
99
+ Pygments==2.19.1
100
+ pyngrok==7.2.5
101
+ pyparsing==3.2.3
102
+ python-dateutil==2.9.0.post0
103
+ python-json-logger==3.3.0
104
+ python-version==0.0.2
105
+ pytz==2025.2
106
+ PyYAML==6.0.2
107
+ pyzmq==26.4.0
108
+ rasterio==1.4.3
109
+ referencing==0.36.2
110
+ requests==2.32.3
111
+ rfc3339-validator==0.1.4
112
+ rfc3986-validator==0.1.1
113
+ rich==14.0.0
114
+ rpds-py==0.24.0
115
+ scikit-learn==1.6.1
116
+ scipy==1.15.2
117
+ Send2Trash==1.8.3
118
+ six==1.17.0
119
+ sniffio==1.3.1
120
+ soupsieve==2.7
121
+ stack-data==0.6.3
122
+ tensorboard==2.16.2
123
+ tensorboard-data-server==0.7.2
124
+ tensorflow==2.16.2
125
+ tensorflow-io-gcs-filesystem==0.37.1
126
+ termcolor==3.0.1
127
+ terminado==0.18.1
128
+ threadpoolctl==3.6.0
129
+ tinycss2==1.4.0
130
+ tomli==2.2.1
131
+ tornado==6.4.2
132
+ tqdm==4.67.1
133
+ traitlets==5.14.3
134
+ types-python-dateutil==2.9.0.20241206
135
+ typing_extensions==4.13.2
136
+ tzdata==2025.2
137
+ uri-template==1.3.0
138
+ urllib3==2.4.0
139
+ wcwidth==0.2.13
140
+ webcolors==24.11.1
141
+ webencodings==0.5.1
142
+ websocket-client==1.8.0
143
+ Werkzeug==3.1.3
144
+ wrapt==1.17.2
templates/index.html ADDED
@@ -0,0 +1,131 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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>Land Cover Classification</title>
7
+ <script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>
8
+ </head>
9
+ <body class="bg-slate-900 text-slate-50">
10
+ <div class="flex flex-col items-center justify-center gap-6 border-b-2 border-teal-700 p-4 ">
11
+ <h1 class="text-3xl">Land Cover Classifier</h1>
12
+ <p>Upload a satellite image to classify the land cover type</p>
13
+ </div>
14
+ <div class="flex items-start justify-center min-h-screen p-4 gap-8">
15
+ <div class="h-[40vh] flex items-center p-4">
16
+ <form id="upload-form" enctype="multipart/form-data" class="flex flex-col items-center gap-4">
17
+ <div class="cursor-pointer">
18
+ <label for="image-upload" class="bg-teal-700 px-4 py-2 rounded cursor-pointer">
19
+ Select Image
20
+ </label>
21
+ <input
22
+ type="file"
23
+ id="image-upload"
24
+ name="file"
25
+ accept="image/*"
26
+ class="hidden"
27
+ />
28
+ </div>
29
+ <button type="submit" class="bg-teal-700 px-4 py-2 rounded cursor-pointer">Classify Image</button>
30
+ </form>
31
+ </div>
32
+
33
+ <div class="min-h-[50vh] flex flex-col items-center justify-center gap-4">
34
+ <div id="preview-image" class="hidden">
35
+ <h3>Uploaded Image</h3>
36
+ <img src="#" alt="Preview" />
37
+ </div>
38
+ <div
39
+ class="hidden flex-col items-center justify-center gap-4"
40
+ id="results-container"
41
+ >
42
+ <div>
43
+ <h3>Prediction Results</h3>
44
+ <div>
45
+ <span id="main-class">Class</span>:
46
+ <span id="confidence">0%</span> confidence
47
+ </div>
48
+
49
+ <h4>Top 3 Predictions</h4>
50
+ <ul id="predictions-list"></ul>
51
+ </div>
52
+ </div>
53
+
54
+ <div class="hidden" id="loading">
55
+ <div class="w-12 h-12 border-4 border-teal-200 border-t-teal-700 rounded-full animate-spin mb-3 mx-auto"></div>
56
+ <p>Processing image...</p>
57
+ </div>
58
+ </div>
59
+ </div>
60
+
61
+ <script>
62
+ document.addEventListener("DOMContentLoaded", function () {
63
+ const form = document.getElementById("upload-form");
64
+ const imageUpload = document.getElementById("image-upload");
65
+ const previewImage = document.getElementById("preview-image");
66
+ const resultsContainer = document.getElementById("results-container");
67
+ const mainClass = document.getElementById("main-class");
68
+ const confidence = document.getElementById("confidence");
69
+ const predictionsList = document.getElementById("predictions-list");
70
+ const loadingIndicator = document.getElementById("loading");
71
+
72
+ // Preview the selected image
73
+ imageUpload.addEventListener("change", function () {
74
+ const file = this.files[0];
75
+ if (file) {
76
+ const reader = new FileReader();
77
+ reader.onload = function (e) {
78
+ previewImage.getElementsByTagName('img')[0].src = e.target.result;
79
+ };
80
+ reader.readAsDataURL(file);
81
+ previewImage.classList.remove("hidden");
82
+ }
83
+ });
84
+
85
+ form.addEventListener("submit", function (e) {
86
+ e.preventDefault();
87
+
88
+ const formData = new FormData(this);
89
+
90
+ loadingIndicator.classList.remove("hidden");
91
+ loadingIndicator.classList.add("flex");
92
+ resultsContainer.classList.remove("hideen");
93
+
94
+ fetch("/predict", {
95
+ method: "POST",
96
+ body: formData,
97
+ })
98
+ .then((response) => response.json())
99
+ .then((data) => {
100
+ loadingIndicator.style.display = "none";
101
+
102
+ if (data.error) {
103
+ alert(data.error);
104
+ return;
105
+ }
106
+
107
+ mainClass.textContent = data.prediction;
108
+ confidence.textContent = data.confidence.toFixed(2) + "%";
109
+
110
+ predictionsList.innerHTML = "";
111
+
112
+ data.top3.forEach((pred) => {
113
+ const li = document.createElement("li");
114
+ li.textContent = `${pred.class}: ${pred.confidence.toFixed(
115
+ 2
116
+ )}%`;
117
+ predictionsList.appendChild(li);
118
+ });
119
+
120
+ resultsContainer.style.display = "flex";
121
+ })
122
+ .catch((error) => {
123
+ loadingIndicator.style.display = "none";
124
+ alert("Error processing the image. Please try again.");
125
+ console.error("Error:", error);
126
+ });
127
+ });
128
+ });
129
+ </script>
130
+ </body>
131
+ </html>