Spaces:
Sleeping
Sleeping
File size: 4,524 Bytes
a5399c2 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 |
import cv2
import numpy as np
import gradio as gr
from skimage.filters import threshold_multiotsu
from scipy.ndimage import binary_fill_holes, binary_opening
import matplotlib.pyplot as plt
import logging
# Configure logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
def enhanced_aggregate_segmentation(image):
"""Advanced concrete aggregate segmentation pipeline"""
try:
# Convert to grayscale if needed
if len(image.shape) == 3:
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
else:
gray = image.copy()
# Step 1: Contrast enhancement
clahe = cv2.createCLAHE(clipLimit=4.0, tileGridSize=(8,8))
enhanced = clahe.apply(gray)
# Step 2: Multi-level Otsu thresholding
thresholds = threshold_multiotsu(enhanced, classes=3)
regions = np.digitize(enhanced, bins=thresholds)
# Step 3: Aggregate mask creation
aggregate_mask = (regions == 2).astype(np.uint8) # Assuming aggregates are brightest
# Step 4: Morphological refinement
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5,5))
cleaned = cv2.morphologyEx(aggregate_mask*255, cv2.MORPH_CLOSE, kernel, iterations=2)
cleaned = cv2.morphologyEx(cleaned, cv2.MORPH_OPEN, kernel, iterations=1)
filled = binary_fill_holes(cleaned > 127)
# Step 5: Final mask processing
final_mask = binary_opening(filled, structure=np.ones((3,3))).astype(np.uint8)
# Create output images
if len(image.shape) == 3:
aggregates = image.copy()
aggregates[final_mask == 0] = 0
mask_vis = cv2.applyColorMap((final_mask*255).astype(np.uint8), cv2.COLORMAP_JET)
mask_vis = cv2.addWeighted(image, 0.7, mask_vis, 0.3, 0)
else:
aggregates = np.zeros_like(image)
aggregates[final_mask == 1] = image[final_mask == 1]
mask_vis = cv2.applyColorMap((final_mask*255).astype(np.uint8), cv2.COLORMAP_JET)
return aggregates, mask_vis
except Exception as e:
logger.error(f"Segmentation error: {str(e)}")
error_img = np.zeros_like(image) if len(image.shape) == 2 else np.zeros((*image.shape[:2], 3))
return error_img, error_img
def process_image(image):
"""Process image for Gradio interface"""
try:
# Convert from Gradio's RGB to OpenCV's BGR
if isinstance(image, np.ndarray) and image.shape[2] == 3:
image = cv2.cvtColor(image, cv2.COLOR_RGB2BGR)
aggregates, mask_vis = enhanced_aggregate_segmentation(image)
# Convert back to RGB for display
if len(aggregates.shape) == 3:
aggregates = cv2.cvtColor(aggregates, cv2.COLOR_BGR2RGB)
mask_vis = cv2.cvtColor(mask_vis, cv2.COLOR_BGR2RGB)
return aggregates, mask_vis
except Exception as e:
logger.error(f"Processing error: {str(e)}")
error_img = np.zeros((512,512,3), dtype=np.uint8)
return error_img, error_img
# Create Gradio interface
with gr.Blocks(title="Concrete Aggregate Analyzer") as app:
gr.Markdown("""
## Concrete Aggregate Segmentation Analyzer
Upload an image of concrete surface for aggregate analysis
""")
with gr.Row():
with gr.Column():
input_img = gr.Image(label="Input Image", type="numpy")
process_btn = gr.Button("Analyze", variant="primary")
with gr.Column():
aggregates_img = gr.Image(label="Detected Aggregates")
mask_img = gr.Image(label="Segmentation Visualization")
debug_output = gr.Textbox(label="Processing Log")
def process_with_logging(img):
logger.handlers.clear()
log_messages = []
class LogHandler(logging.Handler):
def emit(self, record):
log_messages.append(f"{record.levelname}: {record.getMessage()}")
logger.addHandler(LogHandler())
results = process_image(img)
return (*results, "\n".join(log_messages))
process_btn.click(
fn=process_with_logging,
inputs=input_img,
outputs=[aggregates_img, mask_img, debug_output]
)
if __name__ == "__main__":
logger.info("Starting concrete aggregate analyzer...")
app.launch(
server_name="0.0.0.0",
server_port=7860,
share=False
) |