OpenCV人脸识别实战:从环境配置到LBPH阈值调优

简介:这份资源面向具备Python基础、希望入门机器视觉与人脸识别的开发者与学习者,以OpenCV为核心工具,围绕明星人脸检测与识别这一具体场景展开实战。压缩包共120个文件,以110张jpg与5张jpeg人脸样本图片为主体,另含2个Haar级联分类器xml模型文件、1个Python源码脚本、1个说明txt和1张png,整体约51.99MB,图片用于训练与测试,xml提供预训练检测模型,py脚本串联完整流程。内容覆盖Haar特征与级联分类器原理、灰度化与直方图均衡化等预处理、detectMultiScale人脸定位,以及EigenFace、FisherFace、LBPH等特征提取与匹配方法,并涉及用cv2.ml或sklearn训练自定义识别模型。已有459人学习下载,适合作为理解人脸检测识别流程、动手调参与排错的实践素材。

1. 从一堆散装脚本到能跑的人脸识别:这份 OpenCV 实战包到底装了什么

很多人第一次做人脸识别,卡住的地方根本不是算法,而是环境。装完 OpenCV 发现cv2.face模块不存在,或者摄像头一开就报设备被占用,再或者拿到的代码里路径全是作者本机的绝对路径。这份opencv人脸识别实战操作.zip解决的就是这类问题——它把机器视觉里最经典的人脸检测、特征提取、识别比对串成了一条能直接跑的链路,而不是丢给你一堆零散函数。适合两类人:一是刚接触人工智能、想用 Python 把摄像头跑起来的入门者;二是做过图像处理、但没系统走过人脸识别全流程的工程师。它不涉及深度学习训练,核心是 OpenCV 自带的 Haar 级联和 LBPH 算法,好处是 CPU 就能跑、依赖少、代码透明,坏处也明显——光照和角度一变就翻车。下面我按实际拆包顺序讲清楚怎么用、参数怎么调、坑在哪。

2. 环境与依赖:把 opencv-contrib 装对,别在第一步就翻车

2.1 为什么必须是 opencv-contrib 而不是普通 opencv

人脸识别模块cv2.face属于 OpenCV 的 contrib 扩展库,普通pip install opencv-python装出来的包里根本没有这个模块。这是新手最常见的翻车点:代码里写着recognizer = cv2.face.LBPHFaceRecognizer_create(),一运行就报AttributeError: module 'cv2' has no attribute 'face'。原因不是代码错,是包装错了。

常见做法是直接装 contrib 版本,它包含了主库加扩展模块:

# 卸载可能已存在的普通版本,避免两个包冲突 pip uninstall opencv-python opencv-contrib-python -y # 安装带 contrib 的完整版,人脸识别模块就在里面 pip install opencv-contrib-python # 验证 face 模块是否可用 python -c "import cv2; print(cv2.__version__); print(hasattr(cv2, 'face'))"

逻辑说明:先卸载是为了防止opencv-python和opencv-contrib-python同时存在时,Python 导入到没有 face 模块的那个。最后一行验证会打印版本号和True,只要出现False就说明装的还是普通版。参数上不用指定版本号,除非你的项目对某个旧 API 有依赖,那种情况再锁版本。

提示:如果你用的是 conda 环境,对应命令是conda install -c conda-forge opencv,但 conda 的包有时 contrib 模块裁剪过,装完同样要用上面那行验证。

2.2 摄像头与文件路径的初始化检查

环境装好后,第二步是确认视频源能用。OpenCV 读摄像头用cv2.VideoCapture(0),读视频文件把 0 换成路径。这里有个容易被忽略的点:VideoCapture创建失败不会抛异常,而是返回一个对象,isOpened()才是False。很多人不检查直接read(),拿到的是空帧,后面全崩。

import cv2 # 0 表示默认摄像头,笔记本通常是内置那个 cap = cv2.VideoCapture(0) # 必须显式检查,创建失败不会报错 if not cap.isOpened(): print("摄像头打开失败,检查是否被其他程序占用") exit() # 设置分辨率,不是所有摄像头都支持任意分辨率 cap.set(cv2.CAP_PROP_FRAME_WIDTH, 640) cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 480) while True: ret, frame = cap.read() if not ret: print("读取帧失败,可能是设备断开") break cv2.imshow("frame", frame) # 按 q 退出,waitKey 必须调用否则窗口不刷新 if cv2.waitKey(1) & 0xFF == ord('q'): break cap.release() cv2.destroyAllWindows()

逻辑说明:cap.set设置的分辨率是请求值,摄像头可能返回最接近的可用值,所以别假设读到的帧一定是你设的尺寸,后面做人脸检测前最好用frame.shape确认一下。waitKey(1)里的 1 是毫秒,值越小循环越快,但太小会导致窗口无响应,一般 1 到 30 之间。参数上,如果你有多个摄像头,把 0 换成 1、2 逐个试。

3. 人脸检测:Haar 级联的参数怎么调才不误检

3.1 detectMultiScale 四个参数的实际含义

检测环节用的是 Haar 级联分类器,OpenCV 自带训练好的 XML 文件,比如haarcascade_frontalface_default.xml。核心函数是detectMultiScale,它返回一组矩形框,每个框是一个人脸位置。这个函数有四个关键参数,调不好就是漏检或满屏误检。

import cv2 # 加载人脸检测器,路径来自 OpenCV 安装目录的 data 文件夹 face_cascade = cv2.CascadeClassifier( cv2.data.haarcascades + 'haarcascade_frontalface_default.xml' ) # 确认分类器加载成功,空对象检测时会报错 if face_cascade.empty(): raise IOError("级联分类器加载失败,检查路径") img = cv2.imread("test.jpg") gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 关键参数:缩放步长、最小邻居数、最小尺寸 faces = face_cascade.detectMultiScale( gray, scaleFactor=1.1, # 每次图像缩小比例 minNeighbors=5, # 一个候选框周围至少有几个邻居才保留 minSize=(30, 30) # 小于这个尺寸的不当人脸 ) for (x, y, w, h) in faces: cv2.rectangle(img, (x, y), (x + w, y + h), (0, 255, 0), 2) cv2.imshow("result", img) cv2.waitKey(0) cv2.destroyAllWindows()

逻辑说明:scaleFactor=1.1表示每次把图像缩小 10% 再检测,值越小检测越细但越慢,1.05 到 1.2 是常用区间。minNeighbors控制误检,值越大越严格,漏检也越多,5 是平衡点,人脸密集场景可以降到 3。minSize用来过滤远处的小噪点,设太小会把纹理误判成人脸。参数没有万能值,得拿你的实际画面试。

3.2 灰度转换与直方图均衡化的作用

Haar 特征是在灰度图上算的,所以必须先cvtColor转灰度。但只转灰度还不够,光照不均时检测率会掉。常见做法是加一步直方图均衡化,把对比度拉开。

# 转灰度后做均衡化,改善背光或过曝场景 gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) gray = cv2.equalizeHist(gray) # 用均衡化后的图检测 faces = face_cascade.detectMultiScale(gray, 1.1, 5, minSize=(30, 30))

逻辑说明:equalizeHist把像素值重新分布,让暗部细节更清楚。代价是噪声也会被放大,如果画面本身噪点多,均衡化后误检可能增加,这时候要么先做高斯模糊,要么干脆不加这一步。我一般会两种都跑一遍,看哪种框得准。

注意:Haar 检测对正脸有效,侧脸、低头、遮挡基本检不到。如果你的场景人脸角度变化大,这套方案本身就不合适,得换基于深度学习的方法,但那就超出这份资源范围了。

4. 训练与识别:LBPH 的样本采集和阈值设定

4.1 采集样本时的命名规范与数量

LBPH 是局部二值模式直方图,属于传统机器学习方法,需要先用带标签的人脸图训练模型。这份资源里的流程通常是:给每个人采集一批人脸图,存成label.序号.jpg的格式,label 是整数编号。采集时最容易犯的错是数量不够或角度单一。

import cv2 import os face_cascade = cv2.CascadeClassifier( cv2.data.haarcascades + 'haarcascade_frontalface_default.xml' ) # 用户编号,采集前手动指定 user_id = 1 save_dir = "dataset" os.makedirs(save_dir, exist_ok=True) cap = cv2.VideoCapture(0) count = 0 while count < 30: # 每人采集 30 张 ret, frame = cap.read() if not ret: break gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) faces = face_cascade.detectMultiScale(gray, 1.1, 5, minSize=(80, 80)) for (x, y, w, h) in faces: count += 1 # 只保留人脸区域,减少背景干扰 face_roi = gray[y:y + h, x:x + w] # 统一尺寸,LBPH 对尺寸不敏感但统一后更稳 face_roi = cv2.resize(face_roi, (200, 200)) cv2.imwrite(f"{save_dir}/{user_id}.{count}.jpg", face_roi) cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2) cv2.imshow("collect", frame) if cv2.waitKey(1) & 0xFF == ord('q'): break cap.release() cv2.destroyAllWindows()

逻辑说明:minSize=(80, 80)比检测时设得大,是为了保证采集到的人脸有足够像素,太小的图训练出来没意义。每人 30 张是经验值,太少模型不稳,太多训练变慢。采集时要让人稍微转动头部、变换表情,覆盖不同状态,否则模型只认采集时那个姿势。文件名里的序号从 1 递增,训练脚本靠文件名前缀解析 label。

4.2 训练模型与置信度阈值

采集完就该训练了。LBPH 训练很快,CPU 几秒到几十秒。训练完保存成 yml 文件,识别时加载。识别返回两个值:label 和 confidence。这里有个反直觉的点——confidence 在 LBPH 里是距离,值越小表示越像,不是概率。

import cv2 import numpy as np from PIL import Image import os # 读取数据集,解析 label path = "dataset" recognizer = cv2.face.LBPHFaceRecognizer_create() faces = [] ids = [] for file in os.listdir(path): if file.endswith(".jpg"): img_path = os.path.join(path, file) # 转灰度,LBPH 只吃灰度图 gray_img = Image.open(img_path).convert('L') img_np = np.array(gray_img, 'uint8') # 文件名格式 label.序号.jpg,取第一段做标签 label = int(file.split(".")[0]) faces.append(img_np) ids.append(label) recognizer.train(faces, np.array(ids)) recognizer.save("trainer.yml") print("训练完成,样本数:", len(faces))

逻辑说明:Image.open().convert('L')是转灰度的稳妥写法,比cv2.imread(..., 0)在某些格式上更可靠。np.array(..., 'uint8')保证数据类型一致,否则训练会报类型错误。保存的trainer.yml就是模型文件,识别时用recognizer.read()加载。

识别阶段的阈值设定是玄学重灾区:

recognizer = cv2.face.LBPHFaceRecognizer_create() recognizer.read("trainer.yml") # 识别时判断置信度,小于 50 认为可信 label, confidence = recognizer.predict(gray_face) if confidence < 50: print(f"识别为 {label},置信度 {confidence:.1f}") else: print("未知人脸")

逻辑说明:confidence 是距离值,0 表示完全一样,越大越不像。50 这个阈值不是固定的,取决于你的样本质量和人数。人少时阈值可以设 40 到 60,人多时要收紧到 30 左右,否则容易认错。我一般会拿几张没参与训练的照片测一遍,看已知人脸的 confidence 分布,再定阈值。

5. 避坑与排查:五个真实踩过的坑

5.1 现象:检测框满屏乱跳,人脸反而没框住

原因:minNeighbors设得太低,或者画面噪声大导致 Haar 把纹理当人脸。解决:先把minNeighbors提到 6 到 8,再加一步高斯模糊cv2.GaussianBlur(gray, (5, 5), 0)压噪。如果还乱跳,检查是不是把scaleFactor设成了 1.0,那会导致计算量爆炸且误检增多。

5.2 现象:训练时报 "labels must be integers"

原因:从文件名解析 label 时拿到了字符串,或者文件名格式不统一,比如有的叫1.jpg有的叫1.1.jpg,split后取到的段不对。解决:统一命名规范,解析后强制int()转换,并在训练前打印一遍 ids 列表确认全是整数。

5.3 现象:识别时所有人都被判成同一个人

原因:样本里某个人占了绝大多数,或者采集时背景没变化,LBPH 学到了背景而不是人脸。解决:保证每人样本数接近,采集时换几个位置和光照。另外检查是不是忘了resize到统一尺寸,尺寸差异过大会让直方图对不齐。

5.4 现象:摄像头读几帧后就卡死

原因:waitKey没调用或参数为 0,导致 GUI 事件不处理;或者cap.read()返回的帧没及时释放,缓冲区堆积。解决:确保循环里有cv2.waitKey(1),并且不要在循环里做耗时操作,比如每帧都存图。如果用的是笔记本,检查是不是被其他会议软件占用了摄像头。

5.5 现象:换台机器跑,路径全报错

原因:代码里写了作者本机的绝对路径,比如C:/Users/xxx/dataset。解决:全部改成相对路径,用os.path.join拼接,数据集和模型文件放在脚本同级目录。这份资源里的脚本如果带绝对路径,第一件事就是全局替换成相对路径。

6. 进阶技巧:用置信度分布反推阈值,而不是拍脑袋

阈值定不好,识别要么认错要么全判未知。与其凭感觉设 50,不如用数据说话。做法是:拿一批已知标签的测试图,跑一遍predict,把每个人的 confidence 收集起来,看分布。已知人脸的 confidence 应该集中在一个区间,未知人脸则普遍偏高。两条分布的交叠处就是阈值该放的位置。

import cv2 import numpy as np import os recognizer = cv2.face.LBPHFaceRecognizer_create() recognizer.read("trainer.yml") face_cascade = cv2.CascadeClassifier( cv2.data.haarcascades + 'haarcascade_frontalface_default.xml' ) # 收集已知人脸的置信度 known_scores = [] test_dir = "test_known" for file in os.listdir(test_dir): img = cv2.imread(os.path.join(test_dir, file)) gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) faces = face_cascade.detectMultiScale(gray, 1.1, 5) for (x, y, w, h) in faces: roi = cv2.resize(gray[y:y+h, x:x+w], (200, 200)) label, conf = recognizer.predict(roi) known_scores.append(conf) # 收集未知人脸的置信度 unknown_scores = [] test_dir2 = "test_unknown" for file in os.listdir(test_dir2): img = cv2.imread(os.path.join(test_dir2, file)) gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) faces = face_cascade.detectMultiScale(gray, 1.1, 5) for (x, y, w, h) in faces: roi = cv2.resize(gray[y:y+h, x:x+w], (200, 200)) label, conf = recognizer.predict(roi) unknown_scores.append(conf) print("已知人脸置信度:均值 %.1f,最大 %.1f" % (np.mean(known_scores), np.max(known_scores))) print("未知人脸置信度:均值 %.1f,最小 %.1f" % (np.mean(unknown_scores), np.min(unknown_scores)))

逻辑说明:如果已知人脸的 max 是 45,未知人脸的 min 是 60,那阈值设在 50 到 55 之间就合理。如果两者交叠严重,说明模型区分度不够,得回去补样本或换特征。这个方法的代价是需要准备两组测试图,但比反复试参数靠谱得多。

场景建议阈值说明
人数少于 5 人50 到 60类间差异大,可以放宽
人数 5 到 20 人35 到 50需要平衡误识和拒识
人数超过 20 人25 到 35类间距离近,必须收紧
光照变化大在基础上减 5置信度整体偏高,阈值要降

从那以后我每次调 LBPH 阈值,都强制先跑一遍置信度分布,不再靠猜。这套流程虽然土,但比盲目试参数省时间。希望帮到你。

本文还有配套的精品资源,点击获取

相关新闻

EfficientNetV2架构深度解析:tf_efficientnetv2_b3.in1k为何能又快又小?

EfficientNetV2架构深度解析:tf_efficientnetv2_b3.in1k为何能又快又小?

【免费下载链接】tf_efficientnetv2_b3.in1k 项目地址&#xff1a; https://ai.gitcode.com/hf_mirrors/timm/tf_efficientnetv2_b3.in1k 点击查看 免费下载 本文以开源预训练模型 tf_efficientnetv2_b3.in1k 为例&#xff0c;带你快速看懂这个图像分类模型&#xff1a;它仅用…

2026/10/20 2:01:14 阅读更多 →
GhostTrack:IP归属、号码归属与用户名注册速查——不用开浏览器

GhostTrack:IP归属、号码归属与用户名注册速查——不用开浏览器

GhostTrack&#xff1a;IP归属、号码归属与用户名注册速查——不用开浏览器 【免费下载链接】GhostTrack Useful tool to track location or mobile number 项目地址: https://gitcode.com/GitHub_Trending/gh/GhostTrack GhostTrack 是一个 Python 编写的 OSINT 脚本&a…

2026/10/20 2:01:14 阅读更多 →
Linux内核6.x学习路线:从环境搭建到调试进阶的专栏指南

Linux内核6.x学习路线:从环境搭建到调试进阶的专栏指南

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

2026/10/20 2:01:14 阅读更多 →

最新新闻

博途1500PLC字符串包含判断:FOR+MID滑动窗口实现详解

博途1500PLC字符串包含判断:FOR+MID滑动窗口实现详解

用博途1500PLC判断源字符串中是否含有子字符串&#xff0c;这个需求听起来简单&#xff0c;我第一次在现场做的时候也以为一条指令就完事了。那是条包装线的扫码工位&#xff0c;读码器通过Profinet把条码送进PLC&#xff0c;我需要在ABC240315001XYZ这样的字符串里判断有没有2…

2026/10/20 2:37:36 阅读更多 →
大模型Token计费全解析:从分词原理到成本优化实战

大模型Token计费全解析:从分词原理到成本优化实战

记得我刚接触大模型开发那会儿&#xff0c;最让我头疼的还真不是提示词怎么写&#xff0c;而是后台账单上的那一串token数字。明明感觉没聊几句&#xff0c;钱就悄悄没了&#xff0c;看计费详情时又一头雾水。后来自己跑接口做应用&#xff0c;才彻底搞明白Token到底是什么&…

2026/10/20 2:37:36 阅读更多 →
剪纸主题网页制作指南:HTML+CSS+JavaScript实现传统美学与交互设计

剪纸主题网页制作指南:HTML+CSS+JavaScript实现传统美学与交互设计

前两天有个同学跑过来问我&#xff0c;说期末作业想做“Web剪纸”主题的网页&#xff0c;不知道怎么把剪纸这种传统手艺和网页制作结合起来。我当时一听就觉得这个选题选得挺聪明的——剪纸是最有辨识度的中国民间视觉符号之一&#xff0c;红色、镂空、对称&#xff0c;任何一个…

2026/10/20 2:37:36 阅读更多 →
Ubuntu循环登录自救指南:从tty命令行到图形会话修复全流程

Ubuntu循环登录自救指南:从tty命令行到图形会话修复全流程

1. 循环登录的典型症状与背后机制1.1 症状什么样&#xff0c;怎么判断是不是它作为常年折腾桌面Linux的人&#xff0c;Ubuntu循环登录这五个字几乎每年都要见上几次。它不是某个品牌的独家问题&#xff0c;也不是Ubuntu 22.04才有的新毛病。我经手的案例里&#xff0c;从18.04到…

2026/10/20 2:37:36 阅读更多 →
文科生AI提效指南:从认知到实操的工作流全拆解

文科生AI提效指南:从认知到实操的工作流全拆解

“文科生的逆袭时代”&#xff0c;这句话这两年我听得太多了。每次和文科背景的同行、朋友聊起来&#xff0c;大家的核心焦虑其实特别一致&#xff1a;AI这么猛&#xff0c;是不是要把我们这些靠笔杆子、靠理解力、靠沟通吃饭的人给替代了&#xff1f;但我在实际接触和带团队的…

2026/10/20 2:37:36 阅读更多 →
Godot 2D游戏开发第5期:打通场景切换、敌人AI与UI音效的可玩闭环

Godot 2D游戏开发第5期:打通场景切换、敌人AI与UI音效的可玩闭环

做2D游戏做到第五期&#xff0c;最容易遇上的状态就是&#xff1a;玩家已经能跑能跳了&#xff0c;但游戏还不像游戏。前四期我们一路把角色动画、基础TileMap关卡、金币收集勉强拼了出来&#xff0c;可一旦想打通从"进入关卡"到"死亡重来"再到"结算展…

2026/10/20 2:36:35 阅读更多 →

日新闻

CLRC663芯片Pin-to-Pin替代实战:从评估到量产全记录

CLRC663芯片Pin-to-Pin替代实战:从评估到量产全记录

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

2026/10/20 1:01:30 阅读更多 →
ESP32舵机控制指南:原理、多路驱动与避坑实战

ESP32舵机控制指南:原理、多路驱动与避坑实战

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

2026/10/20 1:01:30 阅读更多 →
位移法实现一阶低通滤波:单片机ADC采样降噪实战

位移法实现一阶低通滤波:单片机ADC采样降噪实战

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

2026/10/20 1:01:30 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型&#xff08;GMM&#xff09;的语音识别系统&#xff0c;很多人第一反应就是一堆数学公式&#xff0c;觉得门槛很高。但如果你真的在MATLAB里把它落地跑通&#xff0c;会发现核心其实就是三件事&#xff1a;把声音变成特征向量&#xff0c;用GMM给每个类别…

2026/10/19 10:02:04 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人&#xff0c;但落到具体操作上&#xff0c;无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程&#xff1a;对图像做反白、改调色板、彩色转灰度&#xff0c;最后把像素数据导出成txt文件。单看每一…

2026/10/19 17:32:41 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词&#xff0c;你会发现一个很有意思的现象&#xff1a;每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型&#xff0c;有人指的是运动控制系统&#xff0c;还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/19 1:30:52 阅读更多 →

月新闻

我发现了一个新思路:用 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/19 2:54: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/19 9:10:22 阅读更多 →
黑夜航拍船只数据集训练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/18 12:16:16 阅读更多 →