OpenCV图像矫正实战:透视变换与文档扫描全流程
简介本资源面向图像处理初学者与OpenCV开发者聚焦“全能扫描王”式文档矫正功能的实现帮助解决拍摄文档倾斜、扭曲与透视失真问题。包内共13个文件以9个png与1个jpg测试图片、1个cpp核心源码为主另含gitattributes、gitignore等工程配置文件压缩包约2.23MB便于直接编译调试。源码围绕旋转矫正与透视变换两条主线展开通过getRotationMatrix2D与warpAffine处理整体倾斜借助getPerspectiveTransform与warpPerspective还原矩形文档并串联高斯模糊、Canny边缘检测、轮廓与直线检测、透视矩阵计算及后处理裁剪等完整流程。已有3025人学习下载读者可据此掌握从图像预处理到矫正输出的工程化思路理解各函数参数含义与调参技巧并迁移到桌面端或服务端扫描类应用开发中。1. 从一张拍歪的发票说起OpenCV 图像矫正到底在做什么拍过发票、合同、白板笔记的人都有体会手机举得再正出来的图总是梯形——上边窄下边宽或者左边高右边低。人眼能自动脑补“这其实是个矩形”但 OCR 引擎不行它只认像素坐标。OpenCV 图像矫正要干的事就是把这种透视畸变拉回正视图让后续的文字识别、存档、打印都能对上号。这套流程在“全能扫描王”这类应用里是核心链路边缘检测找纸张轮廓四点定位算角点透视变换做映射最后裁切输出。适合谁做文档扫描、票据识别、白板存档的移动端或服务端开发者以及想用 Python 快速搭一套图像矫正原型的图像处理入门者。它不依赖深度学习模型纯几何滤波就能跑CPU 上单张图几十毫秒这是它至今没被替代的原因。2. 透视变换的数学底子为什么四个点就能把梯形拉成矩形2.1 从仿射到透视多出来的那一个自由度仿射变换能处理平移、旋转、缩放、错切但它有个硬约束——平行线变换后仍然平行。拍文档时纸张远端和近端的平行边在成像后不再平行仿射就无能为力了。透视变换也叫投影变换引入了一个 3×3 的矩阵把二维点写成齐次坐标 (x, y, 1)变换后再除以第三维分量还原[x] [h11 h12 h13] [x] [y] [h21 h22 h23] [y] [w ] [h31 h32 h33] [1] 最终坐标 (x/w, y/w)这个 h31、h32 就是“透视因子”它们让远处的边收缩得更快。八个自由度h33 通常归一化为 1正好对应四对点——源图的四个角点映射到目标矩形的四个角点八个方程解八个未知数唯一解。这就是为什么透视变换必须给四个点少一个都不行。2.2 getPerspectiveTransform 与 warpPerspective 的分工OpenCV 把这件事拆成两步。getPerspectiveTransform(src, dst)负责解方程输入是两个 4×2 的浮点数组输出 3×3 的变换矩阵。warpPerspective(src, M, dsize, ...)负责逐像素重采样把源图按矩阵映射到目标画布。常见做法是先用getPerspectiveTransform算矩阵再调warpPerspective出图。参数上dsize是输出图像的宽高通常设成你想要的矩形尺寸比如 A4 纸按 300 DPI 就是 2480×3508。插值方式默认INTER_LINEAR文档矫正够用如果追求边缘锐利可以换INTER_CUBIC但速度会慢一截。边界模式默认BORDER_CONSTANT超出源图范围的像素填 0黑色这也是为什么矫正后四角偶尔出现黑边——源图里没有对应像素。2.3 角点顺序一个让无数人翻车的细节getPerspectiveTransform不关心你给的四个点是什么顺序它只按数组下标一一对应。但warpPerspective出来的图是否正立完全取决于你 src 点的顺序和 dst 点的顺序是否语义一致。常见做法是统一约定src 按“左上、右上、右下、左下”排列dst 也按同样顺序给目标矩形的四个角。如果 src 顺序乱了出来的图会旋转 90 度甚至镜像。我一般会在代码里写一个order_points函数用坐标和与坐标差来排序xy 最小的是左上最大的是右下x-y 最小的是右上最大的是左下。这个函数几乎是所有文档矫正项目的标配后面章节会给出实现。3. 从拍照到矫正一条可复现的 OpenCV 流水线3.1 预处理灰度、高斯模糊、Canny 边缘直接对彩色图做边缘检测噪声多、阈值难调。标准做法是先转灰度再高斯模糊压噪最后 Canny 提边缘。高斯核大小一般取 5×5太大糊掉纸张边缘太小压不住噪点。Canny 的双阈值我习惯设 75 和 200这是 OpenCV 官方示例里的经验值对白底黑字的文档场景命中率不错。如果背景杂乱比如木桌上拍纸可以先把图像缩到宽 500 左右再做边缘检测小图对噪声不敏感找到轮廓后再按比例放大回原图坐标这样速度和稳定性都更好。import cv2 import numpy as np def preprocess(image_path): # 读取图像保留彩色通道备用 img cv2.imread(image_path) # 缩放宽固定 500保持长宽比降低噪声干扰 ratio img.shape[1] / 500.0 orig img.copy() img cv2.resize(img, (500, int(img.shape[0] / ratio))) # 转灰度 gray cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 高斯模糊5x5 核sigma 自动 blurred cv2.GaussianBlur(gray, (5, 5), 0) # Canny 边缘检测双阈值 75/200 edged cv2.Canny(blurred, 75, 200) return orig, img, edged, ratio逻辑说明ratio记录缩放比例后续找到的轮廓坐标要乘回去才能对应原图。orig保留原图用于最终裁剪。edged是二值边缘图白色是边缘黑色是背景。参数上如果你处理的文档对比度高Canny 阈值可以提到 100/250如果纸张发黄、光照不均降到 50/150 更稳。3.2 轮廓筛选怎么从一堆边缘里挑出纸张Canny 出来的边缘图里纸张轮廓只是其中一条闭合曲线还有文字边缘、桌面纹理、阴影边界。findContours会返回所有轮廓按面积降序排纸张通常是最大的那个。但光看面积不够——如果桌面本身有个大轮廓或者背景有更亮的区域就会误选。我一般加两个约束轮廓近似后的顶点数接近 4且面积占全图比例超过 10%。approxPolyDP用 Douglas-Peucker 算法把轮廓折线化epsilon取轮廓周长的 2%这个比例能把纸张的四个角保留下来同时滤掉文字那种碎边。def find_document_contour(edged): # 只取外轮廓压缩水平/垂直/对角方向的多余点 contours, _ cv2.findContours(edged, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) # 按面积降序 contours sorted(contours, keycv2.contourArea, reverseTrue)[:5] for c in contours: # 计算轮廓周长 peri cv2.arcLength(c, True) # 折线化epsilon 为周长的 2% approx cv2.approxPolyDP(c, 0.02 * peri, True) # 四个顶点且面积足够大认为是纸张 if len(approx) 4 and cv2.contourArea(c) 0.1 * edged.shape[0] * edged.shape[1]: return approx return None逻辑说明RETR_EXTERNAL只取最外层轮廓避免纸张内部文字干扰。[:5]只检查面积最大的五个减少计算量。approxPolyDP的True表示轮廓闭合。面积阈值 10% 是经验值如果拍的是小票可以降到 5%如果拍的是整页书可以提到 20%。返回的approx是 4×1×2 的数组需要 reshape 成 4×2 才能给透视变换用。3.3 四点排序与透视变换把梯形拉正拿到四个角点后先排序再算矩阵。排序逻辑前面提过用 xy 和 x-y 的组合定位四个角。目标矩形的宽高由源四边形的边长推算——上边和下边长度的最大值作为输出宽度左边和右边长度的最大值作为输出高度。这样能保证矫正后的图不拉伸变形。warpPerspective的dsize就填这个宽高。def order_points(pts): # pts 是 4x2 数组 rect np.zeros((4, 2), dtypefloat32) s pts.sum(axis1) rect[0] pts[np.argmin(s)] # 左上xy 最小 rect[2] pts[np.argmax(s)] # 右下xy 最大 diff np.diff(pts, axis1) rect[1] pts[np.argmin(diff)] # 右上x-y 最小 rect[3] pts[np.argmax(diff)] # 左下x-y 最大 return rect def four_point_transform(orig, pts, ratio): # 把缩放图的坐标还原到原图 pts pts.reshape(4, 2) * ratio rect order_points(pts) (tl, tr, br, bl) rect # 计算输出宽度上下边取最大 widthA np.linalg.norm(br - bl) widthB np.linalg.norm(tr - tl) maxWidth max(int(widthA), int(widthB)) # 计算输出高度左右边取最大 heightA np.linalg.norm(tr - br) heightB np.linalg.norm(tl - bl) maxHeight max(int(heightA), int(heightB)) # 目标矩形四点顺序与 rect 一致 dst np.array([ [0, 0], [maxWidth - 1, 0], [maxWidth - 1, maxHeight - 1], [0, maxHeight - 1] ], dtypefloat32) # 算透视矩阵并应用 M cv2.getPerspectiveTransform(rect, dst) warped cv2.warpPerspective(orig, M, (maxWidth, maxHeight)) return warped逻辑说明pts * ratio把缩放图坐标还原到原图保证裁剪的是原图分辨率。order_points返回的顺序固定为左上、右上、右下、左下dst也按这个顺序给两者语义对齐。maxWidth和maxHeight取对边最大值避免输出图被压缩。warpPerspective的第三个参数是输出尺寸这里用算出来的宽高不额外加边距。如果希望输出图四周留白可以在dst里加偏移量比如左上角从 (10, 10) 开始。3.4 二值化与去阴影让 OCR 更友好矫正完的图如果直接送 OCR光照不均和阴影还会干扰。常见做法是加一步自适应阈值或者形态学闭运算。自适应阈值对光照变化鲁棒但会产生椒盐噪声形态学闭运算能填掉文字笔画里的空洞。我一般用cv2.adaptiveThreshold块大小取 11常数 C 取 2然后做一次中值滤波去噪。如果纸张本身有折痕可以先用cv2.morphologyEx做开运算去掉细小黑点再做闭运算连接断裂笔画。def enhance_for_ocr(warped): # 转灰度 gray cv2.cvtColor(warped, cv2.COLOR_BGR2GRAY) # 自适应阈值11x11 邻域C2 thresh cv2.adaptiveThreshold(gray, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 11, 2) # 中值滤波去椒盐噪声 denoised cv2.medianBlur(thresh, 3) return denoised逻辑说明ADAPTIVE_THRESH_GAUSSIAN_C用高斯加权算局部阈值比均值法更平滑。块大小 11 是奇数必须大于 1。C 值越大阈值越低保留的暗部细节越多文档场景一般 2 到 5 之间。中值滤波核 3 足够去掉单像素噪声再大就会糊掉小字。4. 避坑与排查那些让矫正结果“玄学”的瞬间4.1 现象矫正后图像旋转了 90 度或镜像原因order_points的排序逻辑在特定角度下会错位。比如纸张旋转超过 45 度时xy 最小的点可能不是左上角而是右上角。另外如果findContours返回的轮廓点顺序本身是逆时针approxPolyDP出来的四点顺序也会跟着乱。解决在order_points之后加一个校验——计算 rect 的宽高比如果宽小于高说明可能竖过来了但这不是根本办法。更稳的做法是用cv2.minAreaRect先拿到最小外接矩形再取其四个顶点这样顺序天然是顺时针或逆时针配合boxPoints可以固定顺序。我一般会在排序后打印四个点的坐标肉眼确认一下左上角的 x 和 y 都是最小的。4.2 现象边缘检测找不到纸张返回 None原因背景和纸张颜色接近Canny 阈值太高或太低或者纸张只占了画面一小部分面积阈值把它滤掉了再或者光照太暗高斯模糊后边缘被抹平。解决先把图缩到宽 500 再检测小图对阈值不敏感。如果还不行换cv2.Canny的阈值从 50/150 试到 100/250。面积阈值从 10% 降到 5%。实在找不到可以退而求其次用cv2.threshold做全局二值化再找轮廓适合白纸黑字的极端场景。我遇到过一次拍的是深色封面书Canny 完全失效最后用 HSV 空间的 V 通道做阈值才搞定。4.3 现象矫正后四角有黑边或拉伸变形原因黑边是因为warpPerspective的目标画布比源图实际覆盖的区域大超出部分填了黑色。拉伸变形是因为maxWidth和maxHeight算错了——比如把对边长度取成了最小值或者order_points顺序错导致宽高互换。解决黑边可以在warpPerspective之后做一次裁剪用cv2.findContours找最大轮廓再裁一次或者在dst里把目标矩形缩小几个像素。拉伸变形要检查order_points返回的四个点是否真的对应左上、右上、右下、左下打印出来核对。另外np.linalg.norm算边长时用的是浮点坐标没问题但如果 pts 是整数数组减法可能溢出记得转 float32。4.4 现象处理速度慢单张图超过 1 秒原因原图分辨率太高比如 4000×3000直接做 Canny 和warpPerspective很吃 CPU。或者warpPerspective用了INTER_CUBIC插值计算量比INTER_LINEAR大几倍。解决预处理阶段先缩到宽 500找到轮廓后只对原图做一次warpPerspective这样大部分计算都在小图上。插值方式改回INTER_LINEAR文档矫正对插值精度要求不高。如果还慢可以把warpPerspective的输出尺寸限制在 2000 像素宽以内OCR 前再缩放。我实测过4000×3000 的图缩到 500 宽做边缘检测整条流水线从 1.2 秒降到 80 毫秒左右。4.5 现象文字区域出现摩尔纹或锯齿原因warpPerspective重采样时如果源图有高频纹理比如屏幕拍屏会产生摩尔纹。锯齿则是插值方式太粗糙或者输出尺寸和源图比例不匹配。解决在warpPerspective之前对源图做一次轻微高斯模糊核大小 3×3能压掉高频噪声。插值方式换成INTER_CUBIC或INTER_LANCZOS4后者质量更好但更慢。输出尺寸尽量接近源图的实际物理尺寸不要放大太多。如果摩尔纹严重可以在频域做一次低通滤波但那就杀鸡用牛刀了一般文档场景用高斯模糊就够。5. 进阶技巧用形态学与自适应阈值把矫正推到生产级前面四章把主链路跑通了但生产环境里还有两个硬骨头光照不均和纸张折痕。这一章给两个具体技巧都是我在实际项目里反复调参后留下来的。第一个技巧是用形态学闭运算估计背景光照。思路很简单对灰度图做一次大核闭运算核大小取图像宽度的 1/30 左右得到一张“背景光照图”然后用原图减去这张背景图再做归一化。这样阴影和渐变光照就被拉平了。代码不长但效果比单纯自适应阈值稳得多。def remove_illumination(gray): # 大核闭运算估计背景核大小随图像宽度自适应 kernel cv2.getStructuringElement(cv2.MORPH_RECT, (max(1, gray.shape[1] // 30), max(1, gray.shape[1] // 30))) background cv2.morphologyEx(gray, cv2.MORPH_CLOSE, kernel) # 原图减背景再加 255 偏移防止负数 diff cv2.subtract(background, gray) # 归一化到 0-255 normalized cv2.normalize(diff, None, 0, 255, cv2.NORM_MINMAX) return normalized逻辑说明MORPH_CLOSE先膨胀后腐蚀能把暗色文字填掉留下亮色背景。核大小取宽度的 1/30 是个经验值——太小背景估计不准太大计算慢且会抹掉大块阴影。cv2.subtract(background, gray)得到的是“背景比原图亮多少”也就是光照不均的程度。归一化后文字变暗、背景变亮对比度拉大。这个函数对手机拍的文档特别有效尤其是灯光从一侧打过来的场景。第二个技巧是折痕处理。纸张折痕在矫正后表现为一条暗线OCR 会把它当成字符。常见做法是用cv2.morphologyEx做一次开运算核取 3×3 或 5×5把细暗线去掉再做闭运算连接断裂笔画。但开运算也会削弱细笔画所以核不能大。我一般先做一次 3×3 开运算如果折痕还在再补一次中值滤波。如果折痕特别粗那就得用频域滤波或者手动 mask 了但那种情况很少见。验证方法上我习惯用两张图对比一张是原始矫正图一张是增强后的二值图。把两张图并排显示看文字区域是否干净、背景是否均匀。如果二值图里文字断断续续说明阈值太高或开运算太狠如果背景还有大片灰色说明光照没拉平。参数调完后拿一张之前 OCR 识别率低的图跑一遍看识别结果是否改善。我一般会准备 10 张不同光照、不同角度的测试图每次改参数都跑一遍记录识别率变化。从那以后我每次调阈值或形态学核大小都强制走一遍这 10 张图的回归测试不然很容易在某个场景上翻车。希望帮到你。本文还有配套的精品资源点击获取

相关新闻

Java Files.lines()从文本行创建Stream的实战指南与避坑详解

Java Files.lines()从文本行创建Stream的实战指南与避坑详解

做 Java 开发这些年,读取文本文件这事几乎天天都在干。早年间我是标准的 BufferedReader 加 while ((line reader.readLine()) ! null) 循环,一行一行处理,写多了确实觉得啰嗦。后来 Java 8 引入 Stream API,我第一次用 Fil…

2026/10/13 11:21:39 阅读更多 →
论文查重免费平台实测:每天200篇额度如何让降重成本归零

论文查重免费平台实测:每天200篇额度如何让降重成本归零

又是一年毕业季,朋友圈里满是“查重又要花钱”“学校只给一次免费查重机会”的哀嚎。我自己去年帮课题组改论文,前前后后用第三方付费查重花了小几百,后来偶然发现一个每天能免费用 200 篇的查重平台,一开始以为是噱头&#xff0c…

2026/10/13 11:20:38 阅读更多 →
基于边缘形状匹配的拼图求解器:OpenCV轮廓提取与全局优化实战

基于边缘形状匹配的拼图求解器:OpenCV轮廓提取与全局优化实战

简介:这是一份面向计算机视觉与算法实践者的C拼图求解项目源码,核心思路是通过提取拼图碎片的边缘形状特征完成自动拼接,适合具备一定OpenCV基础、希望研究图像分割与轮廓匹配的开发者参考。资源包共53个文件,约239.07MB&#xff…

2026/10/13 11:20:38 阅读更多 →

最新新闻

SonarQube 7.9 部署与实战避坑指南:兼容JDK8/PostgreSQL11的稳定方案

SonarQube 7.9 部署与实战避坑指南:兼容JDK8/PostgreSQL11的稳定方案

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

2026/10/13 12:01:50 阅读更多 →
jQuery 实现商品管理增删改查与数据统计实战

jQuery 实现商品管理增删改查与数据统计实战

最近整理旧项目时,翻出一个用 jQuery 写过的商品列表管理页面,功能很朴素:基于 jQuery 做商品数据的增删改查,再配上几组统计数字。但就是这样一个经典场景,十几年了还在各种后台系统里反复出现,也几乎每天…

2026/10/13 12:01:50 阅读更多 →
CWRU轴承故障信号STFT与CWT时频分析实战指南

CWRU轴承故障信号STFT与CWT时频分析实战指南

简介:本资源是一份面向机械故障诊断、信号处理与智能运维方向研究者及研究生的凯斯西储大学轴承故障数据集时频分析实践指南,聚焦振动信号的深度特征提取与故障辨识方法。文档系统讲解短时傅里叶变换(STFT)与连续小波变换&#xf…

2026/10/13 12:01:50 阅读更多 →
Gin框架认证与授权实战:从JWT到RBAC权限模型

Gin框架认证与授权实战:从JWT到RBAC权限模型

前阵子一位从PHP转Go的同事问我:他在Gin框架里写了一个查询订单的接口,只要前端把user_id传进来,就能看到别人的订单,他想加个认证。我反问他,你知道认证和授权不是一回事吗?他愣了一下。这正是很多人在Gin…

2026/10/13 12:01:50 阅读更多 →
基于SpringBoot+Vue的考编论坛系统设计与实现

基于SpringBoot+Vue的考编论坛系统设计与实现

1. 项目定位与整体设计思路1.1 考编需求拆解:这个论坛到底要做什么说起考编,这几年真的是一个绕不开的话题。不管是应届生还是已经工作的年轻人,越来越多的人把公务员、事业单位、教师编当成一个重要的职业选择。但考编这件事,信息…

2026/10/13 12:01:50 阅读更多 →
MARS多专家接力:提升大模型算法竞赛正确率的实践

MARS多专家接力:提升大模型算法竞赛正确率的实践

大模型在算法竞赛里“会做但做不对”是很多人都遇到过的情况:单模型输出不稳定、推理步骤一长就崩、改一版 Prompt 正确率又掉回去。如果把多个模型的结果做一个简单投票,效果往往也一般。最近我在尝试“MARS 多专家接力”框架时发现,这种方案…

2026/10/13 12:00:48 阅读更多 →

日新闻

物联网系统集成避坑指南:从选型到验收的关键要点

物联网系统集成避坑指南:从选型到验收的关键要点

做了这么多年物联网系统集成的项目,我最大的感受是,大部分坑不是出在技术前沿,而是出在一些看起来很平常的地方。设备选了便宜的、协议没问清楚、现场没摸透、验收标准写得含糊——这些细枝末节,最后都会变成延期、超支和扯皮的大…

2026/10/13 0:00:57 阅读更多 →
ESP32舵机控制全攻略:从PWM原理到高级玩法与常见故障排查

ESP32舵机控制全攻略:从PWM原理到高级玩法与常见故障排查

如果你玩ESP32有一阵子了,很难不碰到舵机控制这道坎。做智能小车要转方向,做机械臂要抬关节,做云台要偏航俯仰,背后都是同一个东西在干活:舵机。而我见过太多人卡在“代码能编译、舵机就是不听话”这个阶段&#xff0c…

2026/10/13 0:00:57 阅读更多 →
CAN总线原理与STM32实战:抗干扰、仲裁、错误处理全解析

CAN总线原理与STM32实战:抗干扰、仲裁、错误处理全解析

1. 为什么CAN总线至今仍是工业现场的“硬通货”?——从汽车底盘到智能温室的真实需求你有没有拆过一辆老款燃油车的中控台?或者调试过某高校实验室里那台跑着Modbus协议却频频丢帧的PLC控制柜?又或者,在某个农业物联网项目里&…

2026/10/13 0:00:57 阅读更多 →

周新闻

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

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

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

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

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

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

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

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

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

2026/10/13 1:58:08 阅读更多 →

月新闻

我发现了一个新思路:用 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/12 21:05:09 阅读更多 →
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/12 14:48:49 阅读更多 →
黑夜航拍船只数据集训练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/12 18:11:17 阅读更多 →