植物叶片病害检测数据集:29类VOC标注与YOLO训练全流程
简介这份资源面向从事植物病害识别、农业智能检测方向的目标检测学习者与开发者提供一套可直接投入训练的大型叶片病害缺陷数据集覆盖葡萄叶黑腐病、番茄叶菌斑、苹果锈叶病、马铃薯晚疫病等29个类别省去自行采集与标注的成本。包内共约2000个文件以1999个VOC格式xml标注文件和1个可视化py脚本为主压缩包约934.99MBdata目录下按训练集与验证集分文件夹存放训练集含2345张图片及对应xml验证集含239张图片及对应xml另附类别标签json字典文件。已有256人学习关注。可视化脚本无需修改即可运行随机传入一张图片便能绘制边界框并保存标注结果便于快速核验数据质量配合类别json与规范的目录结构可直接对接YOLO等主流检测框架开展训练与改进实验适合作为课程设计、科研验证或算法调优的现成数据基础。1. 植物叶片病害检测数据集29类VOC标注从拿到手到跑通第一条baseline植物叶片病害检测这个方向过去两年我从温室巡检机器人到手机端拍照问诊都碰过。真正卡住项目进度的往往不是模型结构而是数据集类别定义混乱、标注框贴边、训练集和验证集里同一片叶子反复出现导致指标虚高。这次要拆的是一份29类植物叶片病害缺陷检测数据集VOC标注格式自带训练集、验证集、类别json文件和可视化脚本。它解决的是「从零标注几千张叶片图」这个最耗人力的环节适合做农业AI质检、病害识别课程设计、以及想拿目标检测练手但缺真实场景数据的工程师。VOC格式意味着你能直接对接YOLO系列、Faster R-CNN、DETR等主流框架不用先写转换器。下面按「先看懂标注体系 → 再跑通可视化 → 再转YOLO训练 → 最后避坑」的顺序讲透。2. 拆解VOC标注与29类目录先搞清楚手里的数据长什么样2.1 VOC格式的三个核心文件和它们的关系VOC标注格式不是单个文件而是一套约定。你拿到手的数据集通常包含三个部分JPEGImages/放原图Annotations/放同名XMLImageSets/Main/放划分列表。XML里记录图片尺寸、每个目标的类别名和边界框坐标xmin、ymin、xmax、ymax。29类意味着XML里的name字段有29种取值比如leaf_spot、rust、powdery_mildew、bacterial_blight这类。类别json文件的作用是把这29个字符串映射成0到28的整数索引训练时模型只认数字。先做一件事确认XML数量和图片数量是否一致。常见翻车是图片有但XML缺失或者XML里filename和实际文件名对不上。用下面这段脚本快速体检import os import xml.etree.ElementTree as ET img_dir JPEGImages xml_dir Annotations imgs {os.path.splitext(f)[0] for f in os.listdir(img_dir) if f.lower().endswith((.jpg, .png, .jpeg))} xmls {os.path.splitext(f)[0] for f in os.listdir(xml_dir) if f.endswith(.xml)} print(图片数:, len(imgs), XML数:, len(xmls)) print(有图无XML:, list(imgs - xmls)[:10]) print(有XML无图:, list(xmls - imgs)[:10]) # 统计每个类别的框数量 from collections import Counter cls_counter Counter() for xf in os.listdir(xml_dir): if not xf.endswith(.xml): continue tree ET.parse(os.path.join(xml_dir, xf)) for obj in tree.findall(object): cls_counter[obj.find(name).text] 1 for k, v in cls_counter.most_common(): print(k, v)逻辑说明第一段用集合差集找出不配对的文件这是最容易被忽略的脏数据来源。第二段遍历所有XML统计类别分布你会立刻看出哪些类是长尾。参数上img_dir和xml_dir按实际路径改如果图片是.JPG大写后缀lower()已经处理了。类别分布出来后如果某类少于50个框训练时要么过采样要么直接合并到相近类否则mAP会被这一类拖死。2.2 类别json文件的正确读法和索引对齐类别json一般长这样{0: leaf_spot, 1: rust, ...}或者[leaf_spot, rust, ...]。两种都要能处理。关键是训练框架里的names列表顺序必须和json完全一致差一位整个标签就全错。我一般会写一个校验函数把json读进来后和XML里出现过的类别名做交集比对import json with open(classes.json, r, encodingutf-8) as f: classes json.load(f) # 兼容dict和list两种写法 if isinstance(classes, dict): # 按key排序后取value避免json里key乱序 names [classes[k] for k in sorted(classes.keys(), keylambda x: int(x))] else: names classes print(类别数:, len(names)) print(前5类:, names[:5]) # 和XML中实际出现的类别比对 xml_names set(cls_counter.keys()) json_names set(names) print(XML有但json没有:, xml_names - json_names) print(json有但XML没有:, json_names - xml_names)逻辑说明sorted那行是血泪经验有些json的key是字符串0到28但写入顺序不保证直接list(classes.values())可能得到乱序。比对结果里如果出现「XML有但json没有」说明标注里混入了未定义类别必须手动清理或补进json。参数上int(x)要求key必须是数字字符串如果key是类别名本身改成直接取values即可。2.3 可视化脚本怎么用先看框再谈训练数据集自带可视化脚本是好事但很多人直接跑完看一眼就过了。我建议把可视化当成标注质量检查工具。核心逻辑是读XML画矩形和类别名用OpenCV或PIL都行。下面是一个可复用的最小版本import cv2 import xml.etree.ElementTree as ET import os def draw_voc(img_path, xml_path, save_path): img cv2.imread(img_path) tree ET.parse(xml_path) root tree.getroot() for obj in root.findall(object): name obj.find(name).text bbox obj.find(bndbox) x1 int(float(bbox.find(xmin).text)) y1 int(float(bbox.find(ymin).text)) x2 int(float(bbox.find(xmax).text)) y2 int(float(bbox.find(ymax).text)) cv2.rectangle(img, (x1, y1), (x2, y2), (0, 255, 0), 2) cv2.putText(img, name, (x1, max(y1 - 5, 10)), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255), 1) cv2.imwrite(save_path, img) # 批量跑前20张 for i, xf in enumerate(os.listdir(Annotations)[:20]): stem os.path.splitext(xf)[0] for ext in [.jpg, .png, .jpeg]: ip os.path.join(JPEGImages, stem ext) if os.path.exists(ip): draw_voc(ip, os.path.join(Annotations, xf), fvis_{i}.jpg) break逻辑说明float()转换是因为部分XML里坐标写成123.0这种浮点字符串直接int()会报错。max(y1-5, 10)防止类别名画到图片外面。跑完重点看三种情况框是否贴边到像素级贴边框在缩放增强后会丢目标、同一片叶子是否被拆成多个框、类别名是否和视觉症状对得上。参数上矩形颜色和线宽随意但建议固定方便批量对比。3. 从VOC转YOLO格式转换脚本、路径规则和三个必调参数3.1 转换的核心公式和目录结构YOLO格式每张图对应一个.txt每行是class_id cx cy w h全部归一化到0到1。转换公式cx (xmin xmax) / 2 / img_wcy (ymin ymax) / 2 / img_hw (xmax - xmin) / img_wh (ymax - ymin) / img_h。目录结构建议直接按YOLO惯例来images/train、images/val、labels/train、labels/val。训练集和验证集的划分如果数据集已经给了ImageSets/Main/train.txt和val.txt直接读不要自己随机分否则验证集里出现训练集同株叶片的近重复图指标会虚高。import os import xml.etree.ElementTree as ET import shutil def voc_to_yolo(xml_path, img_w, img_h, class_names): tree ET.parse(xml_path) lines [] for obj in tree.findall(object): name obj.find(name).text if name not in class_names: continue cid class_names.index(name) b obj.find(bndbox) x1 float(b.find(xmin).text) y1 float(b.find(ymin).text) x2 float(b.find(xmax).text) y2 float(b.find(ymax).text) # 裁剪到图像边界内 x1, y1 max(0, x1), max(0, y1) x2, y2 min(img_w, x2), min(img_h, y2) cx (x1 x2) / 2 / img_w cy (y1 y2) / 2 / img_h w (x2 - x1) / img_w h (y2 - y1) / img_h if w 0 or h 0: continue lines.append(f{cid} {cx:.6f} {cy:.6f} {w:.6f} {h:.6f}) return lines # 读取图片尺寸需要PIL from PIL import Image def get_size(img_path): with Image.open(img_path) as im: return im.size # (w, h)逻辑说明max(0, x1)和min(img_w, x2)是必须的VOC标注里偶尔出现负坐标或超出图像宽高的框不裁剪会导致归一化后值大于1YOLO训练时直接报错或学出诡异框。w 0过滤掉零面积框。参数上class_names必须和json顺序一致:.6f保留6位小数足够再多没必要。3.2 划分训练集和验证集时最容易犯的错如果数据集没有给划分文件自己分的时候千万别用random.shuffle一刀切。植物叶片病害有个特点同一株、同一片叶、同一发病阶段可能拍了多张。正确做法是按「株」或按「拍摄批次」分组后再分。简单可操作的方案是如果文件名里带株号或日期按这个字段分组如果没有至少保证验证集占20%且类别分布和整体接近。下面这个分层抽样脚本可以抄import random from collections import defaultdict def split_by_class(xml_dir, val_ratio0.2, seed42): random.seed(seed) # 每张图的主类别 框最多的类别 img_main_cls {} for xf in os.listdir(xml_dir): if not xf.endswith(.xml): continue tree ET.parse(os.path.join(xml_dir, xf)) cnt defaultdict(int) for obj in tree.findall(object): cnt[obj.find(name).text] 1 if cnt: img_main_cls[xf] max(cnt, keycnt.get) # 按主类别分组 groups defaultdict(list) for xf, c in img_main_cls.items(): groups[c].append(xf) train, val [], [] for c, files in groups.items(): random.shuffle(files) n_val max(1, int(len(files) * val_ratio)) val.extend(files[:n_val]) train.extend(files[n_val:]) return train, val逻辑说明max(cnt, keycnt.get)取框最多的类别作为图片主类别这样分层后每个类别在验证集里都有代表。max(1, ...)保证长尾类至少有一张进验证集否则那一类的mAP无法计算。参数上val_ratio一般0.2数据量小于500张时用0.3seed固定住方便复现。3.3 生成YOLO训练用的data.yaml转换完最后一步是写data.yaml这是YOLOv5/v8训练的入口文件。格式如下path: /home/user/leaf_dataset train: images/train val: images/val nc: 29 names: 0: leaf_spot 1: rust 2: powdery_mildew # ... 补齐29类path是数据集根目录train和val是相对路径。nc必须等于names长度。常见翻车是names写成一行列表但缩进错了YAML对缩进敏感。另一个坑是path用了相对路径但训练时工作目录变了建议写绝对路径。改完用python -c import yaml; print(yaml.safe_load(open(data.yaml)))验证一下能否解析。4. 用YOLOv8跑通第一条baseline命令、参数和指标解读4.1 环境准备和最小训练命令假设你已经装好ultralytics一条命令就能起训yolo detect train \ data/home/user/leaf_dataset/data.yaml \ modelyolov8n.pt \ epochs100 \ imgsz640 \ batch16 \ workers4 \ projectleaf_runs \ namebaseline逻辑说明modelyolov8n.pt用nano版先跑通别一上来上x版显存和时间都吃不消。imgsz640是默认值叶片病害目标通常不大如果标注框普遍小于32像素考虑提到imgsz1024但batch要相应降到8或4。workers4在Linux上够用Windows上设0避免多进程报错。project和name决定输出目录跑完在leaf_runs/baseline/weights/best.pt拿最优权重。4.2 三个必调参数imgsz、batch、学习率imgsz直接决定小目标能否被检测到。叶片病斑在整图里可能只占几十像素640下经过下采样后特征几乎消失。我的经验是统计所有标注框的宽高分布如果中位数小于50像素imgsz至少1024。代价是显存翻倍batch要减半。batch不是越大越好。小数据集上大batch容易过拟合且BN层统计不稳定。29类、几千张图的规模batch16或8比较稳。如果显存不够用batch8配合accumulate2模拟16。学习率默认lr00.01对YOLOv8的SGD优化器偏高小数据集上常见loss震荡。改成lr00.001配合cos_lrTrue余弦退火收敛曲线会平滑很多。如果10个epoch后mAP还不涨先查学习率再查数据。4.3 看指标时别只看mAP50训练日志里重点看四个box_loss、cls_loss、mAP50、mAP50-95。box_loss降不下去说明框回归有问题多半是标注框质量差或imgsz太小。cls_loss高但box_loss低说明框对了但类别分不清29类里可能有视觉相似的类比如不同真菌引起的斑点这时候要么合并类要么加数据。mAP50高但mAP50-95低说明框的位置不够准IoU阈值一提高就掉。这在叶片病害里很常见因为病斑边界本来就模糊不同标注者对边界理解不一致。解决办法不是调模型而是统一标注规范病斑框到底包不包含边缘黄晕这个必须在标注阶段定死。验证集指标异常高比如mAP500.95时先别高兴检查验证集是否和训练集有重复图。用图片哈希去重import hashlib def file_hash(path): with open(path, rb) as f: return hashlib.md5(f.read()).hexdigest() train_hashes {file_hash(os.path.join(images/train, f)) for f in os.listdir(images/train)} val_hashes {file_hash(os.path.join(images/val, f)) for f in os.listdir(images/val)} print(重复图数量:, len(train_hashes val_hashes))逻辑说明MD5对图片内容做哈希完全相同的图会得到相同值。如果重复数大于0说明划分有问题必须重新分。参数上如果图片经过不同压缩MD5不同但视觉相同这种情况要用感知哈希但VOC数据集一般不会。5. 避坑与排查29类叶片病害数据集上最容易翻车的5件事5.1 现象训练loss正常但mAP一直是0原因类别json的索引和data.yaml的names顺序不一致模型学的是错位标签。或者XML里类别名有空格、大小写差异比如Leaf_Spot和leaf_spot被当成两类。解决跑一遍2.2节的比对脚本确保XML类别集合和json完全相等。再用print(names)确认data.yaml里的顺序和json一致。大小写问题统一用.strip().lower()清洗。5.2 现象验证集mAP远高于训练集原因验证集里混入了训练集的近重复图或者验证集太小且类别分布偏斜。植物叶片同一株拍多张的情况极常见。解决用4.3节的哈希去重再检查划分是否按株分组。如果数据集自带的ImageSets/Main/val.txt有问题自己按3.2节重新分层抽样。5.3 现象小病斑全部漏检原因imgsz太小病斑经过骨干网络下采样后特征消失。或者标注框本身太小YOLO的anchor匹配不上。解决先统计框尺寸分布中位数小于50像素就把imgsz提到1024。如果显存不够改用YOLOv8的rectTrue矩形训练减少padding或者换用带P2小目标检测层的模型配置。标注框小于8像素的建议直接删掉这种框连人都标不准。5.4 现象某些类别AP为0但该类明明有样本原因该类在验证集里没有实例或者实例数太少1到2个AP计算不稳定。也可能是该类在训练集里被过采样后模型过拟合验证集上反而崩。解决检查3.2节分层抽样是否保证每类至少一张进验证集。如果某类总样本少于30考虑合并到语义相近的类或者用重复采样把训练集补到50以上。验证集里该类至少要有5个实例AP才有参考意义。5.5 现象训练到一半loss突然变NaN原因学习率太高导致梯度爆炸或者某张图的标注框归一化后值异常比如w1.5。VOC转YOLO时如果没做边界裁剪就会出现这种情况。解决先把lr0降到0.0005加grad_clip10.0。然后跑一遍转换后的labels检查用下面脚本找出非法值import os for lf in os.listdir(labels/train): with open(os.path.join(labels/train, lf)) as f: for line in f: parts line.strip().split() if len(parts) ! 5: print(格式错误:, lf, line) continue vals [float(x) for x in parts[1:]] if any(v 0 or v 1 for v in vals): print(越界:, lf, line)逻辑说明YOLO格式要求所有坐标在0到1之间越界值会让损失函数计算出NaN。参数上len(parts) ! 5还能抓出行数不对的脏标注。跑完把有问题的图从训练集剔除或重新标注。6. 进阶技巧用可视化脚本反查标注质量把mAP再提5个点数据集自带的可视化脚本大多数人只用来「看一眼」其实它可以变成标注质量审计工具。我的习惯是训练前把训练集全部可视化一遍用脚本自动标记出三类可疑框——面积占比小于0.1%的、宽高比大于5的、以及和其他框IoU大于0.7的。这三类分别对应「太小无意义」「细长误标」「重复标注」。下面这个审计脚本可以直接跑import os import xml.etree.ElementTree as ET def audit_xml(xml_path, img_w, img_h): tree ET.parse(xml_path) boxes [] issues [] for obj in tree.findall(object): name obj.find(name).text b obj.find(bndbox) x1 float(b.find(xmin).text) y1 float(b.find(ymin).text) x2 float(b.find(xmax).text) y2 float(b.find(ymax).text) w x2 - x1 h y2 - y1 area_ratio (w * h) / (img_w * img_h) if area_ratio 0.001: issues.append(f过小框: {name} area{area_ratio:.4f}) if max(w / h, h / w) 5: issues.append(f细长框: {name} w{w:.0f} h{h:.0f}) boxes.append((x1, y1, x2, y2, name)) # 检查重复框 for i in range(len(boxes)): for j in range(i 1, len(boxes)): ax1, ay1, ax2, ay2, an boxes[i] bx1, by1, bx2, by2, bn boxes[j] ix1, iy1 max(ax1, bx1), max(ay1, by1) ix2, iy2 min(ax2, bx2), min(ay2, by2) if ix2 ix1 and iy2 iy1: inter (ix2 - ix1) * (iy2 - iy1) union (ax2 - ax1) * (ay2 - ay1) (bx2 - bx1) * (by2 - by1) - inter if inter / union 0.7: issues.append(f重复框: {an} 与 {bn} IoU{inter/union:.2f}) return issues # 批量审计 from PIL import Image for xf in os.listdir(Annotations): if not xf.endswith(.xml): continue stem os.path.splitext(xf)[0] for ext in [.jpg, .png, .jpeg]: ip os.path.join(JPEGImages, stem ext) if os.path.exists(ip): with Image.open(ip) as im: w, h im.size iss audit_xml(os.path.join(Annotations, xf), w, h) if iss: print(stem, iss) break逻辑说明area_ratio 0.001对应640图中约20x20像素以下的框这种框在训练中贡献极小但会拉低精度。max(w/h, h/w) 5抓细长误标叶片病斑一般是团状细长框多半是把叶脉或边缘当成了病斑。IoU大于0.7的重复框直接合并或删一个。参数上0.001和5这两个阈值可以根据你的数据调整但建议先跑一遍看数量如果过小框占比超过10%说明标注规范有问题不是模型能救的。审计完把问题图挑出来重新标再训练一轮mAP50通常能涨3到5个点。这个提升不是模型带来的是数据质量带来的。我自己的习惯是任何新数据集到手先跑可视化审计再跑baseline最后才调参。顺序反了就是浪费时间。另外29类里如果有个别类始终学不好别急着加数据先看那类的框是不是普遍偏小或边界模糊有时候合并两个视觉相近的类比硬分29类更划算。希望帮到你。本文还有配套的精品资源点击获取

相关新闻

OpenCV六步图像处理:平滑、增强、边缘检测、阈值化、细化与面积测量

OpenCV六步图像处理:平滑、增强、边缘检测、阈值化、细化与面积测量

简介:面向图像处理初学者与C开发者的实验资源包,内容源自中国科技大学图像测量课程,完整覆盖五个经典实验:图像平滑与增强、边缘检测、阈值化与细化、面积测量,以及区域边界提取与周长计算。压缩包共46个文件&#xff…

2026/10/11 22:31:21 阅读更多 →
等保测评数据库安全核查:覆盖五大主流数据库的实操指南

等保测评数据库安全核查:覆盖五大主流数据库的实操指南

简介:面向等保测评工程师、数据库管理员及安全运维人员,一套覆盖MYSQL、ORACLE、SQLSERVER、Postgres、Redis五类主流数据库的等保测评作业指导书,系统梳理每种数据库的连接登录方式、测评基本查询语句及相关安全配置核查项,可直接…

2026/10/11 22:31:21 阅读更多 →
SEO写作不过时!16个实战秘诀:同时讨好算法、AI和用户

SEO写作不过时!16个实战秘诀:同时讨好算法、AI和用户

还在纠结“SEO写作是不是过时了”?我这两年带内容团队做了十几个SEO项目,最深的体会是:SEO写作不但没过时,它依然是性价比极高的流量获取方式。区别只在于,以前你只需要写给爬虫看,现在你得同时写给“算法A…

2026/10/11 22:30:21 阅读更多 →

最新新闻

Vibe Coding 的边界:从“70% 问题“到“80% 墙“,AI 编程五大局限性与人机分工深度解析

Vibe Coding 的边界:从“70% 问题“到“80% 墙“,AI 编程五大局限性与人机分工深度解析

文档教程Vibe Coding示例工程 【免费下载链接】vibe-vibe The First Systematic Vibe Coding Open-Source Tutorial | From Zero to Full-Stack, Empowering Everyone to Build Products with AI | Live at: www.vibevibe.cn ;首个系统化 Vibe Coding 开源教程 | 零…

2026/10/12 0:53:26 阅读更多 →
不用模拟器也能玩PS5游戏?拆解AnyPS5的“非模拟器魔法“:relinker重链接+PRX库+RDNA到SPIR-V

不用模拟器也能玩PS5游戏?拆解AnyPS5的“非模拟器魔法“:relinker重链接+PRX库+RDNA到SPIR-V

不用模拟器也能玩PS5游戏?拆解AnyPS5的"非模拟器魔法":relinker重链接PRX库RDNA到SPIR-V 【免费下载链接】AnyPS5 Tool for automatic PS5 executables porting to Linux and Windows 项目地址: https://gitcode.com/GitHub_Trending/an/Any…

2026/10/12 0:53:26 阅读更多 →
基于A星算法的无人机三维路径规划Matlab实现与优化

基于A星算法的无人机三维路径规划Matlab实现与优化

做无人机的人基本都绕不开路径规划这道坎。“基于A星算法的无人机三维路径规划算法研究(Matlab代码实现)” 这个题目看着规整,但真正落地的时候,坑比想象的多:地图怎么建、邻居节点怎么扩展、启发函数怎么写才能既快又…

2026/10/12 0:51:25 阅读更多 →
VS Code 中直接使用 Codex 教程及连接失败解决方案:TaoToken 统一 Key 接入与排错实录

VS Code 中直接使用 Codex 教程及连接失败解决方案: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/12 0:50:24 阅读更多 →
企业 Agent 提示词注入防御实战:双重护栏与对抗语义检测

企业 Agent 提示词注入防御实战:双重护栏与对抗语义检测

在企业将多智能体(Multi-Agent)系统接入客服咨询、内部知识检索或自动化办公流后,安全攻防的对抗维度发生了一场根本性范式转移:传统的 SQL 注入或跨站脚本攻击(XSS)正在退居二线,而以自然语言为…

2026/10/12 0:47:23 阅读更多 →
Cursor怎么使用:3分钟上手Cursor键盘快捷键速查,用TaoToken统一Key接入GPT4与Claude 3.5辅助编程

Cursor怎么使用:3分钟上手Cursor键盘快捷键速查,用TaoToken统一Key接入GPT4与Claude 3.5辅助编程

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

2026/10/12 0:46:23 阅读更多 →

日新闻

复古胶片颗粒感噪点合成器:Canvas ImageData 像素高斯杂色注入算法

复古胶片颗粒感噪点合成器:Canvas ImageData 像素高斯杂色注入算法

在数码相机、高清显示屏与现代矢量图形技术高度发达的今天,画面可以做到绝对的锐利、平滑与无瑕。然而,当一张秋日手账插画或拍立得照片过于“平整无瑕”时,往往会散发出一种冰冷生硬的“数码塑料感(Digital Plasticity&#xff0…

2026/10/12 0:00:59 阅读更多 →
活字印刷古籍线装排版:Canvas 竖排文字与栏线自适应算法

活字印刷古籍线装排版:Canvas 竖排文字与栏线自适应算法

在现代网页与移动端设计中,横排(Horizontal Layout)早已经成为了绝对的主流。然而,当我们翻开泛黄的线装古籍、宋版木刻诗集,或是欣赏一张茶道雅集的手写便签时,那种**自上而下纵向书写、自右向左逐列铺展&…

2026/10/12 0:00:59 阅读更多 →
周日晚间的“精神松绑减震器”:无压力情绪倾倒箱与温和轻声陪伴

周日晚间的“精神松绑减震器”:无压力情绪倾倒箱与温和轻声陪伴

每到周日的晚上八点到十点,很多人心里都会悄悄亮起一盏警示灯。 在心理学上,这种现象有一个专门的称谓——“周日夜晚焦虑症(Sunday Scaries)”。明天又是周一,闹钟又要重新在七点响彻卧房;脑海里仿佛有一个…

2026/10/12 0:00:59 阅读更多 →

周新闻

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

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

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

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

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

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

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

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

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

2026/10/12 0:16:43 阅读更多 →

月新闻

我发现了一个新思路:用 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/11 10:45:37 阅读更多 →
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/11 14:36:53 阅读更多 →
黑夜航拍船只数据集训练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/11 14:36:54 阅读更多 →