ZENLLC commited on
Commit
9444004
·
verified ·
1 Parent(s): 70b9de8

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +58 -26
app.py CHANGED
@@ -1,20 +1,23 @@
1
  import cv2
2
  import numpy as np
3
- from PIL import Image, ImageDraw
4
  import gradio as gr
5
 
6
- def detect_cracks(image: Image.Image) -> Image.Image:
7
  try:
8
- # Convert PIL image to an OpenCV image (BGR format)
9
- cv_image = cv2.cvtColor(np.array(image), cv2.COLOR_RGB2BGR)
 
 
 
10
 
11
- # Convert to grayscale for processing
12
- gray = cv2.cvtColor(cv_image, cv2.COLOR_BGR2GRAY)
13
 
14
- # Apply Gaussian blur to reduce noise and enhance edges
15
  blurred = cv2.GaussianBlur(gray, (5, 5), 0)
16
 
17
- # Use adaptive thresholding to highlight potential crack areas
18
  thresh = cv2.adaptiveThreshold(
19
  blurred, 255,
20
  cv2.ADAPTIVE_THRESH_GAUSSIAN_C,
@@ -22,41 +25,70 @@ def detect_cracks(image: Image.Image) -> Image.Image:
22
  11, 2
23
  )
24
 
25
- # Apply morphological closing to bridge gaps in detected lines
26
  kernel = np.ones((3, 3), np.uint8)
27
  morph = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel, iterations=2)
28
 
29
- # Detect edges with Canny edge detector
30
  edges = cv2.Canny(morph, 50, 150)
31
 
32
- # Find contours based on the detected edges
33
  contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
34
 
35
- # Convert original image to PIL for drawing
36
- annotated = image.copy()
37
- draw = ImageDraw.Draw(annotated)
38
 
39
- # Draw bounding boxes around contours that are large enough to be meaningful cracks
40
  for cnt in contours:
41
- # Filter out noise with a minimum arc length threshold (adjustable)
42
  if cv2.arcLength(cnt, True) > 100:
43
  x, y, w, h = cv2.boundingRect(cnt)
44
- draw.rectangle([x, y, x + w, y + h], outline="red", width=2)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
45
 
46
- return annotated
47
  except Exception as e:
48
- print("Error during crack detection:", e)
49
- return image # Fallback: return the original image if any error occurs
50
 
51
- # Create a Gradio interface for the Space
52
  iface = gr.Interface(
53
  fn=detect_cracks,
54
- inputs=gr.Image(type="pil", label="Upload a Floor/Wall Image"),
55
- outputs=gr.Image(label="Detected Cracks"),
56
- title="Home Inspection: Crack Detection",
57
  description=(
58
- "Upload an image of a floor or wall to detect cracks and other defects. "
59
- "This demo uses traditional computer vision techniques to highlight potential issues."
 
60
  )
61
  )
62
 
 
1
  import cv2
2
  import numpy as np
3
+ from PIL import Image, ImageDraw, ImageFont
4
  import gradio as gr
5
 
6
+ def detect_cracks(image: Image.Image):
7
  try:
8
+ # Convert the PIL image to an OpenCV (RGB) image
9
+ rgb_image = np.array(image)
10
+ # Also create a copy for annotation
11
+ annotated = image.copy()
12
+ draw = ImageDraw.Draw(annotated)
13
 
14
+ # Convert to grayscale
15
+ gray = cv2.cvtColor(rgb_image, cv2.COLOR_RGB2GRAY)
16
 
17
+ # Apply Gaussian blur to reduce noise
18
  blurred = cv2.GaussianBlur(gray, (5, 5), 0)
19
 
20
+ # Adaptive thresholding to highlight crack-like features
21
  thresh = cv2.adaptiveThreshold(
22
  blurred, 255,
23
  cv2.ADAPTIVE_THRESH_GAUSSIAN_C,
 
25
  11, 2
26
  )
27
 
28
+ # Use morphological closing to fill gaps in potential cracks
29
  kernel = np.ones((3, 3), np.uint8)
30
  morph = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel, iterations=2)
31
 
32
+ # Edge detection
33
  edges = cv2.Canny(morph, 50, 150)
34
 
35
+ # Find contours from edges
36
  contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
37
 
38
+ detections = [] # to hold detection details
 
 
39
 
 
40
  for cnt in contours:
41
+ # Filter out small contours (noise)
42
  if cv2.arcLength(cnt, True) > 100:
43
  x, y, w, h = cv2.boundingRect(cnt)
44
+
45
+ # Extract ROI from the original image (for material classification)
46
+ roi = rgb_image[y:y+h, x:x+w]
47
+ if roi.size == 0:
48
+ continue
49
+ # Convert ROI to grayscale and compute mean intensity
50
+ roi_gray = cv2.cvtColor(roi, cv2.COLOR_RGB2GRAY)
51
+ mean_intensity = np.mean(roi_gray)
52
+
53
+ # Simple heuristic: classify material based on brightness
54
+ # (These thresholds are arbitrary and should be tuned based on real data.)
55
+ if mean_intensity < 80:
56
+ material = "Concrete"
57
+ elif mean_intensity < 150:
58
+ material = "Tile"
59
+ else:
60
+ material = "Wood"
61
+
62
+ label = f"Crack ({material})"
63
+ detections.append(f"Detected crack at ({x}, {y}, {w}, {h}) on {material} (mean intensity: {mean_intensity:.1f})")
64
+
65
+ # Draw rectangle and label on the annotated image
66
+ draw.rectangle([x, y, x+w, y+h], outline="red", width=2)
67
+ # Draw the label above the rectangle
68
+ draw.text((x, y-10), label, fill="red")
69
+
70
+ # Create a text summary of detections
71
+ if detections:
72
+ summary = "\n".join(detections)
73
+ else:
74
+ summary = "No significant cracks detected."
75
+
76
+ return annotated, summary
77
 
 
78
  except Exception as e:
79
+ print("Error during detection:", e)
80
+ return image, f"Error: {e}"
81
 
82
+ # Create a Gradio interface with two outputs: image and text
83
  iface = gr.Interface(
84
  fn=detect_cracks,
85
+ inputs=gr.Image(type="pil", label="Upload an Image (Floor/Wall)"),
86
+ outputs=[gr.Image(label="Annotated Image"), gr.Textbox(label="Detection Summary")],
87
+ title="Home Inspection: Granular Crack & Material Detector",
88
  description=(
89
+ "Upload an image of a floor or wall to detect cracks and infer the underlying material "
90
+ "(Concrete, Tile, or Wood) using classical computer vision techniques. "
91
+ "This demo returns both an annotated image and a textual summary."
92
  )
93
  )
94