ZENLLC commited on
Commit
72d2178
·
verified ·
1 Parent(s): 9444004

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +65 -54
app.py CHANGED
@@ -1,23 +1,54 @@
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,70 +56,50 @@ def detect_cracks(image: Image.Image):
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
 
 
1
  import cv2
2
  import numpy as np
3
+ from PIL import Image, ImageDraw
4
  import gradio as gr
5
 
6
+ def classify_pipe_material(image_np):
7
+ """
8
+ Heuristic to classify the overall pipe material based on the image's brightness.
9
+ Assumes that plastic pipes tend to be brighter and metal pipes darker.
10
+ """
11
+ gray = cv2.cvtColor(image_np, cv2.COLOR_RGB2GRAY)
12
+ mean_intensity = np.mean(gray)
13
+ # If the mean intensity is high, assume plastic; otherwise, metal.
14
+ return "Plastic" if mean_intensity > 130 else "Metal"
15
+
16
+ def classify_defect(roi):
17
+ """
18
+ Heuristic to classify the defect type within a region of interest (ROI).
19
+ This simple method uses the area and intensity variation (std deviation)
20
+ to differentiate between a crack (typically long and thin with high contrast)
21
+ and corrosion (possibly larger, more blob-like with different texture).
22
+ """
23
+ area = roi.shape[0] * roi.shape[1]
24
+ std_intensity = np.std(roi)
25
+ # Adjust thresholds based on real-world testing.
26
+ if area < 5000 and std_intensity > 50:
27
+ return "Crack"
28
+ elif area >= 5000 and std_intensity > 40:
29
+ return "Corrosion"
30
+ else:
31
+ return "Other Defect"
32
+
33
+ def detect_pipe_issues(image: Image.Image):
34
  try:
35
+ # Convert the PIL image to a NumPy array (RGB)
36
+ image_np = np.array(image)
37
+ annotated = image.copy() # Copy for annotation
 
38
  draw = ImageDraw.Draw(annotated)
39
 
40
+ # Classify the overall pipe material
41
+ pipe_material = classify_pipe_material(image_np)
42
+
43
+ # Convert to grayscale and enhance contrast using CLAHE
44
+ gray = cv2.cvtColor(image_np, cv2.COLOR_RGB2GRAY)
45
+ clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8,8))
46
+ enhanced = clahe.apply(gray)
47
 
48
  # Apply Gaussian blur to reduce noise
49
+ blurred = cv2.GaussianBlur(enhanced, (5, 5), 0)
50
 
51
+ # Adaptive thresholding to highlight potential defect areas
52
  thresh = cv2.adaptiveThreshold(
53
  blurred, 255,
54
  cv2.ADAPTIVE_THRESH_GAUSSIAN_C,
 
56
  11, 2
57
  )
58
 
59
+ # Use morphological closing to connect fragmented areas
60
  kernel = np.ones((3, 3), np.uint8)
61
  morph = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel, iterations=2)
62
 
63
+ # Detect edges with Canny
64
  edges = cv2.Canny(morph, 50, 150)
65
 
66
+ # Find contours that might correspond to defects
67
  contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
68
+ detections = []
 
69
 
70
  for cnt in contours:
71
+ # Filter out small contours to ignore noise
72
+ if cv2.contourArea(cnt) < 100:
73
+ continue
74
+ x, y, w, h = cv2.boundingRect(cnt)
75
+ roi = enhanced[y:y+h, x:x+w]
76
+ defect_type = classify_defect(roi)
77
+ detection_info = f"{defect_type} at ({x}, {y}, {w}, {h})"
78
+ detections.append(detection_info)
79
+
80
+ # Draw bounding box and defect label
81
+ draw.rectangle([x, y, x+w, y+h], outline="red", width=2)
82
+ draw.text((x, y-10), defect_type, fill="red")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
83
 
84
+ # Prepare a textual summary including pipe material and all defect detections
85
  if detections:
86
+ summary = f"Pipe Material: {pipe_material}\nDetected Issues:\n" + "\n".join(detections)
87
  else:
88
+ summary = f"Pipe Material: {pipe_material}\nNo significant defects detected."
89
 
90
  return annotated, summary
 
91
  except Exception as e:
92
  print("Error during detection:", e)
93
  return image, f"Error: {e}"
94
 
 
95
  iface = gr.Interface(
96
+ fn=detect_pipe_issues,
97
+ inputs=gr.Image(type="pil", label="Upload a Pipe Image"),
98
  outputs=[gr.Image(label="Annotated Image"), gr.Textbox(label="Detection Summary")],
99
+ title="Pipe Defect Detector",
100
  description=(
101
+ "Upload an image of a pipe to detect granular issues such as cracks or corrosion. "
102
+ "The app classifies the defect type and determines if the pipe material is plastic or metal."
 
103
  )
104
  )
105