Java+OpenCV实战:几何图像颜色与形状识别全流程
简介这份PDF面向Java开发者与计算机视觉初学者聚焦如何用Java调用OpenCV视觉库完成几何图像的颜色与形状识别可解决传统RGB识别率不高、Java实现案例偏少的问题。资源共1个PDF文件压缩包约894KB内容以论文形式呈现涵盖HSV颜色空间转换、颜色分离、滤波灰度化、二值化、轮廓提取、干扰轮廓去除、轮廓形状拟合及凸点距离判断等完整流程并给出三角形、圆、矩形、正方形、多边形等几何图形的识别思路。目前已有169人学习下载适合想入门OpenCV-Java图像处理、需要颜色与形状识别参考方案的读者可借鉴用于交通信号灯、信号转向灯等实际场景快速理解从颜色分割到形状判别的技术链路。1. 从一张交通灯照片说起Java 也能做几何图像颜色与形状识别路口抓拍一张照片要判断当前是红灯还是绿灯、箭头指向哪边这件事用 Python OpenCV 做很常见但换成 Java 技术栈的项目就少有人讲。这份资料围绕的就是这样一个场景用 Java 调用 OpenCV 视觉库把一张彩色几何图像先转到 HSV 颜色空间按 H、S、V 的取值范围把红、黄、绿、橙等颜色分离出来再对每种颜色的子图做滤波、灰度化、二值化、轮廓提取、干扰轮廓剔除、多边形拟合最后靠凸点个数和相邻凸点距离判断它是三角形、圆、矩形、正方形还是多边形。整套流程不依赖深度学习模型纯传统图像处理跑在普通 PC 上就能出结果适合做工业分拣、交通信号识别、教学演示这类需要轻量、可解释、能二次开发的场景。如果你手头正好有 Java 项目要接入视觉能力又不想引入 Python 运行时这份资料值得跟着跑一遍。2. 环境搭建与 OpenCV Java 包导入让 Eclipse 认识 native 库2.1 为什么 Java 调 OpenCV 容易翻车OpenCV 本身是 C 写的Java 能调用它靠的是一层 JNI 封装。这意味着你导入的不只是opencv-300.jar这个 Java 接口包还必须让 JVM 在运行时找到对应的动态链接库Windows 下是opencv_java300.dllLinux 下是libopencv_java300.so。很多人第一次跑就报java.lang.UnsatisfiedLinkError十有八九是只加了 jar 没配 native 库路径。这份资料里作者用的是 32 位系统所以选了OpenCV-x86包这一点很关键——位数不匹配是另一个高频翻车点64 位 JVM 加载 32 位 dll 会直接崩。2.2 导入步骤拆解在 OpenCV 官网下载对应版本解压后进入build\java目录你会看到类似这样的结构build/java/ ├── opencv-300.jar ├── x64/ │ └── opencv_java300.dll └── x86/ └── opencv_java300.dll在 Eclipse 里右键项目 → Build Path → Configure Build Path → Libraries → Add External JARs选中opencv-300.jar。接着展开这个 jar双击Native library location指向你系统对应的x86或x64目录。这一步做完代码里System.loadLibrary(Core.NATIVE_LIBRARY_NAME)才能找到库。// 静态代码块里加载 native 库类加载时执行一次 static { // Core.NATIVE_LIBRARY_NAME 在 OpenCV Java 里就是 opencv_java300 System.loadLibrary(Core.NATIVE_LIBRARY_NAME); } public static void main(String[] args) { // 验证库是否加载成功能打印出版本号说明环境通了 System.out.println(OpenCV version: Core.VERSION); }逻辑说明System.loadLibrary的参数是库名而非文件名JVM 会自动补全平台后缀。参数Core.NATIVE_LIBRARY_NAME是 OpenCV Java 封装好的常量避免手写字符串写错版本号。如果这行抛异常先检查 Native library location 是否指向了正确的位数目录再检查系统 PATH 里有没有冲突的同名 dll。提示如果你用 Maven 管理项目常见做法是把 jar 装进本地仓库再用maven-surefire-plugin的argLine指定-Djava.library.path比手动配 Build Path 更利于团队协作。2.3 一个最小可运行骨架环境通了之后先别急着写识别逻辑用下面这个骨架确认能读图、能显示public class OpenCVSmokeTest { static { System.loadLibrary(Core.NATIVE_LIBRARY_NAME); } public static void main(String[] args) { // 用 imread 读图第二个参数 IMREAD_COLOR 表示强制读成三通道彩色 Mat src Imgproc.imread(test.png, Imgproc.IMREAD_COLOR); if (src.empty()) { System.out.println(图片没读到检查路径); return; } // 打印图像宽高和通道数确认数据进来了 System.out.println(宽: src.cols() 高: src.rows() 通道: src.channels()); } }参数说明Imgproc.imread的第二个参数决定读图模式IMREAD_COLOR强制三通道IMREAD_GRAYSCALE直接读灰度。路径建议用绝对路径相对路径在不同 IDE 工作目录下表现不一致这是新手最容易踩的坑之一。3. 颜色分离核心链路从 BGR 到 HSV 再到 inRange 掩膜3.1 先缩小图像别小看这一步后面要逐像素遍历 HSV 值图像越大循环越慢。作者的做法是先Imgproc.resize把图缩小处理速度能提升一个量级。这不是偷懒是工程上很实在的优化。Mat src Imgproc.imread(shapes.png, Imgproc.IMREAD_COLOR); Mat resized new Mat(); // 缩放到宽 400高按比例自动算保持长宽比不失真 Imgproc.resize(src, resized, new Size(400, src.rows() * 400.0 / src.cols()));参数说明Size的第二个参数如果传 0OpenCV 会按第一个参数的比例自动算但这里显式算出来更直观。缩放比例别太狠缩到 100 像素以下轮廓会糊成一团凸点检测就不准了。3.2 BGR 转 HSV为什么不用 RGB 直接判色OpenCV 默认读进来是 BGR 顺序而 HSV 把色调H、饱和度S、明度V拆开颜色判断只看 H 通道就够了S 和 V 用来排除灰白和过暗的干扰。用 RGB 判红色你得同时卡 R 高、G 低、B 低三个条件光照一变就失效用 HSV红色就是 H 在 0 附近或 170 以上那一段鲁棒得多。Mat hsv new Mat(); // 先 BGR 转 RGB如果源图是 RGB 顺序再转 HSV Imgproc.cvtColor(resized, hsv, Imgproc.COLOR_BGR2HSV);参数说明COLOR_BGR2HSV是最常用的转换码。如果你的图是从别的库读进来的 RGB 顺序要先COLOR_RGB2BGR再转 HSV否则红蓝会对调这是血泪经验。3.3 逐像素统计 阈值过滤作者的做法是遍历 HSV 图按各颜色的 H、S、V 范围累计像素个数超过 200 才认为图里有这个颜色。这个阈值是防反光和环境色干扰的后悔药。int colorPixelCount 0; for (int i 0; i hsv.rows(); i) { for (int j 0; j hsv.cols(); j) { double[] hsvVal hsv.get(i, j); int h (int) hsvVal[0]; int s (int) hsvVal[1]; int v (int) hsvVal[2]; // 绿色范围H 35~77S 43~255V 46~255 if (h 35 h 77 s 43 v 46) { colorPixelCount; } } } if (colorPixelCount 200) { System.out.println(图中存在绿色图形); }逻辑说明hsv.get(i, j)返回的是double[]三个元素依次是 H、S、V。阈值 200 是经验值图小的时候可以调低图大的时候要调高否则一个小色块也会被误判。这个循环是纯 Java 遍历图大了会慢生产环境常见做法是改用Core.inRange直接生成掩膜再Core.countNonZero统计效率高很多。3.4 inRange 分割 bitwise_and 取色统计确认有该颜色后用Core.inRange生成掩膜再用Core.bitwise_and把原图和掩膜做与运算得到只保留该颜色的子图。Mat mask new Mat(); Mat colorOnly new Mat(); // 绿色上下界Scalar 三个参数对应 H、S、V Scalar lowerGreen new Scalar(35, 43, 46); Scalar upperGreen new Scalar(77, 255, 255); // inRange 把落在范围内的像素置 255其余置 0 Core.inRange(hsv, lowerGreen, upperGreen, mask); // 用掩膜从原图里抠出绿色部分 Core.bitwise_and(resized, resized, colorOnly, mask);参数说明Scalar的三个值就是 H、S、V 的下界或上界。红色比较特殊H 跨越 0 和 180 两端需要分两段inRange再Core.add合并这是红色分割最容易翻车的地方。bitwise_and的第四个参数是掩膜只有掩膜非零的位置才保留原图像素。4. 形状识别链路滤波、二值化、轮廓拟合与凸点判形4.1 三通道转换与高斯滤波bitwise_and出来的colorOnly可能是单通道直接灰度化会报错先转三通道。然后高斯滤波去掉反光和噪点。// 单通道转三通道CV_8UC3 表示 8 位无符号三通道 colorOnly.convertTo(colorOnly, CvType.CV_8UC3); Mat blurred new Mat(); // 高斯核 5x5标准差自动算 Imgproc.GaussianBlur(colorOnly, blurred, new Size(5, 5), 0);参数说明高斯核必须是奇数5x5 适合中小图图大噪点多可以上 7x7。标准差传 0 让 OpenCV 按核大小自动推导一般够用。4.2 灰度化 二值化找轮廓前必须二值化二值化前必须灰度化顺序不能乱。Mat gray new Mat(); Imgproc.cvtColor(blurred, gray, Imgproc.COLOR_BGR2GRAY); Mat binary new Mat(); // 阈值 127最大值 255THRESH_BINARY 表示大于阈值置 255 Imgproc.threshold(gray, binary, 127, 255, Imgproc.THRESH_BINARY);参数说明阈值 127 是通用起点如果图形偏暗或偏亮用Imgproc.THRESH_OTSU让 OpenCV 自动算阈值更省心。THRESH_BINARY是最常用的二值化模式。4.3 腐蚀膨胀去干扰 findContours零散像素点会干扰轮廓提取先腐蚀掉小的再膨胀把断开的轮廓连上。Mat kernel Imgproc.getStructuringElement(Imgproc.MORPH_RECT, new Size(3, 3)); // 腐蚀一次去掉孤立噪点 Imgproc.erode(binary, binary, kernel); // 膨胀一次把轮廓补连通 Imgproc.dilate(binary, binary, kernel); ListMatOfPoint contours new ArrayList(); Mat hierarchy new Mat(); // RETR_EXTERNAL 只取最外层轮廓CHAIN_APPROX_SIMPLE 压缩水平垂直斜向的冗余点 Imgproc.findContours(binary, contours, hierarchy, Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_SIMPLE);参数说明MORPH_RECT是矩形结构元素也可以用椭圆。腐蚀膨胀次数别太多两次以上小图形会被吃掉。RETR_EXTERNAL适合几何图形识别因为图形内部没有嵌套轮廓。4.4 剔除干扰轮廓面积太小的是噪点太大的是背景边框都要去掉。for (int j 0; j contours.size(); j) { double area Imgproc.contourArea(contours.get(j)); // 面积小于 10 或大于 80000 的轮廓视为干扰 if (area 10 || area 80000) { contours.remove(j); j--; // 删除后索引回退否则会跳过一个元素 } }逻辑说明contours.remove(j)之后列表长度变了不j--会漏检下一个轮廓这是 Java 集合遍历删除的经典坑。面积上下界要根据图像分辨率调缩放到 400 宽的图80000 这个上界基本能覆盖大部分图形。4.5 多边形拟合 凸点距离判形这是整个流程的核心判断逻辑。用approxPolyDP把轮廓拟合成多边形看剩下几个顶点再结合相邻顶点距离区分正方形和矩形、圆和多边形。for (MatOfPoint contour : contours) { MatOfPoint2f contour2f new MatOfPoint2f(contour.toArray()); MatOfPoint2f approx new MatOfPoint2f(); // epsilon 是拟合精度取周长的 2%越小越贴合原轮廓 double epsilon 0.02 * Imgproc.arcLength(contour2f, true); Imgproc.approxPolyDP(contour2f, approx, epsilon, true); Point[] points approx.toArray(); int vertexCount points.length; if (vertexCount 3) { System.out.println(三角形); } else if (vertexCount 4) { // 四个顶点比较相邻边长判断正方形还是矩形 double side1 distance(points[0], points[1]); double side2 distance(points[1], points[2]); if (Math.abs(side1 - side2) 5) { System.out.println(正方形); } else { System.out.println(矩形); } } else if (vertexCount 6) { System.out.println(圆形或多边形); } } // 两点欧氏距离 private static double distance(Point a, Point b) { return Math.sqrt(Math.pow(a.x - b.x, 2) Math.pow(a.y - b.y, 2)); }参数说明epsilon是拟合精度的关键取周长的 1%~2% 比较合适太小会把圆拟合成很多边的多边形太大则三角形会被拟合成一条线。approxPolyDP的最后一个参数true表示轮廓闭合。圆形判断比较玄学因为圆拟合后顶点数不固定常见做法是顶点数大于 6 且各边长度接近就判为圆或者用Imgproc.minEnclosingCircle算圆度辅助判断。5. 避坑与常见问题排查那些让你怀疑人生的报错5.1 UnsatisfiedLinkError: no opencv_java300 in java.library.path现象程序一启动就抛这个异常连 main 都进不去。原因JVM 没找到 native 动态库只配了 jar 没配 dll 路径或者位数不匹配。解决确认 Build Path 里 Native library location 指向了正确的 x86/x64 目录或者启动时加-Djava.library.path你的dll目录。32 位 JVM 配 64 位 dll 也会报这个别问我是怎么知道的。5.2 红色图形死活分割不出来现象绿色、黄色都能分离红色掩膜全黑。原因HSV 里红色 H 值跨越 0 和 180 两端单段inRange覆盖不全。解决分两段处理一段 H 取 0~10一段取 170~180分别inRange后用Core.add合并掩膜。5.3 轮廓提取出来一堆碎点现象findContours返回几百个轮廓全是噪点。原因二值化阈值不合适或者没做腐蚀膨胀。解决先高斯滤波再腐蚀一次去掉孤立点膨胀一次连通轮廓。如果还不行把二值化换成THRESH_OTSU自动阈值。5.4 正方形被判成矩形现象明明是正方形边长比较时差了几个像素就判成矩形。原因图像缩放和轮廓拟合有误差边长不可能完全相等。解决比较边长时给一个容差比如差值小于 5 像素就算相等。容差大小根据图像分辨率调图越大容差可以适当放大。5.5 遍历删除轮廓时漏检现象明明有 5 个轮廓删掉干扰后只剩 3 个漏了。原因for循环里remove之后索引没回退。解决删除后j--或者用Iterator的remove方法后者更规范。6. 二次开发改造从识别 Demo 到可落地模块的几个思路拿到这份资料跑通之后真正要落地还得改几处。第一把逐像素统计换成Core.inRangeCore.countNonZero速度能快十几倍尤其是高分辨率图。第二颜色范围别写死做成配置文件或数据库不同光照环境下 H、S、V 的边界要能调我一般会留一个标定模式让用户点一下图里的颜色自动算出范围。第三形状判断里圆形那块最不稳建议加一个圆度判断4 * PI * area / (perimeter * perimeter)接近 1 就是圆比单纯数顶点靠谱。// 圆度判断比数顶点更稳 double area Imgproc.contourArea(contour); double perimeter Imgproc.arcLength(new MatOfPoint2f(contour.toArray()), true); double circularity 4 * Math.PI * area / (perimeter * perimeter); if (circularity 0.85) { System.out.println(圆形); }参数说明circularity越接近 1 越像圆0.85 是经验阈值实际项目里可以调到 0.8~0.9 之间试。这个指标对光照和缩放都不敏感比凸点法鲁棒。第四把整个流程封装成一个ShapeRecognizer类输入Mat输出ListRecognitionResult每个结果包含颜色名、形状名、外接矩形和置信度。这样上层业务代码不用关心 OpenCV 细节换算法也不影响调用方。第五如果要做实时视频流识别别每帧都跑全流程隔几帧跑一次中间帧用上一帧结果CPU 占用能降下来。验证改造是否成功我习惯用一组固定测试图跑回归红三角、绿圆、蓝矩形、黄正方形各一张再加一张带反光和噪点的干扰图。每次改完参数跑一遍看识别结果有没有退化。这个习惯是从一次改阈值把绿色识别搞挂之后养成的从那以后我每次调 HSV 范围都强制走一遍回归测试再也不敢凭感觉改。希望帮到你。本文还有配套的精品资源点击获取

相关新闻

MATLAB文件与数据接口全攻略:从Excel到Parquet的读写避坑指南

MATLAB文件与数据接口全攻略:从Excel到Parquet的读写避坑指南

简介:聚焦MATLAB文件与数据接口技术,面向需要打通外部数据源的中高级开发者,系统覆盖文本文件、二进制数据、XML配置、数据库查询、Excel表格、网络请求及图像视频流等常见数据读写场景。压缩包共264个文件,以83个m脚本与函数为核…

2026/10/17 16:02:20 阅读更多 →
STM32智能小车寻迹避障方案:硬件设计、状态机与代码实战

STM32智能小车寻迹避障方案:硬件设计、状态机与代码实战

简介:面向嵌入式初学者和电子竞赛选手的STM32智能小车寻迹避障方案,覆盖硬件原理图、C语言工程代码与调试说明,适合课程设计、毕业设计或科创项目快速起步。整套资源共181个文件,压缩包约2.05MB;主体为74个.c源文件和7…

2026/10/16 14:07:08 阅读更多 →
C#实现HL7通讯测试解析:从协议基础到MLLP收发

C#实现HL7通讯测试解析:从协议基础到MLLP收发

简介:这是一份面向C#开发者的HL7医疗数据通讯解析示例资源,主要解决医院信息系统对接中HL7消息通过TCP/MLLP协议传输与解析的难题。资源基于VS2010环境编写,除核心HL7消息接收与解析逻辑外,还附带socket服务端与客户端的完整演示代…

2026/10/17 16:02:25 阅读更多 →

最新新闻

Nmap NSE脚本实战:从端口扫描到网络审计的进阶指南

Nmap NSE脚本实战:从端口扫描到网络审计的进阶指南

1. 为什么我劝你别只把Nmap当端口扫描器用 很多人第一次接触Nmap,都是从一条 nmap 192.168.1.1 开始的。扫出一堆开放端口,看到22、80、443,然后呢?然后就没有然后了。如果你也停在这一步,那说实话,你只用…

2026/10/17 16:02:21 阅读更多 →
PHP整站源码带数据库部署指南:从环境配置到Docker容器化

PHP整站源码带数据库部署指南:从环境配置到Docker容器化

简介:这是一套基于PHPMySQL开发的六合类网站完整源码,采用phpMyAdmin管理数据库,系统划分为后台管理、代理与会员三大模块,适合有一定PHP基础、希望研究整站架构与数据库设计的开发者用于技术学习与二次开发参考。压缩包共1086个文…

2026/10/17 16:02:21 阅读更多 →
OpenCV特征区域分析:几何、矩、形状与纹理特征值计算与稳定性实战

OpenCV特征区域分析:几何、矩、形状与纹理特征值计算与稳定性实战

1. 从"能跑通"到"测得准":特征区域特征值到底在算什么很多人第一次接触特征区域分析,都是被一个很朴素的需求推着走的:图里有一块我关心的区域,我想知道它到底"长什么样"。这个"长什么样"…

2026/10/17 16:02:21 阅读更多 →
高级前端面试官视角:从状态管理到工程化的出题逻辑与刷题策略

高级前端面试官视角:从状态管理到工程化的出题逻辑与刷题策略

我断断续续做过一段时间前端面试官,部门里让我整理一套高级前端开发工程师的面试题,用来筛人和给内部晋升做参考。那段时间我一边出题一边复盘,最直观的感受是:很多候选人简历写得很漂亮,基础题也能答得不错&#xff0…

2026/10/17 16:02:21 阅读更多 →
不卖的天价胸罩:用锚定效应打造品牌营销核武器

不卖的天价胸罩:用锚定效应打造品牌营销核武器

如果你在一个公开场合,看到一件标价上千万美元的内衣被锁在防弹玻璃柜里,由专人看护、媒体围着拍,你会不会下意识地问一句:这东西到底卖给谁? 我第一次关注到维多利亚的秘密那件“Fantasy Bra”时,就是带着…

2026/10/17 16:02:21 阅读更多 →
STM32寄存器编程实战:GPIO、定时器与串口

STM32寄存器编程实战:GPIO、定时器与串口

每次看到论坛里有人说“寄存器难”,我都想拉住他聊五分钟。我入行那几年也被寄存器折磨过,直到有一次调一个功耗敏感的项目,手里的库函数版本和例程对不上,底层配置出来的引脚电平就是不对。从那以后我翻烂了参考手册,…

2026/10/17 16:01:21 阅读更多 →

日新闻

DeepSeek选型与部署:V3/R1、Ollama、API全攻略

DeepSeek选型与部署:V3/R1、Ollama、API全攻略

简介:《DeepSeek使用方法.pdf》是一份面向DeepSeek入门及进阶用户的完整使用指南,重点围绕V3与R1两款模型的能力差异与适用场景展开,帮助读者根据任务类型与成本选择合适的模型。资源共1个PDF文件,压缩包大小约311KB,篇…

2026/10/17 0:00:25 阅读更多 →
200+Deepseek润色指令拆解:从底层原理到场景落地的完整指南

200+Deepseek润色指令拆解:从底层原理到场景落地的完整指南

简介:这是一份聚焦DeepSeek提示词优化的《200Deepseek润色指令》PDF文档,共收录两百余条可直接套用的润色指令,涵盖语法修正、风格统一、逻辑梳理、表达精炼等维度,并针对商务写作、学术论文、广告文案等场景给出差异化建议。文档…

2026/10/17 0:00:25 阅读更多 →
OpenCV轮廓法物体计数系统:轻量、可控、可落地的工业级实现

OpenCV轮廓法物体计数系统:轻量、可控、可落地的工业级实现

简介:本资源是一份基于OpenCV的本科课程设计完整报告,面向计算机视觉初学者、图像处理学习者及高校通信/信息类专业学生,解决物体智能计数与检测结果结构化记录的实际问题。项目覆盖图像预处理、轮廓检测、边界框绘制、轨迹栏交互式参数调节、…

2026/10/17 0:00:25 阅读更多 →

周新闻

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

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

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

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

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

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

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

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

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

2026/10/16 15:04:24 阅读更多 →

月新闻

我发现了一个新思路:用 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/16 21:54:38 阅读更多 →
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/16 3:49:43 阅读更多 →
黑夜航拍船只数据集训练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/16 14:23:36 阅读更多 →