Spaces:
Sleeping
Sleeping
File size: 5,296 Bytes
27e44c1 | 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 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 | #!/usr/bin/env python3
from __future__ import annotations
import os
from functools import lru_cache
from typing import Any
import gradio as gr
from huggingface_hub import hf_hub_download
from ultralytics import YOLO
TITLE = "Crack Detection Studio"
DEFAULT_MODEL_REPO_ID = "Mezosky/cracker-yolo26l-baseline"
DEFAULT_MODEL_FILENAME = "best.pt"
DEFAULT_DEVICE = os.getenv("DEVICE", "cpu")
DEFAULT_IMGSZ = int(os.getenv("IMGSZ", "640"))
DEFAULT_CONF = float(os.getenv("CONF", "0.25"))
DEFAULT_IOU = float(os.getenv("IOU", "0.45"))
@lru_cache(maxsize=1)
def get_model() -> tuple[YOLO, str]:
model_repo_id = os.getenv("MODEL_REPO_ID", DEFAULT_MODEL_REPO_ID)
model_filename = os.getenv("MODEL_FILENAME", DEFAULT_MODEL_FILENAME)
model_path = hf_hub_download(repo_id=model_repo_id, filename=model_filename, repo_type="model")
return YOLO(model_path), model_path
def build_rows(result: Any) -> list[list[Any]]:
rows: list[list[Any]] = []
boxes = getattr(result, "boxes", None)
if boxes is None or len(boxes) == 0:
return rows
xyxy = boxes.xyxy.cpu().tolist()
confs = boxes.conf.cpu().tolist()
class_ids = boxes.cls.cpu().tolist()
names = getattr(result, "names", {})
for idx, (box, conf, class_id) in enumerate(zip(xyxy, confs, class_ids), start=1):
class_id_int = int(class_id)
class_name = names.get(class_id_int, f"class_{class_id_int}") if isinstance(names, dict) else str(class_id_int)
x1, y1, x2, y2 = [round(float(value), 1) for value in box]
rows.append([idx, class_name, round(float(conf), 4), x1, y1, x2, y2])
return rows
def infer(image, conf_threshold, iou_threshold, image_size):
if image is None:
return None, [], "Upload an image to start detection."
model, _ = get_model()
results = model.predict(
source=image,
conf=float(conf_threshold),
iou=float(iou_threshold),
imgsz=int(image_size),
device=DEFAULT_DEVICE,
verbose=False,
)
result = results[0]
rendered = result.plot()
rendered_rgb = rendered[..., ::-1]
rows = build_rows(result)
if not rows:
summary = "No crack detections found at this confidence threshold."
else:
avg_conf = sum(row[2] for row in rows) / len(rows)
summary = f"Detected **{len(rows)} crack box(es)**. Mean confidence: **{avg_conf:.3f}**."
return rendered_rgb, rows, summary
def build_demo() -> gr.Blocks:
css = """
.gradio-container {
background: radial-gradient(1200px 600px at 5% 0%, #0f172a 0%, #111827 35%, #030712 100%);
}
.hero {
background: linear-gradient(135deg, #0ea5e9 0%, #22d3ee 45%, #34d399 100%);
border-radius: 18px;
padding: 18px 22px;
color: #00111a;
box-shadow: 0 12px 30px rgba(34, 211, 238, 0.25);
margin-bottom: 12px;
}
.glass {
background: rgba(255, 255, 255, 0.06);
border: 1px solid rgba(255, 255, 255, 0.15);
border-radius: 14px;
padding: 10px;
}
"""
with gr.Blocks(title=TITLE, css=css) as demo:
gr.HTML(
"""
<div class='hero'>
<h1 style='margin:0;font-size:28px'>Crack Detection Studio</h1>
<p style='margin:6px 0 0 0;font-size:14px'>Upload one image and get instant crack localization from YOLO26.</p>
</div>
"""
)
gr.Markdown(
"Model repo: `" + os.getenv("MODEL_REPO_ID", DEFAULT_MODEL_REPO_ID) + "` \\n"
"Model file: `" + os.getenv("MODEL_FILENAME", DEFAULT_MODEL_FILENAME) + "` \\n"
"Device: `" + DEFAULT_DEVICE + "`"
)
with gr.Row():
with gr.Column(scale=1, elem_classes=["glass"]):
input_image = gr.Image(type="pil", label="Upload Image")
conf_slider = gr.Slider(0.05, 0.95, value=DEFAULT_CONF, step=0.01, label="Confidence Threshold")
iou_slider = gr.Slider(0.10, 0.90, value=DEFAULT_IOU, step=0.01, label="IoU Threshold")
imgsz_slider = gr.Slider(320, 1280, value=DEFAULT_IMGSZ, step=32, label="Inference Image Size")
run_button = gr.Button("Detect Cracks", variant="primary")
with gr.Column(scale=1, elem_classes=["glass"]):
output_image = gr.Image(type="numpy", label="Predicted Crack Positions")
output_table = gr.Dataframe(
headers=["id", "class", "confidence", "x1", "y1", "x2", "y2"],
datatype=["number", "str", "number", "number", "number", "number", "number"],
row_count=8,
column_count=(7, "fixed"),
label="Detections",
)
summary_md = gr.Markdown("Upload an image to start detection.")
run_button.click(
fn=infer,
inputs=[input_image, conf_slider, iou_slider, imgsz_slider],
outputs=[output_image, output_table, summary_md],
)
input_image.change(
fn=infer,
inputs=[input_image, conf_slider, iou_slider, imgsz_slider],
outputs=[output_image, output_table, summary_md],
)
return demo
demo = build_demo()
if __name__ == "__main__":
demo.launch()
|