trttung1610's picture
Update app.py
b812372
import gradio as gr
from PIL import Image
import torch
import torchvision.models as models
import torchvision.transforms as transforms
import cv2
import numpy as np
import openpyxl
import os
from tkinter import filedialog
# Load the pre-trained EfficientNet-B7 model
model = models.efficientnet_b7(pretrained=True)
model.eval()
# Define the transformations to be applied to the input image
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406],
std=[0.229, 0.224, 0.225])
])
def predict_house_area(room_id, excel_file, image_files):
total_area_sqm = 0
predicted_areas = []
# Check if the excel_file is provided
if excel_file is not None:
# Load the existing Excel workbook
workbook = openpyxl.load_workbook(excel_file.name)
worksheet = workbook.active
else:
# Create a new Excel workbook
workbook = openpyxl.Workbook()
worksheet = workbook.active
# Write the headers to the worksheet
worksheet.cell(row=1, column=1).value = "Room ID"
worksheet.cell(row=1, column=2).value = "Image File"
worksheet.cell(row=1, column=3).value = "Predicted Area (sqm)"
# Get the last row index to append new data
last_row_index = worksheet.max_row if worksheet.max_row else 1
# Loop over all the images
for i, image_file in enumerate(image_files):
# Load the input image
img = Image.open(image_file.name)
# Extract the image file name from the path
image_file_name = os.path.basename(image_file.name)
# Check if the image is PNG and convert to JPEG if it is
if img.format == "PNG":
# Convert the image to RGB format
img = img.convert("RGB")
# Apply the transformations to the input image
img_transformed = transform(img)
# Add a batch dimension to the transformed image tensor
img_transformed_batch = torch.unsqueeze(img_transformed, 0)
# Use the pre-trained model to make a prediction on the input image
with torch.no_grad():
output = model(img_transformed_batch)
# Convert the output tensor to a probability distribution using softmax
softmax = torch.nn.Softmax(dim=1)
output_probs = softmax(output)
# Extract the predicted class (house square footage) from the output probabilities
predicted_class = torch.argmax(output_probs)
# Calculate the predicted area based on the predicted class
predicted_area_sqm = 0
if predicted_class in [861, 648, 594, 894, 799, 896, 454]:
# Convert to grayscale and apply adaptive thresholding
gray = cv2.cvtColor(np.array(img), cv2.COLOR_RGB2GRAY)
gray = cv2.GaussianBlur(gray, (5, 5), 0)
mask = cv2.adaptiveThreshold(gray, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY_INV, 11, 2)
# Apply Canny edge detection to the binary mask
edges = cv2.Canny(mask, 30, 100)
# Apply dilation to fill gaps in the contour
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))
dilated = cv2.dilate(edges, kernel, iterations=2)
eroded = cv2.erode(dilated, kernel, iterations=1)
# Find contours in binary mask
contours, _ = cv2.findContours(eroded, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
# Find largest contour and calculate area
max_area = 0
for c in contours:
area = cv2.contourArea(c)
if area > max_area:
max_area = area
# Convert pixel area to square meters
pixels_per_meter = 300 # adjust this value based on your image resolution and actual room dimensions
predicted_area_sqm = (max_area + 10) / (2 * pixels_per_meter ** 2)
else:
predicted_area_sqft = predicted_class.item()
predicted_area_sqm = predicted_area_sqft * 0.092903 / 4.2
# Add the predicted area to the sum
total_area_sqm += predicted_area_sqm
# Add the predicted area to the list of predicted areas
predicted_areas.append(predicted_area_sqm)
# Write the room ID, image file name, and predicted area to the worksheet
worksheet.cell(row=last_row_index + i + 1, column=1).value = room_id
worksheet.cell(row=last_row_index + i + 1, column=2).value = image_file_name
worksheet.cell(row=last_row_index + i + 1, column=3).value = predicted_area_sqm
# Save the workbook to a temporary file
temp_file = "predicted_areas.xlsx"
workbook.save(temp_file)
return f"Sum of predicted house square footage: {total_area_sqm:.2f} square meters", temp_file
inputs = [
gr.inputs.Textbox(label = "Mã Phòng" , type = "text"),
gr.inputs.File(label="Excel File", type="file"),
gr.inputs.File(label="Images", type="file", file_count="multiple")
]
outputs = [
gr.outputs.Textbox(label="Sum of Predicted House Square Footage"),
gr.outputs.File(label="Excel Result")
]
interface = gr.Interface(
fn=predict_house_area,
inputs=inputs,
outputs=outputs,
title="House Predictor",
allow_flagging="never" # Disable flag button
)
if __name__ == "__main__":
interface.launch()