Repository navigation
Expand file tree
/
Copy pathapp.py
More file actions
146 lines (114 loc) · 4.93 KB
/
Copy pathapp.py
File metadata and controls
146 lines (114 loc) · 4.93 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
import os
import joblib
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from flask import Flask, render_template, request, jsonify
from werkzeug.utils import secure_filename
from spectral.io import envi
# Make a directory for uploads if it doesn't exist
script_dir = os.path.dirname(os.path.abspath(__file__))
# Build full path to the pkl files
model_path = os.path.join(script_dir, 'optimized_soil_carbon_model.pkl')
selector_path = os.path.join(script_dir, 'feature_selector.pkl')
# Load the files using full path
model = joblib.load(model_path)
selector = joblib.load(selector_path)
# Flask app setup
app = Flask(__name__)
app.config['UPLOAD_FOLDER'] = 'uploads'
# Ensure required folders exist
os.makedirs('uploads', exist_ok=True)
os.makedirs('static', exist_ok=True)
# Global variables to store map and image shape
org_c_map = None
rows, cols = 0, 0
# Allowed extensions
ALLOWED_EXTENSIONS_HDR = {'hdr'}
ALLOWED_EXTENSIONS_BIN = {'bin'}
# Function to check allowed file extensions
def allowed_file(filename, allowed_ext):
return '.' in filename and filename.rsplit('.', 1)[1].lower() in allowed_ext
# Function to add spectral indices
def add_spectral_indices(X):
df = X.copy()
if 'W700' in df.columns and 'W1700' in df.columns:
df['NDI_700_1700'] = (df['W700'] - df['W1700']) / (df['W700'] + df['W1700'])
if 'W600' in df.columns and 'W2100' in df.columns:
df['SR_600_2100'] = df['W600'] / df['W2100']
if 'W2200' in df.columns:
df['CR_2200'] = df['W2200'] / (0.5 * (df.get('W2100', 1) + df.get('W2300', 1)))
return df
@app.route('/', methods=['GET', 'POST'])
def index():
global org_c_map, rows, cols
value = None
error = None
if request.method == 'POST':
# Get uploaded files
hdr_file = request.files['hdr_file']
bin_file = request.files['bin_file']
# Check extensions
if not (allowed_file(hdr_file.filename, ALLOWED_EXTENSIONS_HDR) and
allowed_file(bin_file.filename, ALLOWED_EXTENSIONS_BIN)):
error = "Invalid file type! Please upload a valid .hdr file and .bin file."
return render_template('index.html', rows=rows, cols=cols, value=value, error=error)
# Secure filenames
hdr_filename = secure_filename(hdr_file.filename)
bin_filename = secure_filename(bin_file.filename)
# Save files
hdr_path = os.path.join(app.config['UPLOAD_FOLDER'], hdr_filename)
bin_path = os.path.join(app.config['UPLOAD_FOLDER'], bin_filename)
hdr_file.save(hdr_path)
bin_file.save(bin_path)
try:
# Load image
img = envi.open(hdr_path, bin_path)
cube = img.load() # shape: (rows, cols, bands)
# Get wavelengths
wavelengths = img.metadata.get("wavelength")
wavelengths = [float(w) for w in wavelengths]
# Prepare data
rows, cols, bands = cube.shape
pixel_data = cube.reshape(-1, bands)
band_names = [f"W{int(w)}" for w in wavelengths]
pixel_df = pd.DataFrame(pixel_data, columns=band_names)
# Add spectral indices
pixel_df = add_spectral_indices(pixel_df)
# Select features
selected_columns = selector.get_support(indices=True)
selected_features = pixel_df.columns[selected_columns]
X_selected = pixel_df[selected_features]
# Predict
y_pred_flat = model.predict(X_selected)
org_c_map = y_pred_flat.reshape(rows, cols)
# Save map image
plt.figure(figsize=(10, 6))
plt.imshow(org_c_map, cmap='YlGn', interpolation='none')
plt.title("Predicted Soil Organic Carbon Map")
plt.colorbar(label='Org C (%)')
plt.axis('off')
plt.savefig('static/output_map.png')
plt.close()
except Exception as e:
# Clear previous map and dimensions
org_c_map = None
rows, cols = 0, 0
error = f"An error occurred while processing the image: {e}"
return render_template('index.html', rows=rows, cols=cols, value=value, error=error)
return render_template('index.html', rows=rows, cols=cols, value=value, error=error)
@app.route('/get_value', methods=['POST'])
def get_value():
global org_c_map, rows, cols
# Get requested row/col
row = int(request.form['row'])
col = int(request.form['col'])
# Clip values to valid range
row = max(0, min(row, rows - 1))
col = max(0, min(col, cols - 1))
# Get value
value = org_c_map[row, col] if org_c_map is not None else None
# Re-render index with value shown
return jsonify({'value': f"{value:.3f} %" if value is not None else "N/A"})
if __name__ == '__main__':
app.run(debug=True)