在计算机视觉领域,裂缝检测是一项基础且重要的任务。之前我们已经掌握了使用OpenCV进行图像读取、预处理、自适应阈值和形态学操作等核心功能。今天,我们将把这些功能封装成一个轻量级的Web应用——使用Gradio框架,让检测结果从PyCharm的控制台跃升到浏览器界面,实现更直观、更吸引人的可视化交互。
Gradio简介:Python轻量级Web框架
Gradio是一个专为机器学习模型和Python函数设计的轻量级Web框架。与JavaScript、Java、C++等语言构建的复杂Web应用不同,Gradio可以让你用短短几行Python代码就创建一个可交互的网页。它有两种核心模式:
- gr.Blocks:功能更强大,支持自定义页面布局和排版,适合需要复杂界面的场景。我们本次将使用这种模式。
- gr.Interface:更简单,适合快速原型开发,但灵活性较低。
Gradio提供了丰富的UI组件,让我们可以像搭积木一样构建Web界面。以下是几个常用组件:
- gr.Markdown:用于显示标题、说明文字等富文本内容。
- gr.Textbox:既可输入也可输出,常用于显示检测报告等文本结果。
- gr.Row:水平排列组件,配合
with语句使用,实现横向布局。 - gr.Column:垂直排列组件,实现纵向布局。
- gr.Image:用于输入或输出图片,是裂缝检测的核心组件。
- gr.Button:触发操作的按钮,比如“检测”按钮。
环境搭建:一行命令搞定
在开始编码之前,我们需要安装必要的Python库。打开终端,执行以下命令:
pip install gradio opencv-python numpy
如果你在国内,使用清华镜像源可以加速下载:
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple gradio opencv-python numpy
✅ 安装完成后,我们就可以开始编写代码了。值得注意的是,Gradio支持Python 3.7及以上版本,建议使用最新稳定版。此外,如果你熟悉TypeScript或其他前端语言,会发现Gradio的组件设计理念与之类似——都是基于事件驱动的响应式编程。
核心代码解析:构建检测界面
让我们先来看一下创建Gradio应用的核心代码结构。首先,我们使用with gr.Blocks(title = ...) as demo创建一个Blocks容器。这里的title参数就是网页标题栏显示的文字,demo是这个容器的变量名。
with
上下文管理器:Python的with语句会自动处理资源的打开和关闭,确保应用运行稳定。

接下来,我们定义输入图片组件:
input_img = gr.Image(label = "上传裂缝图片", type = "numpy")
这里type = "numpy"表示图片将以NumPy数组的形式传递给处理函数。Gradio支持多种图片类型,包括文件路径、PIL Image等。下表总结了常用参数:
| 上传后转成 NumPy 数组 | 因为OpenCV 处理需要 NumPy 格式 |
按钮组件可以设置样式,例如variant = "primary"可以让按钮高亮显示。Gradio提供了多种variant选项:

最关键的部分是按钮的点击事件绑定——detect_btn.click(),它连接了前端交互和后端逻辑:


# ============ 创建界面 ============
with gr.Blocks(title = "AI裂缝检测系统") as demo:
gr.Markdown("AI裂缝检测系统")
gr.Markdown("上传裂缝照片,自动检测裂并计算长度、宽度")
with gr.Row():
with gr.Column():
input_img = gr.Image(label = "上传裂缝图片" , type = "numpy")
detect_btn = gr.Button("开始检测" , variant = "primary")
with gr.Column():
output_img = gr.Image(label = "检测结果")
output_text = gr.Textbox(label = "检测报告" , lines = 10)
detect_btn.click(
fn = detect_crack,
inputs = input_img,
outputs = [output_img , output_text]
)
gr.Markdown("====")
gr.Markdown(
"作者 : 棒 棒 | 学校 : 索菲亚大学 | Github : [crack-detector](https://github.com/12345678875/crack-detector)"
)为了帮助你更直观地理解整个流程,我让AI生成了一张整体代码流程图:

裂缝检测算法实现
裂缝检测的核心算法我们已经在前两篇文章中详细介绍过,这里只做简要回顾。整个流程包括:读取图片 → 灰度化 → 高斯模糊去噪 → Canny边缘检测 → 自适应阈值处理 → 形态学操作(开闭运算)→ 裂缝轮廓提取 → 计算裂缝面积、长度等指标 → 在原图上绘制结果并展示。
以下是核心检测函数的代码:
# # ============ 裂缝检测函数 ============
def detect_crack(image):
if image is None:
return None,"wrong , can not read the picture"
#gray->blurred->adaptive->kernel->close
gray = cv2.cvtColor(image , cv2.COLOR_BGR2GRAY)
blurred = cv2.GaussianBlur(gray , (5 , 5) , 0)
edges = cv2.Canny(blurred , 80 , 200)
adaptive = cv2.adaptiveThreshold(
edges , 255,
cv2.ADAPTIVE_THRESH_GAUSSIAN_C,
cv2.THRESH_BINARY_INV,
ADAPTIVE_BLOCK_SIZE,
ADAPTIVE_C
)
#=========形态学操作这里还是有点不太熟======
kernel = np.ones((MORPH_KERNEL_SIZE , MORPH_KERNEL_SIZE ), np.uint8)
closed = cv2.morphologyEx(adaptive , cv2.MORPH_CLOSE, kernel , iterations = MORPH_ITERATIONS)
contours , _ = cv2.findContours(closed , cv2.RETR_EXTERNAL , cv2.CHAIN_APPROX_SIMPLE)
##========计算+画图========
img_copy = image.copy()
crack_count = 0
report_lines = []
for i , contour in enumerate(contours):
area = cv2.contourArea(contour)
if area > MIN_AREA:
length = cv2.arcLength(contour , True)
length_mm = length / PIXELS_PER_MM
width = area / (length / 2)
width_mm = width / PIXELS_PER_MM
report_lines.append(f"裂缝{crack_count}: 长度={length_mm:.2f}mm, 宽度={width_mm:.2f}mm")
#画轮廓
cv2.drawContours(img_copy , [contour] , -1 ,(0 , 255 , 0) , 2)
crack_count += 1
if crack_count == 0:
report = "未检测到有效裂缝(面积 < 100 像素²)"
else:
report = f"共检测到 {crack_count} 条裂缝"
report += " ".join(report_lines)
report += f"\n检测时间:{datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')}"
report += f"标定参数:{PIXELS_PER_MM}像素 / mm(需根据实际标定调整)"
return img_copy,report⚠️ 注意事项:
- 自适应阈值参数
blockSize和C需要根据实际图片调整,建议先在小样本上测试。 - 形态学操作的内核大小(kernel)也会影响检测精度,过大会丢失细节,过小会引入噪声。
- 如果检测效果不理想,可以尝试调整Canny算子的高低阈值。
完整代码整合
将上述所有部分整合在一起,就得到了完整的裂缝检测Web应用代码:
import gradio as gr
import cv2
import numpy as np
import datetime
import os
# # ============ 配置参数 ============
PIXELS_PER_MM = 12
MIN_AREA = 100
ADAPTIVE_BLOCK_SIZE = 11
ADAPTIVE_C = 2
MORPH_KERNEL_SIZE = 3
MORPH_ITERATIONS = 5
# # ============ 裂缝检测函数 ============
def detect_crack(image):
if image is None:
return None,"wrong , can not read the picture"
#gray->blurred->adaptive->kernel->close
gray = cv2.cvtColor(image , cv2.COLOR_BGR2GRAY)
blurred = cv2.GaussianBlur(gray , (5 , 5) , 0)
edges = cv2.Canny(blurred , 80 , 200)
adaptive = cv2.adaptiveThreshold(
edges , 255,
cv2.ADAPTIVE_THRESH_GAUSSIAN_C,
cv2.THRESH_BINARY_INV,
ADAPTIVE_BLOCK_SIZE,
ADAPTIVE_C
)
#=========形态学操作这里还是有点不太熟======
kernel = np.ones((MORPH_KERNEL_SIZE , MORPH_KERNEL_SIZE ), np.uint8)
closed = cv2.morphologyEx(adaptive , cv2.MORPH_CLOSE, kernel , iterations = MORPH_ITERATIONS)
contours , _ = cv2.findContours(closed , cv2.RETR_EXTERNAL , cv2.CHAIN_APPROX_SIMPLE)
##========计算+画图========
img_copy = image.copy()
crack_count = 0
report_lines = []
for i , contour in enumerate(contours):
area = cv2.contourArea(contour)
if area > MIN_AREA:
length = cv2.arcLength(contour , True)
length_mm = length / PIXELS_PER_MM
width = area / (length / 2)
width_mm = width / PIXELS_PER_MM
report_lines.append(f"裂缝{crack_count}: 长度={length_mm:.2f}mm, 宽度={width_mm:.2f}mm")
#画轮廓
cv2.drawContours(img_copy , [contour] , -1 ,(0 , 255 , 0) , 2)
crack_count += 1
if crack_count == 0:
report = "未检测到有效裂缝(面积 < 100 像素²)"
else:
report = f"共检测到 {crack_count} 条裂缝"
report += " ".join(report_lines)
report += f"\n检测时间:{datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')}"
report += f"标定参数:{PIXELS_PER_MM}像素 / mm(需根据实际标定调整)"
return img_copy,report
# ============ 创建界面 ============
with gr.Blocks(title = "AI裂缝检测系统") as demo:
gr.Markdown("AI裂缝检测系统")
gr.Markdown("上传裂缝照片,自动检测裂并计算长度、宽度")
with gr.Row():
with gr.Column():
input_img = gr.Image(label = "上传裂缝图片" , type = "numpy")
detect_btn = gr.Button("开始检测" , variant = "primary")
with gr.Column():
output_img = gr.Image(label = "检测结果")
output_text = gr.Textbox(label = "检测报告" , lines = 10)
detect_btn.click(
fn = detect_crack,
inputs = input_img,
outputs = [output_img , output_text]
)
gr.Markdown("====")
gr.Markdown(
"作者 : 棒 棒 | 学校 : 索菲亚大学 | Github : [crack-detector](https://github.com/12345678875/crack-detector)"
)
# ============ 启动应用 ============
if __name__ == "__main__":
demo.launch()[AFFILIATE_SLOT_1]
运行这段代码后,你会在控制台看到类似如下的输出:
Running on local URL: http://127.0.0.1:7860
打开浏览器访问该地址,即可看到我们的裂缝检测界面。上传一张裂缝图片,点击“检测裂缝”按钮,等待几秒钟,右侧就会显示处理后的结果,包括裂缝轮廓、面积占比等数据。
运行效果展示
下面是在本地测试的运行截图,展示了上传图片和检测结果:


从截图可以看出,Gradio界面简洁直观,左侧是输入区域,右侧是输出区域。检测结果不仅显示了裂缝的轮廓,还以文字形式输出了裂缝面积和长度,便于后续分析。
[AFFILIATE_SLOT_2]
总结与进阶
本文详细介绍了如何将OpenCV裂缝检测算法封装为Gradio Web应用。通过使用gr.Blocks模式,我们实现了自定义布局;通过gr.Image、gr.Button等组件,构建了完整的用户交互界面。整个过程只需几十行Python代码,无需任何前端知识(JavaScript、TypeScript等)。如果你希望进一步优化,可以考虑:
- 添加批量处理功能,支持多张图片同时检测。
- 集成更先进的深度学习模型(如U-Net)提升检测精度。
- 部署到云服务器(如Hugging Face Spaces)实现公网访问。
希望本文能帮助你快速掌握Gradio的应用技巧,将你的计算机视觉项目从本地脚本升级为可分享的Web应用!
type="numpy"
浙公网安备 33010602011771号