简介一份面向Qt/C开发者的OpenCV人脸识别工程示例适合希望在桌面应用里集成计算机视觉能力的初学者与进阶开发者。资源演示了在Qt环境中配置OpenCV、调用Haar级联分类器检测人脸并在GUI界面上用QPainter实时标注检测区域同时涉及灰度化、直方图均衡化等预处理操作涵盖从工程创建到界面显示的完整链路。压缩包共19个文件包含3个C源文件、3个头文件、pro工程配置文件、ui界面设计文件、两个级联分类器XML含常用的frontalface模型、翻译支持文件、Makefile及排错日志等整体仅2.06MB结构紧凑便于按模块对照学习。已有1655人学习下载。通过完整源码、界面设计与日志记录读者既能快速复现基础人脸检测流程也能参考其针对资源路径错误、库版本不兼容等典型问题的调试思路进一步迁移到实时视频流或性能优化等扩展场景很适合作为人脸识别入门项目的起点。1. 认识 QtOpenCV 人脸识别工程为什么“能跑”与“能用”差着一整套编译环境你从网上下载了一个叫“QtOpenCV人脸识别.zip”的工程压缩包解压之后里面是.pro文件、一堆.cpp和.h还有几个 xml 文件和图片文件夹。你满心以为打开 Qt Creator 点一下运行就能看到摄像头画面结果等了五分钟编译报错刷了一屏窗口根本没弹出来。这不是运气问题而是这个标题背后实际上有三层东西Qt 负责界面和事件循环OpenCV 负责图像采集与算法而两者之间的编译器版本、链接库和线程协作才是这个项目真正的主战场。这类项目能解决的问题很具体——本地摄像头实时画面、人脸检测、人脸比对、在界面上显示姓名或置信度最常见的落地场景是门禁机、考勤机、实验室签到和课堂点名。它适合已经有 C 基础、手上有 Windows 开发环境、想把自己的 OpenCV 图像处理能力嵌进桌面产品的人。如果你只想要一个网页里能跑的识别 demo这个工程帮不了你但如果你要把视频流接进带界面的桌面程序它是很典型的起步框架。2. Qt 与 OpenCV 的版本匹配是第一道门槛MSVC、位宽与编译器三件套2.1 为什么 Qt 5.15.2 和 OpenCV 4.5.5 是常见搭配打开压缩包里的.pro文件你大概率会看到 Qt 5.15.2 或者类似版本号写在注释里。Qt 5.15.2 属于 LTS 版本官方安装包通常提供两种工具链MinGW 和 MSVC2019 64bit。我这里直接说结论做 QtOpenCV 人脸识别请优先选MSVC2019 64bit不要用 MinGW。原因是 OpenCV 官方 Windows 安装包只提供 MSVC 编译好的二进制库vc14/vc15/vc16 分别对应 VS2015、VS2017、VS2019。Qt 5.15.2 自带的 MSVC2019 64bit 库和 OpenCV 的 vc16 库是同一套 ABI链接时最省事。MinGW 的二进制格式和 MSVC 不互通你想让两者一起工作要么自己用 MinGW 重新编译整个 OpenCV要么忍受各种奇怪的链接错误。对于“下载一个 zip 就想跑起来”的诉求统一到 MSVC 是少走弯路的选择。如果你手头只有 VS2022也不是不能用。VS2022 向下兼容 VS2019 的库格式但最容易踩的坑是 Qt Creator 自动检测到 VS2022 工具集后生成 vc17 的构建套件。我一般会在 Kit 里手动改成 Microsoft Visual C 2019 (x86_64)确保它匹配 Qt 5.15.2 的预编译库。这个细节决定你接下来一小时是顺利编译还是和moc、qmake报错搏斗。2.2 用 .pro 文件把 OpenCV 接进 Qt 工程压缩包如果是 qmake 工程核心配置就在.pro文件里。打开之后一般长这样# FaceRecognizer.pro QT core gui widgets # 界面相关模块 CONFIG c17 # 用 C17vector 和智能指针都好用 INCLUDEPATH D:/opencv/opencv/build/include \ D:/opencv/opencv/build/include/opencv2 LIBS -LD:/opencv/opencv/build/x64/vc16/lib \ -lopencv_world455d # Debug 模式链接带 d 的库Release 模式下要把opencv_world455d换成opencv_world455也就是去掉那个 d。两边如果写反编译期不一定报错但运行阶段会直接提示找不到opencv_world455.dll或者内存访问异常。这是这个项目里出现频率最高的低级错误后面避坑章会再展开。INCLUDEPATH指向的目录必须能看到opencv2/opencv.hpp。很多人配置完还是报opencv2/opencv.hpp: No such file or directory基本是路径少写了一层opencv2因为 OpenCV 的头文件实际在build/include/opencv2下面。程序里写#include opencv2/opencv.hpp编译器会在你给的 include 目录里找opencv2/opencv.hpp所以INCLUDEPATH要写到.../include这一层而不是.../include/opencv2。2.3 运行时找不到 DLL环境变量与 windeployqt编译链接只是第一步运行阶段 OpenCV 的动态库也得能被系统找到。常见做法是手动把D:/opencv/opencv/build/x64/vc16/bin加进系统 PATH然后重启 Qt Creator。注意重启是必须的Qt Creator 不会实时读新的环境变量不重启就运行仍然报找不到 dll而且报错信息里会带着绝对路径让你误以为是代码问题。更好的做法是在 Qt 的命令行环境里执行windeployqt这个工具会把程序依赖的 Qt 运行库自动拷贝到 exe 所在目录。但windeployqt不处理 OpenCV 的 dll所以实际发布时我一般是两条命令一起用先windeployqt release/你的程序名.exe再把opencv_world455.dll手动拷进 release 目录。这样别人拿到整个文件夹就能跑不需要再配置任何环境变量。3. 用 Qt 界面接住摄像头画面VideoCapture 到 QImage 的显示链路3.1 打开摄像头VideoCapture 的初始化和参数设定摄像头采集在 Qt 工程里通常不直接用 Qt Multimedia而是交给 OpenCV 的cv::VideoCapture因为后续帧处理要用 OpenCV 做直接一条链路处理更简单。初始化参数很直接// CameraWidget.cpp #include opencv2/opencv.hpp cv::VideoCapture cap; bool openCamera() { if (!cap.open(0)) { // 0 表示默认摄像头 return false; } cap.set(cv::CAP_PROP_FRAME_WIDTH, 640); cap.set(cv::CAP_PROP_FRAME_HEIGHT, 480); cap.set(cv::CAP_PROP_FPS, 30); return true; }参数说明open(0)读的是系统默认摄像头如果你机器上接了 USB 摄像头而内置摄像头被禁用可能要试open(1)或open(2)。640x480 是识别类任务比较稳的分辨率分辨率越高detectMultiScale耗时越长界面就越卡。CAP_PROP_FPS是期望帧率实际帧率取决于摄像头固件OpenCV 底层只是尽量调度到接近这个值。我一般不会在第一版就接摄像头而是先用一个cap.open(test.mp4)调试显示链路。视频文件和摄像头在VideoCapture的接口上完全一致先用文件把 Qt 界面调通再切回摄像头能少踩很多“摄像头没插好”之外的坑。3.2 cv::Mat 转 QImage格式、步长与内存拷贝这是 Qt 和 OpenCV 结合最核心的一个步骤。OpenCV 的默认通道顺序是 BGR而 Qt 的QImage::Format_RGB888需要 RGB 顺序直接转会让画面偏蓝偏红看起来像坏了一样。正确的转法是先cvtColor再构造 QImage// CameraWidget.cpp #include QImage #include QPixmap QImage matToQImage(const cv::Mat mat) { cv::Mat rgb; cv::cvtColor(mat, rgb, cv::COLOR_BGR2RGB); return QImage(rgb.data, rgb.cols, rgb.rows, static_castint(rgb.step), QImage::Format_RGB888).copy(); }最后那个.copy()很多人会丢掉但它恰恰是最关键的一步。QImage构造函数只拿了rgb.data的指针不会复制数据rgb是cvtColor的临时变量函数一退出数据就释放了界面再去绘制这片内存就是典型的悬垂指针表现是画面闪烁、花屏甚至直接崩溃。.copy()做一次深拷贝把像素数据复制进 QImage 自己的缓冲区之后 OpenCV 那边的内存随便释放画面都安全。rgb.step是 OpenCV 里一行的字节数。摄像头画面宽度通常按 4 字节对齐step不一定等于cols * channels所以构造 QImage 时一定要把step传进去否则图像会有一条条斜线。如果你看到画面是斜着撕裂的九成是这个参数没传对。3.3 用 QTimer 驱动采集识别线程不卡界面摄像头采集和识别不能放在界面线程的循环里否则拖动窗口时画面会停止看起来像死机。Qt 开发里常见的做法是用QTimer定时触发采集把耗时操作放在槽函数里执行// CameraWidget.cpp #include QTimer QTimer *timer new QTimer(this); void startVideo() { connect(timer, QTimer::timeout, this, CameraWidget::onFrame); timer-start(33); // 约 30 帧每秒 } void onFrame() { cv::Mat frame; if (!cap.read(frame)) return; cv::Mat small; cv::resize(frame, small, cv::Size(640, 480)); QImage img matToQImage(small); ui-screenLabel-setPixmap( QPixmap::fromImage(img).scaled(ui-screenLabel-size(), Qt::KeepAspectRatio)); }timer-start(33)对应约 30fps。如果你的机器跑识别时 CPU 已经拉满就把间隔改到50也就是 20fps换来的是整体帧率稳定不忽快忽慢。注意cap.read(frame)是阻塞的它从摄像头驱动读一帧通常耗时很短真正耗时的是后面的人脸检测如果每帧都要检测建议把检测逻辑放到独立线程用信号槽把结果传回界面线程去刷新标签。4. 人脸识别逻辑落到 Qt 界面上Haar 检测与 LBPH 的完整联动4.1 用 CascadeClassifier 做检测加载模型与参数调优人脸识别分两段检测是“脸在哪里”识别是“这是谁”。OpenCV 图像处理里最常见的检测方案是 Haar 级联分类器模型文件是haarcascade_frontalface_default.xml在 OpenCV 安装包的sources/data/haarcascades目录下可以找到。把这个 xml 拷贝到工程目录里加载和检测的代码如下// FaceDetector.cpp #include opencv2/objdetect.hpp cv::CascadeClassifier faceCascade; bool initDetector() { if (!faceCascade.load(./haarcascade_frontalface_default.xml)) { return false; } return true; } std::vectorcv::Rect detectFaces(const cv::Mat gray) { std::vectorcv::Rect faces; faceCascade.detectMultiScale(gray, faces, 1.1, // scaleFactor每次缩放 10% 5, // minNeighbors邻居框数量 0, // flags旧 API 填 0 cv::Size(60, 60)); // 最小检测框 return faces; }scaleFactor是每次图像缩小的比例1.1是精度和速度的平衡点。调成1.05检测更精细但更慢调成1.2速度快但容易漏检。minNeighbors是至少要有几个相邻框重叠才算真脸值越大误检越少但也会漏掉侧脸正脸正面场景5是标准值。cv::Size(60, 60)过滤掉太小的人脸如果你要检测屏幕里很远的人这个值还可以再降到40但要注意小尺寸框的误检率会上升。4.2 用 LBPH 训练识别模型样本准备与训练代码检测出人脸之后识别部分我一般用 OpenCV 的 LBPHLocal Binary Patterns Histograms局部二值模式直方图。LBPH 的优势是不需要 GPU、不依赖深度学习框架CPU 上做一张人脸比对只要几毫秒对新手很友好。它的坑在于需要 OpenCV contrib 模块如果你的 OpenCV 是官方默认安装包可能没有face.hpp编译会报找不到头文件。解决方式是换用带 contrib 的安装包或者直接用 vcpkg 安装opencv4[contrib]。训练数据的组织方式是一个人的照片放一个文件夹文件名里带 label 和序号比如person01_001.jpg。训练代码逻辑如下// FaceTrainer.cpp #include opencv2/face.hpp std::vectorcv::Mat images; std::vectorint labels; // 遍历样本目录灰度化后塞进 images cv::Mat gray cv::imread(path, cv::IMREAD_GRAYSCALE); images.push_back(gray); labels.push_back(1); // 1 表示 person01 cv::Ptrcv::face::LBPHFaceRecognizer model cv::face::LBPHFaceRecognizer::create(); model-train(images, labels); model-save(./lbph_model.yml);训练之前最好用 4.1 节的人脸检测把样本裁成纯人脸只保留额头到下巴区域。样本越干净LBPH 的直方图特征越稳定。我实际训练时每类至少准备 20 张光照要尽量接近真实场景否则会出现“训练时准换上摄像头就不认人”的情况。4.3 识别与置信度预测结果如何映射到界面显示模型训练好之后运行时加载模型对检测到的人脸框做灰度化、缩放然后调用predict// FaceRecognizer.cpp model-load(./lbph_model.yml); int label -1; double confidence 0.0; model-predict(grayFace, label, confidence); if (label 1 confidence 80.0) { ui-nameLabel-setText(QStringLiteral(张三)); } else { ui-nameLabel-setText( QStringLiteral(陌生人置信度 %1).arg(confidence)); }confidence是输入人脸与训练样本的直方图距离数值越大表示越不像。80这个阈值是经验值光照好的环境可以收紧到70光照差的环境要放宽到90。如果你发现陌生人频繁被识别成本人就是阈值太宽反过来本人被识别成陌生人就是阈值太紧。这个参数没有绝对标准必须基于你自己的摄像头环境去调后面进阶章会讲怎么系统地验证。5. 踩坑记录MSVC 错、debug/release 混用、黑屏和识别率翻车的 4 个案例5.1 现象编译报错:-1: error: dependent ..\..\..\..\qt\5.15.2\msvc2019_64\include\qtwidget\... does not exist先看 Qt Creator 底部的编译输出如果错误以:-1: error:开头这是项目级别的错误不是代码语法错误。我见过最普遍的原因是构建套件Kit选错。压缩包里的.pro是为 MSVC 写的你打开时如果 Qt Creator 自动选择了 MinGW Kit它去查找 MSVC 版本的 Qt 头文件路径拼接出来就是这种..\..\..\qt\5.15.2\msvc2019_64的乱码。解决点左侧“项目”标签在 Build 设置里把 Kit 切换成Qt 5.15.2 MSVC2019 64bit然后重新执行 qmake。如果 Kit 列表里没有这个选项回到 Qt 安装器补装 MSVC2019 64bit 组件。这类问题几乎都和版本不对应有关检查顺序是“编译器位数 - Qt 库版本 - qmake 是否重新跑”。5.2 现象编译通过运行时提示找不到opencv_world455.dll这是环境变量问题。OpenCV 的 dll 在D:/opencv/opencv/build/x64/vc16/bin下面这个目录没有加入系统 PATHWindows 搜索动态库时就找不到了。解决把上述 bin 目录加到系统 PATH关闭并重启 Qt Creator。如果你是直接双击 exe 运行重启 exe 就行。这里有个更隐蔽的情况debug 工程链接了opencv_world455d.dll带 drelease 工程链接了opencv_world455.dll如果你只往输出目录拷了其中一个另一个模式运行照样报错。我一般直接两个 dll 都拷避免来回切换模式时又踩一遍。5.3 现象画面有窗口但摄像头黑屏或花屏偏色黑屏最常见的两个原因摄像头被别的程序占用或者QImage构造出的格式不对。先排除占用问题把微信、腾讯会议之类可能抢摄像头的程序都关掉再试。如果仍然黑屏看代码里有没有做 BGR 到 RGB 的转换没转的话画面是蓝橙色调不是黑屏但一眼能看出来不对。花屏斜线则是步长问题。构造QImage时传给构造函数的step必须是frame.step不能自己想当然写frame.cols * 3。有些摄像头输出的行有对齐填充写死cols * 3会让图像错位。这个坑我之前以为是相机坏了排查了半天才发现是步长写死导致。伸手就能复现的验证方式是先用本地图片文件跑matToQImage如果图片显示正常而摄像头花屏再去怀疑步长和格式。5.4 现象识别率忽高忽低换了环境就不认人LBPH 对光照极其敏感同样的脸工位暖光下训练走到走廊白炽灯下识别置信度可能从 40 跳到 120直接判成陌生人。这不是模型坏了是特征分布变了。解决思路有两个一是训练样本刻意覆盖多种光照让模型学到的直方图更泛化二是在送入predict之前做预处理比如直方图均衡化cv::equalizeHist把灰度分布拉平减少光照干扰。另外把阈值从 80 改到 90~100 也能降低拒识率但会引入更多误识别。我一般优先做样本覆盖和预处理阈值只在最后微调。还有一个需要顺手提的提醒很多人搜“OpenCV 安装”会看到 Python 教程里面说“cv2 安装成功却找不到”那是 Python 的包管理问题和 C 工程无关。你在这个 Qt 工程里不会遇到 cv2搜索时带上Qt Creator、MSVC这些词结果才和当前项目匹配。把 Python 那套思路套到 C 工程上往往越调越乱。6. 从 demo 到门禁级换 DNN 模型、调置信度阈值与一条验证习惯6.1 检测升级用 OpenCV DNN 替代 Haar 级联Haar 级联在侧脸、遮挡和暗光场景下漏检明显。如果你的目标是人脸识别门禁机这类产品检测部分要考虑换成 OpenCV DNN 模块加载深度模型。DNN 的接口不复杂加载模型后输入 blob输出的是人脸框和关键点准确率和 Haar 不在一个量级。代价是模型文件几十 MB而 Haar 的 xml 才 1 MB 左右。6.2 验证方法用历史数据调阈值不管是 LBPH 还是深度学习特征识别阈值都需要用数据说话。我现在的习惯是建一个test文件夹里面放本人和陌生人的照片各几十张每次调完参数跑一遍统计误识率和拒识率把结果记在笔记本上。调阈值时不要只看两三个样本至少跑 50 张图再下结论。这个习惯让我少走了很多弯路——置信度 80 听起来合理但只有数据能告诉你它适不适合你的摄像头和你的光照。人脸识别工程的最后一公里往往不在算法而在参数标定。每换一个摄像头、每换一处安装位置模型都要重新验证一遍。我现在拿到这类工程第一件事不是读代码而是先确认编译器版本和 OpenCV 库匹配再跑一张测试图片看颜色对不对最后才碰算法参数——这个顺序帮我避掉了九成环境问题。希望帮到你。本文还有配套的精品资源点击获取
企业数字化 ERP 产品动态
相关推荐
人机协同的挑战与突破:从技术原理到实践应用 1. 人机协同的本质与挑战 人机协同(Human-Machine Collaboration)这个概念听起来很美好,但真正落地时总会遇到各种"水土不服"。我在工业自动化领域做了八年系统集成,参与过二十多个号称"人机协同"的项目&… · 2026/11/4 16:25:47
Beamer模板四层结构解析:从翻车到可控的学术PPT工程化 1. 为什么“Beamer”模版不是改改颜色就完事——从一场答辩翻车说起去年帮某高校实验室的A同学调试毕业答辩PPT,他提前一周发来文件,说“按导师要求用了Beamer,只调了主题色和字体,应该没问题”。我打开一看,首页标题字… · 2026/11/5 4:42:54
PageIndex 深度解析:页面级索引如何提升 RAG 检索准确率 1. 从标题到本质:PageIndex 到底想解决什么问题第一次看到 PageIndex 这个名字,我下意识以为又是一个做分页组件的 UI 库。直到把它和 RAG、LLM、向量数据库这几个词放在一起,才反应过来——这大概率是一个围绕“页面级索引”做文章的知识检索… · 2026/11/4 19:02:45
邯郸电工证资格证是上岗必备,这些你知道吗? 邯郸电工证资格证是上岗必备,这些你知道吗? 急需特种作业证才能上岗找工作,这是很多在郑州的应届工程类毕业生面临的现实问题。尤其是像 邯郸电工证资格证… · 2026/11/8 13:16:57
恩平可以买电工证吗?全国通用的电工证怎么考? 恩平可以买电工证吗?全国通用的电工证怎么考? 你是不是正在恩平找工作,但因为没有电工证而被拒?别急,今天咱们就来聊一聊【恩平可以买电工证吗】,告诉你全国通用的电工证怎么考、怎么用、怎么避免踩坑。 恩平可以买电工证吗?正规途径在哪里?… · 2026/11/8 13:16:57
电工证学历门槛低?卢雷冬电工证报考指南+良心建议 电工证学历门槛低?卢雷冬电工证报考指南+良心建议 学历不高怕报不上名?卢雷冬电工证其实没有你想象中那么难!今天咱们就来聊聊怎么考这个证,别再被“学历”两个字吓退了。 卢雷冬电工证到底是什么?… · 2026/11/8 13:16:57
阳江市办理高压电工证真实经历:怕考不过白交培训费?别踩这些坑 阳江市办理高压电工证真实经历:怕考不过白交培训费?别踩这些坑 怕考不过白交培训费?阳江市办理高压电工证的伙伴们,我今天就从一个真实经历出发,告诉你怎么避开那些坑,少走弯路。去年我身边有个朋友,花了三千多报了个高压电工证培训班,结果考试没过,… · 2026/11/8 13:16:57
电工证题库简答怎么准备?良心建议帮你稳过实操考试 电工证题库简答怎么准备?良心建议帮你稳过实操考试 实操考试心里没底怕挂科,特别是电工证题库简答部分,不少人都在这上面栽过跟头。别慌,今天就从焦作市政公用工程从业者的角度出发,给你 良心建议… · 2026/11/8 13:16:57
兰州电工证哪里办理值不值得考 电工证对工地人员真的有帮助吗 兰州电工证哪里办理值不值得考 电工证对工地人员真的有帮助吗 工地太忙根本没时间复习考试,你是被甲方催着赶工期,还是被工头逼着出工?很多在工地干电工的兄弟都遇到过这样的问题:手里没证,干不了活;手里有证,又怕考试不过白忙一场。特别是兰州地区,… · 2026/11/8 13:15:57
电工证丢失还能补吗?千万别踩坑,丢了证等于失业 电工证丢失还能补吗?千万别踩坑,丢了证等于失业 你正在找工作,但手里的电工证突然丢了,这下怎么办?别急,先别慌, 电工证丢失还能补吗 ?答案是肯定的,但 千万别踩坑 ,补办流程如果不了解,可能会耽误你上岗、甚至影响到你的收入。… · 2026/11/8 0:00:20
电力电缆作业证直播报名入口与办理流程良心建议 电力电缆作业证直播报名入口与办理流程良心建议 你是不是也担心学历不高报不了名?别急,今天就给你讲讲 电力电缆作业证直播 的报名流程和那些你必须知道的干货, 良心建议 在这里,别错过。 电力电缆作业证直播报名需要什么条件?… · 2026/11/8 0:00:20
英德电工证报考费多少钱,怕考不过白交培训费?看完这篇别再踩坑 英德电工证报考费多少钱,怕考不过白交培训费?看完这篇别再踩坑 怕考不过白交培训费?英德电工证报考费多少钱,你真的了解吗?现在市面上培训机构五花八门,价格参差不齐,很多人一不小心就花了冤枉钱,结果还考不过。别急,今天就来给你说清楚英德电工证的… · 2026/11/8 0:00:20
电工证丢失还能补吗?千万别踩坑,丢了证等于失业 电工证丢失还能补吗?千万别踩坑,丢了证等于失业 你正在找工作,但手里的电工证突然丢了,这下怎么办?别急,先别慌, 电工证丢失还能补吗 ?答案是肯定的,但 千万别踩坑 ,补办流程如果不了解,可能会耽误你上岗、甚至影响到你的收入。… · 2026/11/8 0:00:20
电力电缆作业证直播报名入口与办理流程良心建议 电力电缆作业证直播报名入口与办理流程良心建议 你是不是也担心学历不高报不了名?别急,今天就给你讲讲 电力电缆作业证直播 的报名流程和那些你必须知道的干货, 良心建议 在这里,别错过。 电力电缆作业证直播报名需要什么条件?… · 2026/11/8 0:00:20
英德电工证报考费多少钱,怕考不过白交培训费?看完这篇别再踩坑 英德电工证报考费多少钱,怕考不过白交培训费?看完这篇别再踩坑 怕考不过白交培训费?英德电工证报考费多少钱,你真的了解吗?现在市面上培训机构五花八门,价格参差不齐,很多人一不小心就花了冤枉钱,结果还考不过。别急,今天就来给你说清楚英德电工证的… · 2026/11/8 0:00:20
双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/7 11:25:08
STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/7 12:02:18
DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/8 1:18:25