Views / app.py
ZENLLC's picture
Update app.py
9444004 verified
raw
history blame
3.73 kB
import cv2
import numpy as np
from PIL import Image, ImageDraw, ImageFont
import gradio as gr
def detect_cracks(image: Image.Image):
try:
# Convert the PIL image to an OpenCV (RGB) image
rgb_image = np.array(image)
# Also create a copy for annotation
annotated = image.copy()
draw = ImageDraw.Draw(annotated)
# Convert to grayscale
gray = cv2.cvtColor(rgb_image, cv2.COLOR_RGB2GRAY)
# Apply Gaussian blur to reduce noise
blurred = cv2.GaussianBlur(gray, (5, 5), 0)
# Adaptive thresholding to highlight crack-like features
thresh = cv2.adaptiveThreshold(
blurred, 255,
cv2.ADAPTIVE_THRESH_GAUSSIAN_C,
cv2.THRESH_BINARY_INV,
11, 2
)
# Use morphological closing to fill gaps in potential cracks
kernel = np.ones((3, 3), np.uint8)
morph = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel, iterations=2)
# Edge detection
edges = cv2.Canny(morph, 50, 150)
# Find contours from edges
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
detections = [] # to hold detection details
for cnt in contours:
# Filter out small contours (noise)
if cv2.arcLength(cnt, True) > 100:
x, y, w, h = cv2.boundingRect(cnt)
# Extract ROI from the original image (for material classification)
roi = rgb_image[y:y+h, x:x+w]
if roi.size == 0:
continue
# Convert ROI to grayscale and compute mean intensity
roi_gray = cv2.cvtColor(roi, cv2.COLOR_RGB2GRAY)
mean_intensity = np.mean(roi_gray)
# Simple heuristic: classify material based on brightness
# (These thresholds are arbitrary and should be tuned based on real data.)
if mean_intensity < 80:
material = "Concrete"
elif mean_intensity < 150:
material = "Tile"
else:
material = "Wood"
label = f"Crack ({material})"
detections.append(f"Detected crack at ({x}, {y}, {w}, {h}) on {material} (mean intensity: {mean_intensity:.1f})")
# Draw rectangle and label on the annotated image
draw.rectangle([x, y, x+w, y+h], outline="red", width=2)
# Draw the label above the rectangle
draw.text((x, y-10), label, fill="red")
# Create a text summary of detections
if detections:
summary = "\n".join(detections)
else:
summary = "No significant cracks detected."
return annotated, summary
except Exception as e:
print("Error during detection:", e)
return image, f"Error: {e}"
# Create a Gradio interface with two outputs: image and text
iface = gr.Interface(
fn=detect_cracks,
inputs=gr.Image(type="pil", label="Upload an Image (Floor/Wall)"),
outputs=[gr.Image(label="Annotated Image"), gr.Textbox(label="Detection Summary")],
title="Home Inspection: Granular Crack & Material Detector",
description=(
"Upload an image of a floor or wall to detect cracks and infer the underlying material "
"(Concrete, Tile, or Wood) using classical computer vision techniques. "
"This demo returns both an annotated image and a textual summary."
)
)
if __name__ == "__main__":
iface.launch()