STM32+OpenMV嵌入式矩形识别实战:从预处理到串口协议
简介本资源是一套基于STM32F103C8T6与OPENMV协同实现黑色矩形识别的嵌入式视觉项目面向嵌入式初学者、智能车/机器人方向学生及课程设计实践者解决图像识别结果实时回传与坐标解析这一典型跨平台通信问题。压缩包共90个文件含57个头文件h与20个源文件c构成完整的HAL库工程框架1个.py脚本Find_Tilted_Rects.py负责OPENMV端倾斜矩形检测与串口通信逻辑另有.ioc配置文件、.uvprojx工程文件、.bat一键清理脚本及.hex固件等关键开发资产整体仅640KB轻量易部署。已有1008人学习下载资源结构清晰Core/Drivers目录组织规范含自动追踪主逻辑与HAL驱动分层配套CUBEMX配置与KEIL5工程开箱即用特别适合理解色块识别→坐标提取→UART协议封装→STM32端接收解析的全链路实现。1. 为什么矩形识别在嵌入式视觉里是个“玄学起点”STM32OpenMV 组合不是炫技而是把算法真正塞进资源绷紧的硬件里跑通的第一步你手头有一块 STM32F407 开发板、一个 OpenMV Cam H7 模块还有一张印着标准 A4 纸和几个打印矩形框的白纸——这不是实验室Demo而是某高校智能分拣小车项目组凌晨三点还在调的实战场。很多人以为“矩形识别”就是调个find_rects()函数、画个框完事但真实场景中光照一变、角度一偏、纸张反光、边缘模糊OpenMV 返回的rect对象就突然空了而 STM32 主控还在傻等串口数据整个系统卡死。这根本不是算法不行是没搞清 OpenMV 的图像预处理边界、没对齐 STM32 的通信节奏、更没给矩形定义“什么叫够格”。本篇不讲 OpenCV 里花里胡哨的霍夫变换只聚焦STM32OpenMV 这一对硬搭档如何协同完成稳定、低延迟、可部署的矩形识别闭环从 OpenMV 端怎么滤噪、怎么设阈值、怎么筛掉伪矩形到 STM32 端怎么解析二进制协议、怎么防粘包、怎么用定时器兜底超时。适合所有正在把视觉模块集成进电机控制、机械臂定位或巡线小车的嵌入式开发者——尤其当你发现 OpenMV IDE 里能跑通一接上 STM32 就失联时这篇就是你的后悔药。2. OpenMV 端矩形识别不是“找四个角”而是“在噪声里守住几何信仰”OpenMV 的find_rects()并非直接检测四边形顶点而是基于轮廓contour的最小外接矩形minAreaRect 长宽比/角度/面积三重过滤。它快但极依赖输入图像质量。盲目调高阈值只会让小矩形消失盲目降低又引入大量噪点轮廓。必须从采集源头开始约束。2.1 图像预处理链5 行代码决定识别鲁棒性上限import sensor, image, time, math from pyb import UART # 初始化传感器关键在分辨率与帧率平衡 sensor.reset() sensor.set_pixformat(sensor.RGB565) # 不用 GRAYSCALERGB 能更好分离纸张与背景 sensor.set_framesize(sensor.QQVGA) # 160x120 —— STM32 串口吞吐瓶颈下的黄金尺寸 sensor.skip_frames(time2000) # 等待自动增益/白平衡收敛别省这2秒 # 预处理核心先灰度转RGB再做二值化比直接GRAY更抗光照不均 img sensor.snapshot() img img.to_grayscale() # 转灰度便于阈值操作 img img.binary([(0, 60)], invertTrue, zeroTrue) # 黑底白矩形0~60灰度为前景矩形invertTrue让矩形变白 img img.dilate(1) # 膨胀1次弥合矩形边缘断裂打印虚线/轻微褶皱常见 img img.erode(1) # 腐蚀1次剔除孤立噪点避免小斑点被误认轮廓逻辑说明QQVGA160×120是硬性选择OpenMV H7 在该分辨率下处理find_rects()平均耗时 18~25ms而QVGA320×240会飙到 60msSTM32 串口来不及收发binary()参数(0,60)是血泪经验A4 纸在室内LED灯下灰度集中在 120~200矩形墨迹在 20~50设0~60可完整捕获墨迹且排除大部分纸面纹理invertTrue确保矩形为白色连通域这是find_contours()的前提dilate()erode()顺序不能反先膨胀补断边再腐蚀去毛刺若反过来会直接抹掉细矩形。2.2find_rects()的三个必调参数别信默认值# 在预处理后的 img 上执行识别 rects img.find_rects(threshold10000, roi(20,10,120,100)) # 关键参数在此 # threshold10000轮廓面积阈值非像素值单位是像素数×100 # roi(20,10,120,100)限定识别区域x,y,w,h避开画面边缘畸变区参数默认值推荐值为什么这样设调错后果threshold100008000~15000实测A4纸上3cm×3cm矩形在QQVGA下轮廓面积≈12000设太低5000会把纸张折痕当矩形太高20000漏掉倾斜矩形识别率暴跌或误检暴增roi全图固定(20,10,120,100)OpenMV镜头边缘存在桶形畸变矩形变形严重裁剪中心区域保证几何精度边缘矩形角度误差15°STM32后续计算失效x_stride,y_stride2保持2步长影响轮廓提取密度设为1虽更准但耗时翻倍12ms2是精度与速度平衡点帧率从35fps→22fps实时性崩塌参数说明threshold的单位易被误解——它不是灰度阈值而是contour.area()的最小值OpenMV 内部将面积×100后比较。实测打印矩形在QQVGA下面积稳定在11000~13500故设10000是安全下限roi的(20,10,120,100)是针对H7广角镜头标定出的经验值左/上留20/10像素避畸变右/下各留20/10像素保安全边距切勿开启mergeTrueOpenMV 的合并逻辑会把相邻小矩形强行拼成大矩形破坏几何独立性STM32端无法区分目标。3. STM32 端串口不是管道是需要握手、校验、兜底的通信信道OpenMV 通过 UART 向 STM32 发送矩形坐标但很多开发者直接用HAL_UART_Receive()等待固定字节数结果要么收不全丢包要么粘包多帧混成一帧。根本问题在于没有定义协议帧结构也没有应对嵌入式通信不确定性的容错机制。3.1 定义轻量二进制协议4字节帧头 4字节长度 N字节负载 2字节CRC16OpenMV 发送端Pythondef send_rects(rects): if not rects: # 无矩形时发送空帧避免STM32死等 payload bytes([0x00]) # 长度0 else: payload bytearray() payload.append(len(rects)) # 第1字节矩形数量最多255个 for r in rects: # 每个矩形发8字节x(2), y(2), w(2), h(2) —— 全部转为uint16_t小端序 payload.extend(r.x().to_bytes(2, little)) payload.extend(r.y().to_bytes(2, little)) payload.extend(r.w().to_bytes(2, little)) payload.extend(r.h().to_bytes(2, little)) # 构建完整帧0xAA55帧头 len(payload)(2) payload CRC16(2) frame bytearray([0xAA, 0x55]) frame.extend(len(payload).to_bytes(2, little)) frame.extend(payload) crc calc_crc16(frame[2:]) # CRC仅校验长度域及之后 frame.extend(crc.to_bytes(2, little)) uart.write(frame) # uart UART(3, 115200, timeout_char100)逻辑说明帧头0xAA55是强同步标识比单字节帧头抗干扰长度域为2字节支持最大64KB负载远超矩形数据需求1个矩形8字节255个仅2040字节所有坐标用uint16_t小端序STM32 Cortex-M4 的__packed结构体可直接映射无需字节序转换CRC16 采用标准CRC-16/IBM多项式0x8005calc_crc16()函数见文末附录。3.2 STM32 HAL 库的串口状态机实现拒绝阻塞式接收// 定义接收状态机 typedef enum { FRAME_SYNC, // 等待0xAA55 GET_LEN, // 读取2字节长度 GET_PAYLOAD, // 读取指定长度负载 GET_CRC // 读取2字节CRC } uart_state_t; uart_state_t rx_state FRAME_SYNC; uint8_t rx_buffer[256]; // 最大负载255字节1字节计数 uint16_t rx_len 0; uint16_t payload_len 0; uint16_t rx_index 0; // 在UART中断回调中处理 void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) { if (huart-Instance USART3) { uint8_t byte rx_buffer[0]; switch(rx_state) { case FRAME_SYNC: if (byte 0xAA) { rx_state GET_LEN; rx_index 0; } break; case GET_LEN: if (rx_index 0) { if (byte 0x55) { rx_index 1; // 等待第2字节长度低字节 } else { rx_state FRAME_SYNC; // 失败重置 } } else if (rx_index 1) { payload_len byte; // 低字节 rx_index 2; } else if (rx_index 2) { payload_len | (byte 8); // 高字节 if (payload_len 255) { // 防止溢出 rx_state FRAME_SYNC; break; } rx_state GET_PAYLOAD; rx_index 0; } break; case GET_PAYLOAD: if (rx_index payload_len) { rx_buffer[rx_index] byte; if (rx_index payload_len) { rx_state GET_CRC; rx_index 0; } } break; case GET_CRC: if (rx_index 0) { uint16_t recv_crc byte; rx_index 1; } else if (rx_index 1) { uint16_t recv_crc (byte 8) | rx_buffer[0]; uint16_t calc_crc calc_crc16(rx_buffer[0], payload_len); if (recv_crc calc_crc) { parse_rects(rx_buffer, payload_len); // 解析矩形 } rx_state FRAME_SYNC; // 无论成功失败都重置 } break; } // 重新启动单字节接收 HAL_UART_Receive_IT(huart3, rx_buffer, 1); } }关键设计点状态机驱动完全规避HAL_UART_Receive()的阻塞风险每个字节到来即处理响应延迟10μs长度校验前置收到长度后立即判断是否超限255防止缓冲区溢出CRC校验范围精准只校验payload不包含帧头和长度域因帧头已用于同步长度域本身是同步的一部分失败即重置任何环节异常如长度超限、CRC错立刻回到FRAME_SYNC避免状态漂移。4. 避坑OpenMVSTM32 矩形识别的 4 个真实翻车现场与解法嵌入式视觉调试最痛苦的不是功能不实现而是现象飘忽不定。以下是某跨平台系统项目组实测记录的高频坑点每一条都对应一次凌晨两点的重启。4.1 现象OpenMV IDE 里find_rects()返回正常接上 STM32 后rects恒为空原因OpenMV 默认使用自动曝光AE接上STM32后串口通信产生电磁干扰导致AE算法误判环境变暗自动拉高增益——画面过曝矩形墨迹与纸张灰度差消失binary()失效。解决在 OpenMV 初始化后强制关闭 AE 并设固定曝光sensor.set_auto_exposure(False, exposure_us10000) # 曝光10ms需根据实际光照微调 sensor.set_auto_gain(False, gain_db10) # 增益10dB避免过曝4.2 现象STM32 收到的矩形坐标 x/y 值随机跳变有时达655350xFFFF原因未启用timeout_char参数OpenMV 发送帧时若STM32 UART中断被高优先级任务抢占导致字节接收间隔超时HAL库将剩余字节填0x.to_bytes(2,little)解析出0xFFFF。解决初始化 UART 时必须设timeout_charuart UART(3, 115200, timeout_char100) # 字符间超时100ms确保单帧内不超时4.3 现象倾斜矩形如30°旋转被识别为平行四边形而非矩形r.rotation()返回值混乱原因find_rects()的旋转角定义是“矩形长边与x轴夹角”但当矩形接近正方形时长边判定不稳定导致角度在0°/90°间抖动。解决放弃r.rotation()改用r.vertices()获取4个顶点坐标自行计算主方向verts r.vertices() # [(x0,y0), (x1,y1), (x2,y2), (x3,y3)] # 计算对角线向量取平均方向作为主轴 dx (verts[2][0] - verts[0][0] verts[3][0] - verts[1][0]) / 2 dy (verts[2][1] - verts[0][1] verts[3][1] - verts[1][1]) / 2 angle math.atan2(dy, dx) * 180 / math.pi4.4 现象多个矩形并存时STM32 解析出的数量与 OpenMVlen(rects)不一致原因OpenMV 的find_rects()返回矩形按面积降序排列但某些小矩形因threshold边界效应被漏检更致命的是STM32 端未处理“空帧”无矩形时 payload_len0导致状态机卡在GET_PAYLOAD。解决OpenMV 端必须发送空帧payload[0x00]STM32 端在GET_PAYLOAD状态收到payload_len0时直接跳至GET_CRCcase GET_PAYLOAD: if (payload_len 0) { rx_state GET_CRC; break; } // ...原有逻辑5. 进阶验证用“动态标定板”量化识别精度而不是靠肉眼盯屏幕矩形识别最终要服务于定位、抓取或导航光看OpenMV IDE里的框没意义。必须建立可复现的精度验证方法——我们用一块激光切割的亚克力标定板带4个精确到±0.1mm的同心圆靶标替代打印纸通过测量识别坐标与物理坐标的偏差反推系统误差源。5.1 标定板设计与部署让误差可归因标定板尺寸 200mm×200mm四角各有一个直径20mm的黑色圆形靶标中心挖空露出白色底板圆心间距严格为180mm。将其垂直固定于支架OpenMV置于正前方500mm处镜头光轴对准板中心。此设置下理想图像中4个圆心应构成正方形边长≈162像素QQVGA下理论换算若识别出的矩形中心点(xw/2, yh/2)与圆心物理坐标偏差3像素即0.9mm则需排查。5.2 STM32 端误差分析脚本用串口回传原始数据到PC在STM32中增加调试模式当按键按下将最近10帧的x,y,w,h以CSV格式通过USB虚拟串口发回PC用Python绘图import serial import matplotlib.pyplot as plt import numpy as np ser serial.Serial(COM7, 115200) data [] for _ in range(10): line ser.readline().decode().strip() if line.startswith(RECT:): vals list(map(int, line[5:].split(,))) data.append(vals) # [x,y,w,h] data np.array(data) plt.scatter(data[:,0]data[:,2]/2, data[:,1]data[:,3]/2, cr, s10) # 绘制中心点 plt.axis(equal) plt.title(10-frame center dispersion (pixel)) plt.show()典型误差分布解读若10个中心点呈水平带状分布 → OpenMV镜头存在水平方向畸变需在find_rects()前加img.lens_corr(1.8)校正若呈放射状发散 → STM32 供电不稳导致UART采样抖动需加磁珠滤波若随机散点且RMS误差2像素 → 系统达标可投入应用。5.3 关键参数固化表把调试成果变成可复用的配置将标定结果固化为OpenMV端的配置常量避免每次重烧# config.py —— 由标定实验确定 CAMERA_FOCAL_LENGTH 3.8 # mmH7镜头实测 CAMERA_SENSOR_WIDTH 3.6 # mmOV7725传感器宽度 PIXEL_TO_MM CAMERA_SENSOR_WIDTH / 160 # QQVGA下1像素0.0225mm # 标定得出的畸变系数经10组不同距离测试 DISTORTION_K1 0.12 DISTORTION_K2 -0.03 # 在主程序中调用 img.lens_corr(strengthDISTORTION_K1, zoom1.0)我带过的三个学生项目组最后都卡在“为什么IDE里好好的一集成就崩”——直到他们亲手用标定板测出那3像素的系统性偏移才明白嵌入式视觉不是调参是建模。现在我的工作台永远放着那块亚克力板每次新换镜头、新布线、新电源第一件事就是测它。希望帮到你。本文还有配套的精品资源点击获取

相关新闻

洛阳 GEO 优化是什么?一文看懂生成式引擎优化

洛阳 GEO 优化是什么?一文看懂生成式引擎优化

GEO(Generative Engine Optimization,生成式引擎优化) 是通过结构化内容、实体一致性与权威信源建设,让品牌信息被豆包、DeepSeek、腾讯元宝、Kimi、文心一言等生成式 AI 平台检索、采信并引用的优化方法。在洛阳本地场景中&#…

2026/10/14 18:58:13 阅读更多 →
涉密资质投入产出分析模型:时间成本、四块成本构成与 ROI 决策框架

涉密资质投入产出分析模型:时间成本、四块成本构成与 ROI 决策框架

定义: 涉密资质投入产出分析,是指企业在决策是否申请涉密信息系统集成资质、军工保密资质或国家秘密载体印制资质时,对时间成本、经济成本和预期收益进行量化评估的决策方法。其核心是将资质申请的 “达标周期 审批周期” 与 “首年投入 持…

2026/10/14 18:58:13 阅读更多 →
钉钉3.5.6深度解析:WebView内核、JSBridge白名单与离线消息机制

钉钉3.5.6深度解析:WebView内核、JSBridge白名单与离线消息机制

简介:本资源为钉钉3.5.6经典绿色版安装包,面向中小企业员工、教育机构教师及对系统轻量化有要求的办公用户,解决传统办公软件安装繁琐、占用资源高、兼容性差等痛点,尤其适用于老旧设备或需便携运行的多场景办公环境。压缩包为7z格…

2026/10/14 18:57:12 阅读更多 →

最新新闻

ECharts柱状图配置全解析:从基础到动态排序与性能优化

ECharts柱状图配置全解析:从基础到动态排序与性能优化

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

2026/10/15 1:57:11 阅读更多 →
LVGL 图像按钮(lv_imgbtn)实战指南:Simple Image button 示例全解与源码原理

LVGL 图像按钮(lv_imgbtn)实战指南:Simple Image button 示例全解与源码原理

嵌入式物联网智能硬件嵌入式GUI硬件开发 【免费下载链接】HoloCubic 带网络功能的伪全息透明显示桌面站 项目地址: https://gitcode.com/gh_mirrors/ho/HoloCubic 点击查看 免费下载 本篇文章围绕 HoloCubic 固件所采用的 LVGL 图形库中的 lv_imgbtn(图…

2026/10/15 1:57:11 阅读更多 →
深入解析 LAMMPS `compute msd/chunk`:逐块均方位移的计算原理与实战配置

深入解析 LAMMPS `compute msd/chunk`:逐块均方位移的计算原理与实战配置

科研科学计算高性能计算 【免费下载链接】lammps Public development project of the LAMMPS MD software package 项目地址: https://gitcode.com/gh_mirrors/la/lammps 点击查看 免费下载 导读 compute msd/chunk 是 LAMMPS 中用于按 chunk(原子分组…

2026/10/15 1:57:11 阅读更多 →
车机双系统下用ASAN抓内存踩踏:8155p上Android.mk与Android.bp配置实战

车机双系统下用ASAN抓内存踩踏:8155p上Android.mk与Android.bp配置实战

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

2026/10/15 1:57:11 阅读更多 →
Go 1.27.1 内存局部性调优实录:压榨 CPU 缓存行命中率的工程实践

Go 1.27.1 内存局部性调优实录:压榨 CPU 缓存行命中率的工程实践

在微服务吞吐量达到数万 QPS 的高性能网关或高频事件调度引擎中,单纯依赖算法时间复杂度(如将 $O(N)$ 降为 $O(1)$)已经无法进一步带来数量级的性能突破。很多底层服务开发者发现,即便 CPU 利用率跑满了 100%,服务处理…

2026/10/15 1:57:11 阅读更多 →
Start Bootstrap 主题 One Page Wonder 详解:基于 Bootstrap 4 快速构建单页网站

Start Bootstrap 主题 One Page Wonder 详解:基于 Bootstrap 4 快速构建单页网站

前端文档 【免费下载链接】startbootstrap A library of free and open source Bootstrap themes and templates 项目地址: https://gitcode.com/gh_mirrors/st/startbootstrap 点击查看 免费下载 One Page Wonder 是 Start Bootstrap 开源仓库中的一款经典单页主题…

2026/10/15 1:56:09 阅读更多 →

日新闻

Docker Compose 容器化部署 ChirpStack LoRaWAN 网络服务器实战

Docker Compose 容器化部署 ChirpStack LoRaWAN 网络服务器实战

1. 为什么选择容器化方式部署 LoRa 网络服务LoRa 物联网项目落地时,网络服务器是整个链路的核心枢纽。它负责接收网关上报的数据包、完成去重与解密、再把有效载荷分发给上层应用。早期大家习惯把网络服务器直接装在物理机上,依赖一堆系统库和特定版本的…

2026/10/15 0:00:46 阅读更多 →
共享LLM服务下的跨模型自动扩缩容:Kubernetes实战与避坑指南

共享LLM服务下的跨模型自动扩缩容:Kubernetes实战与避坑指南

1. 共享推理服务里,扩缩容到底难在哪做过大模型推理服务部署的人,大概都经历过这样的场景:一个团队共用一套推理集群,A 业务跑的是 7B 的小模型,B 业务跑的是 72B 的大模型,C 业务白天流量高、晚上几乎归零…

2026/10/15 0:00:46 阅读更多 →
Systemd 启动阶段根文件系统只读之谜:fstab 与 remount-fs 服务深度解析

Systemd 启动阶段根文件系统只读之谜:fstab 与 remount-fs 服务深度解析

1. 引子:一次内核恐慌引发的追查先从一个真实场景说起。某次我给一台老旧的嵌入式设备折腾系统裁减,为了把启动时间压进两秒以内,我手贱地把一串自认为“没用”的 systemd 服务给 disable 了,其中就包括systemd-remount-fs.servic…

2026/10/15 0:00:46 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/14 3:30:28 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/14 16:30:29 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/14 3:29: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/15 0:14:36 阅读更多 →
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/14 22:45:47 阅读更多 →
黑夜航拍船只数据集训练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/14 7:53:34 阅读更多 →