Python图像识别实战:古建筑表面病害检测系统从算法到GUI落地
简介这份资源面向具备Python基础、对计算机视觉与深度学习有一定了解的研发人员、文物保护技术人员及研究生提供一套古建筑表面病害辅助检测系统的完整工程实例。系统以YOLO目标检测模型为核心结合OpenCV图像处理、FastAPI服务接口与SQLite结果存储可自动识别并定位裂缝、剥落、盐析、霉斑、渗水等常见病害覆盖图像采集、数据标注、模型训练、推理检测到结果可视化与人工复核的全流程强调“模型识别人工复核”的协同模式。资源包为1个docx文档约112KB内含项目背景、模型架构、数据集配置、训练与推理代码示例、检测服务接口实现及SQLite历史查询等章节并附数据库与GUI设计说明。已有94人学习。读者可据此动手搭建可复核、可追踪的数字化病害档案用于日常巡检、修缮前调查与过程质量检查提升古建筑保护工作的智能化与标准化水平。1. 古建筑表面病害检测从人工锤敲到 Python 图像识别的落地路径做古建筑修缮的同行大多有过这样的经历一面青砖墙老师傅拿着小锤逐块敲靠声音判断空鼓一天下来胳膊抬不起来记录还全靠手绘草图。更麻烦的是同一面墙不同人敲结论可能对不上。这几年我一直在琢磨能不能用 Python 加图像识别把这件事做成一套辅助检测系统——不是替代老师傅而是先把可疑区域圈出来让人带着重点去复核。这套古建筑表面病害辅助检测系统核心就是三件事采集墙面图像、识别裂缝与剥落等病害、把结果落到数据库和界面上供人查看。它适合做文物数字化、建筑巡检、图像识别落地的人也适合想拿一个完整项目练手的开发者。下面我按实际做下来的顺序把选型、代码、参数和踩过的坑讲清楚。2. 病害识别方案怎么选传统图像处理还是深度学习2.1 两类病害的成像特征决定了技术路线古建筑表面病害常见的有裂缝、剥落、空鼓、泛碱、风化几类。其中裂缝和剥落在二维图像上特征最明显也最适合做视觉检测。裂缝表现为细长的暗色线条宽度从零点几毫米到几厘米不等方向随机剥落表现为成片的颜色突变区域边界不规则内部纹理和周围砖石差异大。这两类目标的成像特征差异直接决定了不能只用一套方法。裂缝是线状结构对边缘和梯度敏感剥落是面状区域对颜色和纹理敏感。我一开始想用一套阈值分割全搞定结果裂缝被当成噪声滤掉剥落又和阴影混在一起翻车得很彻底。后来改成两条支路裂缝走边缘增强加形态学连接剥落走颜色空间转换加区域生长。传统方法的好处是不需要标注数据参数调好就能跑适合样本少的场景。缺点是泛化差换一面墙、换一种光照阈值就得重调。深度学习的好处是泛化强但需要标注。实际项目里我一般这么分如果病害类型固定、拍摄条件可控传统方法够用如果要覆盖多种建筑、多种光照就上深度学习用传统方法做预处理和数据增强。2.2 最小可跑通的裂缝检测代码先给一段能直接跑的裂缝检测基于 OpenCV思路是灰度化、CLAHE 增强对比度、Canny 边缘、形态学闭运算连接断点、轮廓筛选。import cv2 import numpy as np def detect_cracks(img_path, min_area80, max_width40): # 读取图像并转灰度 img cv2.imread(img_path) gray cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # CLAHE 限制对比度自适应直方图均衡clipLimit 控制增强强度 clahe cv2.createCLAHE(clipLimit2.0, tileGridSize(8, 8)) enhanced clahe.apply(gray) # 高斯滤波去噪核大小必须是奇数 blurred cv2.GaussianBlur(enhanced, (5, 5), 0) # Canny 双阈值低阈值:高阈值约 1:2 到 1:3 edges cv2.Canny(blurred, 40, 120) # 闭运算连接断裂的裂缝边缘核越大连接越强但可能粘连 kernel cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5, 5)) closed cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel, iterations2) # 轮廓筛选面积过滤噪声外接矩形长宽比过滤块状区域 contours, _ cv2.findContours(closed, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) result img.copy() cracks [] for cnt in contours: area cv2.contourArea(cnt) if area min_area: continue x, y, w, h cv2.boundingRect(cnt) # 裂缝通常是细长形短边过大的排除 if min(w, h) max_width: continue cracks.append((x, y, w, h, area)) cv2.rectangle(result, (x, y), (x w, y h), (0, 0, 255), 2) return result, cracks if __name__ __main__: out, boxes detect_cracks(wall_sample.jpg) print(f检出候选裂缝 {len(boxes)} 处) cv2.imwrite(crack_result.jpg, out)逻辑说明CLAHE 解决古建筑墙面光照不均的问题比全局直方图均衡更稳Canny 的双阈值决定哪些梯度算边缘低阈值抓弱边缘但会引入噪声高阈值干净但会断线闭运算把断开的裂缝边缘连起来迭代次数越多连接越强但两次以上容易把相邻裂缝粘成一片。参数说明min_area是面积下限拍近景时裂缝像素多可以调大拍远景要调小max_width是短边上限用来排除块状区域如果墙面本身有方形砖缝干扰这个值要设得比砖缝宽度小。2.3 剥落检测走颜色空间这条路剥落区域和周围砖石的颜色差异在 HSV 空间比 RGB 空间更稳定因为 HSV 把色调和亮度分开了光照变化主要影响 V 通道。做法是把图像转 HSV对 H 和 S 通道做阈值分割再对 V 通道做局部方差判断纹理突变。def detect_spalling(img_path, h_range(0, 30), s_min40, v_var_thresh120): img cv2.imread(img_path) hsv cv2.cvtColor(img, cv2.COLOR_BGR2HSV) h, s, v cv2.split(hsv) # 色调和饱和度阈值圈出偏色区域 mask_h cv2.inRange(h, h_range[0], h_range[1]) mask_s cv2.inRange(s, s_min, 255) mask cv2.bitwise_and(mask_h, mask_s) # 局部方差反映纹理突变剥落区纹理通常比砖石平滑或更杂乱 v_f v.astype(np.float32) mean cv2.blur(v_f, (15, 15)) sq_mean cv2.blur(v_f * v_f, (15, 15)) variance sq_mean - mean * mean mask_var (variance v_var_thresh).astype(np.uint8) * 255 final_mask cv2.bitwise_and(mask, mask_var) # 开运算去小噪点 kernel cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (7, 7)) final_mask cv2.morphologyEx(final_mask, cv2.MORPH_OPEN, kernel) return final_mask逻辑说明H 通道阈值范围要根据砖石颜色定青砖偏青蓝红砖偏红黄范围设错会把整面墙都圈进去。局部方差用积分图思路算blur的核大小决定感受野15 像素适合中近距离拍摄。参数说明s_min是饱和度下限泛碱区域饱和度低这个值要调低才能抓到v_var_thresh是方差阈值纹理越复杂的墙面要设得越高。3. 把检测结果落到数据库和 GUI一套能交付的系统长什么样3.1 数据库表结构设计检测结果不能只存一张标注图得能按建筑、按时间、按病害类型查。我用 SQLite 做本地存储轻量、免安装适合单机部署。核心三张表建筑信息表、检测记录表、病害明细表。-- 建筑信息表 CREATE TABLE building ( id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, -- 建筑名称 location TEXT, -- 位置描述 build_year TEXT, -- 年代 created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); -- 检测记录表一次检测对应一条 CREATE TABLE inspection ( id INTEGER PRIMARY KEY AUTOINCREMENT, building_id INTEGER, image_path TEXT, -- 原图路径 result_path TEXT, -- 标注图路径 inspect_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP, operator TEXT, FOREIGN KEY (building_id) REFERENCES building(id) ); -- 病害明细表一处病害一条 CREATE TABLE defect ( id INTEGER PRIMARY KEY AUTOINCREMENT, inspection_id INTEGER, defect_type TEXT, -- crack / spalling / efflorescence bbox_x INTEGER, bbox_y INTEGER, bbox_w INTEGER, bbox_h INTEGER, area REAL, -- 像素面积 severity TEXT, -- low / medium / high FOREIGN KEY (inspection_id) REFERENCES inspection(id) );逻辑说明把建筑、检测、病害拆成三层是为了支持「同一建筑多次检测对比」这个需求。病害明细里存 bbox 坐标而不是只存图方便后续做面积统计和变化趋势分析。severity字段用规则算裂缝按长度和宽度分级剥落按面积占比分级。参数说明area存像素面积如果要换算实际面积需要在采集时记录拍摄距离和相机焦距用标定系数转换。3.2 用 Tkinter 搭一个能用的界面GUI 不需要花哨能选图、能跑检测、能看结果、能存库就行。Tkinter 是 Python 自带的不用额外装依赖适合交付给非技术用户。import tkinter as tk from tkinter import filedialog, messagebox from PIL import Image, ImageTk import sqlite3 import os class DefectApp: def __init__(self, root): self.root root self.root.title(古建筑表面病害辅助检测) self.root.geometry(900x600) self.img_path None self.conn sqlite3.connect(inspection.db) self._build_ui() def _build_ui(self): # 顶部按钮区 top tk.Frame(self.root) top.pack(filltk.X, padx10, pady8) tk.Button(top, text选择图像, commandself.load_image).pack(sidetk.LEFT) tk.Button(top, text裂缝检测, commandself.run_crack).pack(sidetk.LEFT, padx6) tk.Button(top, text剥落检测, commandself.run_spalling).pack(sidetk.LEFT, padx6) tk.Button(top, text保存记录, commandself.save_record).pack(sidetk.LEFT, padx6) # 图像显示区 self.canvas tk.Label(self.root, bg#f0f0f0) self.canvas.pack(expandTrue, filltk.BOTH, padx10, pady6) # 状态栏 self.status tk.StringVar(value就绪) tk.Label(self.root, textvariableself.status, anchortk.W).pack(filltk.X, padx10) def load_image(self): path filedialog.askopenfilename(filetypes[(图像, *.jpg *.png *.bmp)]) if not path: return self.img_path path img Image.open(path) img.thumbnail((860, 480)) self.tk_img ImageTk.PhotoImage(img) self.canvas.config(imageself.tk_img) self.status.set(f已加载{os.path.basename(path)}) def run_crack(self): if not self.img_path: messagebox.showwarning(提示, 请先选择图像) return # 调用第 2 章的检测函数此处省略重复定义 out, boxes detect_cracks(self.img_path) self._show_result(out) self.status.set(f裂缝检测完成候选 {len(boxes)} 处) def _show_result(self, bgr_img): rgb bgr_img[:, :, ::-1] img Image.fromarray(rgb) img.thumbnail((860, 480)) self.tk_img ImageTk.PhotoImage(img) self.canvas.config(imageself.tk_img) def save_record(self): if not self.img_path: return cur self.conn.cursor() cur.execute(INSERT INTO inspection (building_id, image_path) VALUES (?, ?), (1, self.img_path)) self.conn.commit() self.status.set(记录已保存) if __name__ __main__: root tk.Tk() app DefectApp(root) root.mainloop()逻辑说明界面分三层——按钮区触发动作画布区显示图像状态栏反馈进度。_show_result里做了 BGR 到 RGB 的转换因为 OpenCV 读进来是 BGRPIL 显示要 RGB这一步漏了图会变色是新手最常见的翻车点。参数说明thumbnail的尺寸要小于画布否则显示不全数据库连接在__init__里建立整个应用生命周期复用不要每次操作都开关连接。3.3 检测流程串起来实际使用流程是新建建筑记录 → 选择该建筑 → 导入图像 → 跑检测 → 人工复核修正 → 保存。人工复核这一步不能省算法给的是候选老师傅的判断才是最终结论。系统里要留一个「手动增删标注框」的入口让复核结果能回写数据库。4. 避坑与排查那些让检测结果不可信的细节4.1 现象同一面墙两次拍摄检测结果差很多原因光照变化导致 CLAHE 增强后的对比度不一致Canny 阈值固定时强光下边缘多、弱光下边缘少。解决采集时用固定光源或加遮光罩或者在检测前做一次亮度归一化把图像平均亮度拉到固定值再处理。我一般会在预处理里加一步cv2.normalize把灰度均值归到 128 附近。4.2 现象砖缝被大量识别成裂缝原因砖缝本身是线状暗纹和裂缝的梯度特征高度相似。解决两个方向。一是提高min_area砖缝通常比裂缝短二是加方向过滤裂缝走向随机砖缝走向规则用霍夫变换检测主方向后排除规则排列的线段。如果墙面是规则砌筑这个方法很有效。4.3 现象剥落检测把阴影圈进去原因阴影区域 V 通道低局部方差也低和剥落的特征重叠。解决在 HSV 分割时加 V 通道下限阴影的 V 值通常低于 40剥落区不会那么暗。另外可以用形态学判断区域边界阴影边界平滑剥落边界破碎。4.4 现象数据库里病害坐标和原图对不上原因GUI 显示时做了缩放但保存的是缩放后的坐标。解决检测在原图上做坐标存原图坐标系显示时只缩放显示不缩放数据。这个坑我在第一个版本里踩过存进去的框全偏了后来统一规定「数据永远用原图坐标」才解决。4.5 现象程序跑一段时间内存涨原因OpenCV 的 Mat 对象和 PIL 的 Image 对象没及时释放尤其是循环处理多张图时。解决处理完一张图后显式del掉中间变量或者把检测逻辑放到独立函数里让局部变量随函数返回自动回收。Tkinter 里反复设置PhotoImage也要注意旧对象释放。5. 进阶技巧让辅助检测真正省人力的三个做法第一个做法是批量处理和报告生成。单张检测只是演示实际巡检一次几百张图要能批量跑完并输出一份带缩略图和统计的 HTML 报告。用jinja2模板渲染把每张图的标注结果和病害数量填进去修缮队拿到报告就能直接排工期。批量处理时用concurrent.futures开多进程图像检测是 CPU 密集型多进程比多线程有效进程数设成 CPU 核心数就行。第二个做法是病害变化对比。同一建筑不同时期拍的照片把两次检测的病害框对齐算面积变化率。裂缝面积增长超过阈值就标红提示需要优先处理。对齐用简单的 IoU 匹配重叠度超过 0.3 认为是同一处病害。这个功能对长期监测特别有用能看出哪面墙在恶化。第三个做法是模型微调。传统方法跑一段时间后把人工复核修正过的样本攒起来标注成数据集用轻量分割模型训练一版。我一般用 MobileNet 做 backbone 的 U-Net输入 512×512训练 50 轮左右在自建数据上 IoU 能到 0.6 以上。推理时和传统方法做融合两个都检出的区域置信度最高只有一个检出的交给人工重点看。# 批量处理示例多进程加速 from concurrent.futures import ProcessPoolExecutor import glob def process_one(path): out, boxes detect_cracks(path) save_path path.replace(.jpg, _result.jpg) cv2.imwrite(save_path, out) return path, len(boxes) if __name__ __main__: files glob.glob(images/*.jpg) with ProcessPoolExecutor(max_workers4) as ex: results list(ex.map(process_one, files)) for path, n in results: print(f{path}: {n} 处)逻辑说明ProcessPoolExecutor把每张图的检测分发到独立进程绕开 GIL 限制。max_workers设成 CPU 核心数设太大反而因为进程切换开销变慢。参数说明glob的模式按实际目录结构调整如果图像很大可以在process_one里先缩放再检测速度会快很多但坐标要按缩放比例还原。这套系统我做下来最大的体会是算法精度不是第一位的流程闭环才是。检测、复核、存档、对比每一步都打通修缮队才愿意用。我自己的习惯是每做完一个版本拿同一批图跑三遍看结果稳不稳定不稳定就先查预处理别急着调模型。希望帮到你。本文还有配套的精品资源点击获取

相关新闻

道路坑洼检测实战:从数据预处理到LeNet-5部署的完整闭环

道路坑洼检测实战:从数据预处理到LeNet-5部署的完整闭环

简介:本资源是一套面向计算机视觉初学者与课程设计学生的道路坑洼检测实战项目,基于Python与CNN深度学习模型实现,适用于高校《数字图像处理》《机器学习》等课程的期末大作业或课程设计参考。项目已获97分高分评价,代码完整、注释…

2026/10/10 22:03:52 阅读更多 →
SpringBoot房屋租赁管理系统实战:权限控制、状态机与缓存优化

SpringBoot房屋租赁管理系统实战:权限控制、状态机与缓存优化

做房屋租赁管理系统一年多了,从最初的需求梳理到最终上线,踩过的坑、改过的代码、优化过的查询,都值得拿出来好好聊聊。这个项目用的是SpringBoot全家桶,前后端分离,前端Vue打包后放进SpringBoot的static目录统一部署&…

2026/10/10 22:03:52 阅读更多 →
从 SM-2 到 FSRS:Anki 背后的间隔重复算法三十年

从 SM-2 到 FSRS:Anki 背后的间隔重复算法三十年

从 SM-2 到 FSRS:Anki 背后的间隔重复算法三十年 【免费下载链接】anki Anki is a smart spaced repetition flashcard program 项目地址: https://gitcode.com/GitHub_Trending/an/anki 记忆会随时间衰减,这是艾宾浩斯在 1885 年用无意义音节实验…

2026/10/10 22:02:51 阅读更多 →

最新新闻

非功能需求实战:性能、安全与可用性的量化落地

非功能需求实战:性能、安全与可用性的量化落地

每次上线前,我都习惯把功能需求清单从头到尾过一遍,确认每个按钮、每个流程都按文档实现了。但真正让我半夜爬起来处理线上事故的,从来不是某个功能没做对,而是那些根本没写进文档里的东西——并发一上来系统就卡死、数据量涨到百…

2026/10/10 22:47:28 阅读更多 →
震旦adc225打印机驱动怎么下载?办公小白必看的3种打印机驱动安装方法(附震旦官网)

震旦adc225打印机驱动怎么下载?办公小白必看的3种打印机驱动安装方法(附震旦官网)

办公室里那台震旦adc225复合机突然连不上电脑,或者更换新主机后打印毫无反应,这类场景对于日常行政和IT维护人员来说并不陌生。不少用户打开搜索框,输入“震旦adc225打印机驱动”、“震旦打印机驱动下载”等关键词,却发现版本五花…

2026/10/10 22:47:28 阅读更多 →
C# OpenVINO 印章检测实战:从模型加载到推理部署

C# OpenVINO 印章检测实战:从模型加载到推理部署

简介:本资源面向具备一定C#基础的开发者与计算机视觉学习者,提供一套在.NET环境下调用Intel OpenVINO工具套件、直接读取百度预训练模型实现印章检测的完整源码方案。项目通过C/CLI封装OpenVINO原生API,在C#中完成模型加载、图像预处理、推理…

2026/10/10 22:47:28 阅读更多 →
YOLOv13+PyQt5手机使用行为分析工程包

YOLOv13+PyQt5手机使用行为分析工程包

简介:本资源是一套面向计算机视觉初学者与行为分析研究者的手机使用检测实践方案,聚焦于日常场景中用户手机持有、操作等行为的识别与习惯建模。项目基于YOLO系列算法(兼容v5至v12)构建,集成标注完备的目标检测数据集&…

2026/10/10 22:47:28 阅读更多 →
X射线底片焊缝缺陷检测:数据集预处理与YOLOv8实战

X射线底片焊缝缺陷检测:数据集预处理与YOLOv8实战

简介:一套面向X射线底片焊缝缺陷检测的目标检测数据集,适用于工业无损检测、焊接质量评估与算法研究场景,也适合目标检测工程师用于模型训练、调优和效果验证。压缩包约39.56MB,按JPEGImages、Annotations、labels三目录组织&…

2026/10/10 22:47:28 阅读更多 →
开源实时3D地球引擎WorldWideView:如何在浏览器里可视化全球飞机、船舶与冲突事件

开源实时3D地球引擎WorldWideView:如何在浏览器里可视化全球飞机、船舶与冲突事件

【免费下载链接】worldwideview 项目地址: https://gitcode.com/gh_mirrors/wo/worldwideview 点击查看 免费下载 WorldWideView 是一款开源实时 3D 地球引擎,让你在普通浏览器中直接可视化全球飞机航线、船舶动态与冲突事件。它把持续刷新的真实世界数…

2026/10/10 22:46:28 阅读更多 →

日新闻

卫星轨道分类全解析:从LEO到GEO的选型逻辑与工程实践

卫星轨道分类全解析:从LEO到GEO的选型逻辑与工程实践

1. 从“卫星轨道分类”这个标题说起:为什么值得花时间搞懂第一次接触“卫星轨道分类”这个概念,很多人会觉得它离自己很远——不就是天上的星星怎么转吗?但如果你正在做航天任务规划、遥感数据接收、星座设计,甚至只是准备一场航天…

2026/10/10 0:00:39 阅读更多 →
Spring AOP 核心原理与实战:从概念到日志切面落地

Spring AOP 核心原理与实战:从概念到日志切面落地

1. 从一个真实痛点说起:为什么你的代码里到处都是重复逻辑刚入行那会儿,我写过一个用户管理模块,注册、登录、改密码、注销四个接口。每个接口里都塞了几乎一样的日志打印、参数校验、事务开启和提交。当时觉得没什么,能跑就行。直…

2026/10/10 0:00:40 阅读更多 →
Python招聘数据采集与分析可视化:从采集清洗到薪资技能城市可视化全链路

Python招聘数据采集与分析可视化:从采集清洗到薪资技能城市可视化全链路

简介:这是一套面向计算机相关专业学生与项目实战学习者的Python数据采集与分析可视化完整项目,以Boss直聘岗位数据为对象,适合用作毕业设计、课程设计或期末大作业。资源包共38个文件,约246KB,以13个py源码文件为核心&…

2026/10/10 0:00:40 阅读更多 →

周新闻

KT148A语音芯片外挂8002D功放的工程实践指南

KT148A语音芯片外挂8002D功放的工程实践指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/10 11:14:25 阅读更多 →
LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/10 1:36:08 阅读更多 →
ARM架构深度解析:从RISC设计理念到交叉编译实战

ARM架构深度解析:从RISC设计理念到交叉编译实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/10 11:14:58 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/10 5:23:50 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/9 21:32:20 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/10 10:38:42 阅读更多 →