Pratikd-110924's picture
Update app.py
a99deac verified
Raw
History Blame Contribute Delete
12.4 kB
import os
# CHANGE 1: Move this to the very top, BEFORE importing torch
os.environ["CUDA_VISIBLE_DEVICES"] = "-1"
from flask import Flask, request, render_template, redirect, url_for, jsonify
from werkzeug.utils import secure_filename
from PIL import Image
import torch
import torch.nn as nn
import torchvision.transforms as transforms
from torchvision.utils import save_image
from io import BytesIO
import cv2
import numpy as np
# Flask app initialization
app = Flask(__name__)
# CHANGE 2: Force device to CPU (Do not check for CUDA)
device = torch.device("cpu")
# Attention Mechanism
class AttentionBlock(nn.Module):
def __init__(self, in_channels):
super(AttentionBlock, self).__init__()
self.query_conv = nn.Conv2d(in_channels, in_channels // 8, kernel_size=1)
self.key_conv = nn.Conv2d(in_channels, in_channels // 8, kernel_size=1)
self.value_conv = nn.Conv2d(in_channels, in_channels, kernel_size=1)
self.gamma = nn.Parameter(torch.zeros(1))
def forward(self, x):
batch_size, C, height, width = x.size()
query = self.query_conv(x).view(batch_size, -1, height * width)
key = self.key_conv(x).view(batch_size, -1, height * width)
value = self.value_conv(x).view(batch_size, -1, height * width)
energy = torch.bmm(query.permute(0, 2, 1), key) # BxNqxNk
attention = torch.softmax(energy, dim=-1) # BxNq x Nk
out = torch.bmm(value, attention.permute(0, 2, 1)) # BxNc x Nq
out = out.view(batch_size, C, height, width)
out = self.gamma * out + x
return out
# Encoder and Decoder Blocks
class Encoder(nn.Module):
def __init__(self, input_nc):
super(Encoder, self).__init__()
self.encoder = nn.Sequential(
nn.Conv2d(input_nc, 64, kernel_size=7, stride=1, padding=3),
nn.InstanceNorm2d(64),
nn.ReLU(inplace=True),
nn.Conv2d(64, 128, kernel_size=3, stride=2, padding=1),
nn.InstanceNorm2d(128),
nn.ReLU(inplace=True),
nn.Conv2d(128, 256, kernel_size=3, stride=2, padding=1),
nn.InstanceNorm2d(256),
nn.ReLU(inplace=True),
)
def forward(self, x):
return self.encoder(x)
class Decoder(nn.Module):
def __init__(self, output_nc):
super(Decoder, self).__init__()
self.decoder = nn.Sequential(
nn.ConvTranspose2d(256, 128, kernel_size=3, stride=2, padding=1, output_padding=1),
nn.InstanceNorm2d(128),
nn.ReLU(inplace=True),
nn.ConvTranspose2d(128, 64, kernel_size=3, stride=2, padding=1, output_padding=1),
nn.InstanceNorm2d(64),
nn.ReLU(inplace=True),
nn.Conv2d(64, output_nc, kernel_size=7, stride=1, padding=3),
nn.Tanh()
)
def forward(self, x):
return self.decoder(x)
# Generator definition (combining Encoder, Attention, and Decoder)
class Generator(nn.Module):
def __init__(self, input_nc, output_nc):
super(Generator, self).__init__()
self.encoder = Encoder(input_nc)
self.attention = AttentionBlock(256)
self.decoder = Decoder(output_nc)
def forward(self, x):
x = self.encoder(x)
x = self.attention(x)
x = self.decoder(x)
return x
# Initialize the Generator
# CHANGE 3: Ensure model is explicitly moved to CPU after loading
G1 = Generator(input_nc=1, output_nc=3).to(device)
import os
G1.load_state_dict(torch.load(os.path.join("weights", "best_G1.pth"), map_location=device))
G1.to(device) # Double check to ensure it stays on CPU
G1.eval()
# Image transformation pipeline
transform = transforms.Compose([
transforms.Resize((256, 256)),
transforms.ToTensor(),
transforms.Normalize((0.5,), (0.5,)),
])
# Sliding Window function
def sliding_window_colorization(input_image, model, patch_size=64, overlap=32):
img_width, img_height = input_image.size
patches = []
# Slide window over the image and process each patch
for y in range(0, img_height - patch_size + 1, patch_size - overlap):
for x in range(0, img_width - patch_size + 1, patch_size - overlap):
patch = input_image.crop((x, y, x + patch_size, y + patch_size))
patch = transform(patch).unsqueeze(0).to(device)
# Generate colorized patch
with torch.no_grad():
colorized_patch = model(patch)
patches.append((x, y, colorized_patch))
# Handle rightmost edge (if necessary)
if img_width % patch_size != 0:
x = img_width - patch_size
for y in range(0, img_height - patch_size + 1, patch_size - overlap):
patch = input_image.crop((x, y, x + patch_size, y + patch_size))
patch = transform(patch).unsqueeze(0).to(device)
with torch.no_grad():
colorized_patch = model(patch)
patches.append((x, y, colorized_patch))
if img_height % patch_size != 0:
y = img_height - patch_size
for x in range(0, img_width - patch_size + 1, patch_size - overlap):
patch = input_image.crop((x, y, x + patch_size, y + patch_size))
patch = transform(patch).unsqueeze(0).to(device)
with torch.no_grad():
colorized_patch = model(patch)
patches.append((x, y, colorized_patch))
# Combine the patches into a single image
output_image = torch.zeros((1, 3, img_height, img_width), device=device)
count_map = torch.zeros((1, 3, img_height, img_width), device=device)
for (x, y, colorized_patch) in patches:
output_image[:, :, y:y + patch_size, x:x + patch_size] += colorized_patch
count_map[:, :, y:y + patch_size, x:x + patch_size] += 1
output_image /= count_map
return output_image
# Helper function to calculate greenery rate
def calculate_greenery_rate(image_path):
# Read the image
image = cv2.imread(image_path)
if image is None:
raise FileNotFoundError(f"Image not found at path: {image_path}")
# Convert the image from BGR to HSV color space
hsv_image = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
# Define the HSV range for detecting greenery
lower_green = np.array([30, 40, 40]) # lower bound
upper_green = np.array([90, 255, 255]) # higher bound
# Create a binary mask where green colors are in range
green_mask = cv2.inRange(hsv_image, lower_green, upper_green)
# Calculate the number of green pixels
green_pixel_count = np.sum(green_mask > 0)
# Calculate the total number of pixels in the image
total_pixel_count = image.shape[0] * image.shape[1]
# Calculate the greenery rate
greenery_rate = (green_pixel_count / total_pixel_count) * 100
return greenery_rate
# Flask routes
@app.route('/')
def index():
return render_template('index.html')
@app.route('/upload', methods=['POST'])
def upload_image():
if 'file' not in request.files:
return "No file part"
file = request.files['file']
if file.filename == '':
return "No selected file"
if file:
uploaded_image_path = os.path.join("static", "uploaded_image.png")
file.save(uploaded_image_path)
# Process the SAR image
image = Image.open(uploaded_image_path).convert("L") # Convert to grayscale
# Apply sliding window colorization
colorized_image = sliding_window_colorization(image, G1, patch_size=256, overlap=32)
# Denormalize and save the colorized image
colorized_image = colorized_image * 0.5 + 0.5 # Denormalize
colorized_image_path = os.path.join("static", "colorized_image.png")
save_image(colorized_image, colorized_image_path)
# Calculate greenery rate
greenery_rate = calculate_greenery_rate(colorized_image_path)
return render_template(
'result.html',
uploaded_image_url="/static/uploaded_image.png",
colorized_image_url="/static/colorized_image.png",
greenery_rate=f"{greenery_rate:.2f}%"
)
# Folder to save uploaded images
UPLOAD_FOLDER = 'static/uploads'
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
@app.route('/greenery', methods=['GET'])
def greenery_rate_page():
return render_template('greenery.html')
@app.route('/greenery-upload', methods=['POST'])
def greenery_upload():
if 'file' not in request.files:
return redirect(request.url)
file = request.files['file']
if file.filename == '':
return redirect(request.url)
if file:
# Save the file
filename = secure_filename(file.filename)
filepath = os.path.join(app.config['UPLOAD_FOLDER'], filename)
file.save(filepath)
# Dummy greenery rate calculation (replace with your logic)
greenery_rate = calculate_greenery_rate(filepath)
# Pass the image URL and greenery rate to the template
uploaded_image_url = url_for('static', filename=f'uploads/{filename}')
return render_template('greenery.html', uploaded_image_url=uploaded_image_url, greenery_rate=f"{greenery_rate:.2f}%")
# Predefined chatbot data
faq_data = [
{
"question": "What is SAR?",
"keywords": ["sar", "what"],
"response": "SAR stands for Synthetic Aperture Radar. It is a type of radar used to create two-dimensional images or three-dimensional reconstructions of objects.",
},
{
"question": "Advantages of SAR",
"keywords": ["advantages", "sar"],
"response": "Advantages of SAR include all-weather imaging, ability to penetrate clouds and darkness, and high-resolution imaging over large areas.",
},
{
"question": "Disadvantages of SAR",
"keywords": ["disadvantages", "sar", "cons"],
"response": "Disadvantages of SAR include high operational costs, susceptibility to speckle noise, and complexity in data interpretation.",
},
{
"question": "Applications of SAR",
"keywords": ["applications", "sar", "usage"],
"response": "Applications of SAR include disaster management, environmental monitoring, urban planning, agriculture, and military surveillance.",
},
{
"question": "SAR Image Colorization",
"keywords": ["sar", "colorization"],
"response": "SAR image colorization involves using algorithms or deep learning models to add colors to grayscale SAR images for better visual interpretation.",
},
{
"question": "Limitations of SAR",
"keywords": ["limitations", "sar"],
"response": "Limitations of SAR include difficulty in interpretation due to speckle noise and high computational costs for processing.",
},
{
"question": "Pros and Cons of SAR",
"keywords": ["pros", "cons", "sar"],
"response": "Pros of SAR include all-weather capability, cloud penetration, and high-resolution imaging. Cons include high costs, noise, and complexity in interpretation.",
},
{
"question": "Components of a SAR system",
"keywords": ["components", "sar", "system"],
"response": "A SAR system typically consists of a radar antenna, transmitter, receiver, signal processor, and platform (airborne or satellite-based).",
},
{
"question": "SAR for disaster management",
"keywords": ["sar", "disaster", "management"],
"response": "SAR is used in disaster management for monitoring floods, landslides, and earthquakes, providing timely information for relief and recovery operations.",
},
]
@app.route('/chatbot')
def chatbot():
return render_template('chatbot.html')
@app.route('/chatbot/ask', methods=['POST'])
def chatbot_ask():
user_question = request.json.get('question', '').lower()
# Scoring mechanism for relevance
best_match = None
max_score = 0
for entry in faq_data:
score = sum(keyword in user_question for keyword in entry["keywords"])
if score > max_score:
best_match = entry
max_score = score
# Return the best match response if found, otherwise a default message
response = best_match["response"] if best_match else "Sorry, I couldn't find an answer to your question."
return jsonify({'response': response})
if __name__ == '__main__':
app.run(debug=True)