尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

OpenCV课程包Python 2.7迁移实战:从SVM到深度学习目标检测

OpenCV课程包Python 2.7迁移实战:从SVM到深度学习目标检测 简介面向高校计算机专业学生的计算机视觉与人工智能开源教学项目以OpenCV、Python、TensorFlow、Keras为技术栈基于CASIS数据集实现多模态图像处理与目标检测算法帮助学习者把深度学习理论与工程代码相结合。压缩包共220个文件大小41.23MB包含55个py源码、4个ipynb交互式教程、54张jpg与48张png图像样本、38个xml标注/配置文件以及avi/mp4演示视频和pdf/txt说明文档覆盖数据预处理、模型训练到检测演示的完整链路。目前已有60人学习下载。提供三个Session的ipynb教程结合演示视频可直观展示从环境配置到目标检测结果的可视化过程PDF与TXT文档补充了安装指南、项目背景与使用说明旨在降低上手门槛。整体目录按课程模块组织既适合课堂演示也适合学生课后对照源码进行实验和二次开发可作为课程设计与自学项目参考。1. 打开压缩包看到三个 Notebook 和四个 AVI先别急着关掉这个课程包的命名很长但真正决定它是否能跑的是_run_winpack_demo_python27.cmd和三个CASIS-OpenCV-Course_Session*.ipynb。四个视频不是摆设768x576.avi、tree.avi、Megamind.avi、Megamind_bugy.avi分别对应不同的测试场景后面的 SVM 模型和字母数据则把传统机器学习和深度学习串在一条线上。它解决的是高校计算机专业学生「只懂 API、不懂任务链路」的问题——从读视频帧、构造多通道特征到用 SVM 分类、再用 TensorFlow/Keras 搭建卷积网络最后落到目标检测每一步都有可跑的实验。想快速补项目经验的学生、要在课堂上带实验的老师、以及从传统 CV 转向深度学习的工程人员都能从这个包里抽出可复用的代码框架。不过要提醒一句脚本是为 Python 2.7 写的如果直接双击.cmd大概率会踩环境坑本文就从迁移环境开始。2. 环境准备OpenCV、TensorFlow 与 Keras 的版本兼容和安装验证因为_run_winpack_demo_python27.cmd明确提到 python27而现在的系统基本都是 python3所以第一步不是直接跑项目而是构造一个能同时容纳 OpenCV、Scikit-learn、TensorFlow 和 Keras 的虚拟环境。你会发现只要版本不匹配import cv2都能报错更不用说后面的tf.keras了。下面给出一套我常用的组合按「先图像库、再机器学习库、最后深度学习库」的顺序安装避免依赖互相覆盖。2.1 为什么要从 Python 2.7 迁到 Python 3原项目的演示脚本带python27字样这在教学包里很常见OpenCV 课程发布时很多学校还在用 Python 2.7。但如今 OpenCV 4.x 的 Python 绑定和 TensorFlow 2.x 早已放弃 Python 2.7直接沿用旧脚本会碰到print语法、xrange不存在、cv2.xxx接口变更等问题。迁移不是把print加括号那么简单更关键的是 OpenCV 的 API 名称和默认参数变了。例如旧代码常用cv2.cv.Scalar新版本需要改为cv2.Scalar或直接用元组cv2.CreateHOGDescriptor变成了cv2.HOGDescriptor。因此先在 Python 3 下面重建环境再逐个修改导入和调用是成本最低的方式。2.2 用虚拟环境安装 OpenCV 和深度学习框架我一般会先建一个干净的虚拟环境避免把系统 Python 搞乱。下面的命令在 Windows/Linux 上都适用只要先准备好 Python 3.9 或 3.10。TensorFlow 2.13 在 Python 3.11 上也很稳定但如果你用的是 3.12需要留意包是否全部发布。# 创建并激活虚拟环境假设项目解压在 D:/CASIS python -m venv D:/CASIS/.venv # Windows: .venv\Scripts\activate Linux/macOS: source .venv/bin/activate # 安装依赖。opencv-contrib-python 用于读取视频和额外模块二者不可重复安装。 pip install opencv-python opencv-contrib-python4.8.1.78 # scikit-learn 用于 SVM 与数据划分numpy/scipy 会自动带上 pip install scikit-learn1.3.2 # TensorFlow 2.x 自带 keras但单独装 keras 可以固定版本 pip install tensorflow2.13.0 keras2.13.1 # Notebook 环境与可视化 pip install jupyter matplotlib这段命令刻意把opencv-contrib-python固定为 4.8.1.78是因为它的视频后端和 SIFT 等模块比较稳定不用频繁跟随新版变化。scikit-learn锁定 1.3.2 是与 Python 3.9/3.10 兼容较好的版本如果装得更新某些旧代码里的train_test_split行为会略有不同。TensorFlow 与 Keras 必须保持主版本一致例如 TensorFlow 2.13 配 Keras 2.13否则会在from tensorflow import keras时出现AttributeError。Jupyter 只是用来打开课程提供的.ipynb不是运行所必需。安装完之后用下面这段验证代码确认所有库都能被正确导入import cv2 import numpy as np import sklearn import tensorflow as tf from tensorflow import keras print(OpenCV:, cv2.__version__) print(NumPy:, np.__version__) print(scikit-learn:, sklearn.__version__) print(TensorFlow:, tf.__version__) print(Keras:, keras.__version__) # 测试 VideoCapture没有摄像头时对象创建后 isOpened 为 False cap cv2.VideoCapture(0) if not cap.isOpened(): print(摄像头不可用但 OpenCV 安装正常)这段代码有两个目的一是打印版本号确认依赖没有互相覆盖二是通过VideoCapture的创建行为检查 OpenCV 的视频后台是否正常。如果cap.isOpened()返回 False不代表安装失败只是没有可用摄像头或当前环境没有视频输入设备之后读 AVI 文件时走文件路径即可。cv2.__version__是最直观的检查点OpenCV 4.8.x 的输出会类似4.8.1如果你看到 3.x请重新安装。2.3 项目文件与 Notebook 的对应关系解压后你会看到一堆扩展名不同的文件它们并不是散乱的素材。下表是我在复跑时整理出来的对应关系。文件/目录类型在教学项目中的用途CASIS-OpenCV-Course_Session1.ipynbNotebook图像读取、灰度化、颜色空间转换等基础操作CASIS-OpenCV-Course_Session2.ipynbNotebook特征提取、SVM 分类、OCR 与字母识别CASIS-OpenCV-Course_Session3.ipynbNotebook神经网络、TensorFlow/Keras 图像分类与目标检测768x576.avi视频文件课程主测试视频分辨率 768x576用于帧处理演示tree.avi视频文件户外/树木场景适合测试背景建模和运动分割Megamind.avi视频文件动画片段目标运动明显用于检测结果可视化Megamind_bugy.avi视频文件可能是故意制造 bug 的版本用于调试训练digits_svm.dat模型文件OpenCV 预训练的手写数字 SVM 模型可被cv2.ml.SVM_load读取letter-recognition.data特征数据UCI 字母识别数据集16 维特征用于传统机器学习实验_run_winpack_demo_python27.cmd脚本Windows 上的一键演示脚本设置环境并启动 Session 代码这张表帮助你快速定位Session1里讲的往往是视频帧和颜色通道Session2会把digits_svm.dat和letter-recognition.data用到极致Session3才开始让神经网络登场。Megamind_bugy.avi这个带bugy的名字在课程里经常是故意截断或换编码的版本用来训练学生识别“视频读取失败”和“模型跑飞”的差异。实际操作时最好按 Session1→Session3 顺序执行不要先跑深度学习因为后面会用到前面构造的特征函数。2.4 安装层最常见的三个坑第一个坑是ModuleNotFoundError: No module named opencv。容易看错正确包名是opencv-python导入时用import cv2不是import opencv。第二个坑是 TensorFlow 与 NumPy 的 ABI 不兼容会出现Segmentation fault或core dumped。解决办法是把numpy降到 TensorFlow 要求的范围内比如 TensorFlow 2.13 要求numpy1.24的某个版本直接执行pip install numpy1.24。第三个坑是_run_winpack_demo_python27.cmd里写死了 Python 27 路径双击后要么闪退要么提示找不到python.exe。提示在迁移阶段不要双击.cmd运行整个项目而是用jupyter notebook逐个打开 Notebook先跑通过一个单元格再继续。这样可以第一时间看到哪个 API 不兼容。等你把环境跑通下一步才是真正进入图像处理而不是花半天时间解决环境报错。这里我固定了版本是想让你少走弯路。3. 多模态图像处理在 OpenCV 中的落地AVI 视频读取与多通道特征拼接这一章要处理 CASIS 包里的四个视频。很多教程只教你cv2.imread读一张图但教学项目把视频当作图像序列来喂给模型所以必须先理解怎么从 AVI 中持续拿到帧再把一帧图像拆成多个模态特征。3.1 什么叫“多模态”以及如何用普通摄像头模拟多模态图像处理的本意是融合来自不同传感器的信息比如可见光与红外、RGB 与深度图。在这个教学包里并没有真正的红外相机但可以用同一帧图像的不同表示来模拟多模态BGR 是原始模态HSV 是色相模态灰度是亮度模态Canny 边缘是结构模态。把它们沿通道方向拼接起来就得到多通道特征张量后面的分类器或检测器可以从不同「视角」学习目标外观。这也是为什么不建议直接省略这一步——很多目标检测算法在特征图上做融合与这里的多通道拼接思想一致。下面代码演示了从768x576.avi中读取一帧并拼出多通道特征import cv2 import numpy as np cap cv2.VideoCapture(768x576.avi) if not cap.isOpened(): raise IOError(无法打开 768x576.avi请检查视频编码或文件路径) # 读取第 30 帧作为样例跳过前面的无用帧 for _ in range(30): ret, frame cap.read() if not ret: break # 如果视频是 BGR 顺序转换成备用表示 gray cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) hsv cv2.cvtColor(frame, cv2.COLOR_BGR2HSV) edges cv2.Canny(gray, 50, 150) # 手动把 3 通道 BGR、3 通道 HSV、单通道 grey、单通道 edges 拼成 8 通道张量 # dstack 沿第三维堆叠等价于 np.concatenate([...], axis2) multi_modal np.dstack([frame, hsv, gray[..., np.newaxis], edges[..., np.newaxis]]) print(拼接后的张量形状:, multi_modal.shape) cap.release()逻辑说明ret是VideoCapture.read()返回的布尔值表示这一帧是否解码成功在文件路径错误或编码不支持时ret会一直为False。cvtColor把 BGR 转成灰度或 HSV供后面的特征提取使用。Canny用两个阈值50和150检测边缘低于 50 的梯度被认为是噪声高于 150 的一定是边缘介于两者之间则看是否与已检测到的边缘相连。np.dstack是沿第三维堆叠这样multi_modal的形状就是(高, 宽, 8)其中第 0-2 通道来自 BGR第 3-5 通道来自 HSV第 6 通道是灰度第 7 通道是边缘。如果你把三张单通道图直接传给分类器很容易丢失空间关联而拼接成多通道后卷积网络可以直接把这 8 个通道当输入。3.2 视频参数与帧率控制768x576.avi这个文件名直接点明了视频尺寸宽 768 像素、高 576 像素。处理视频时不能假设所有视频都同尺寸tree.avi和Megamind.avi的长宽比不同。用CAP_PROP_*可以读到真实参数并在训练前统一缩放到一个固定大小。下面的代码打印了常用参数fps cap.get(cv2.CAP_PROP_FPS) width cap.get(cv2.CAP_PROP_FRAME_WIDTH) height cap.get(cv2.CAP_PROP_FRAME_HEIGHT) total cap.get(cv2.CAP_PROP_FRAME_COUNT) print(fFPS{fps}, 分辨率{width}x{height}, 总帧数{total}) # 跳转到第 100 帧再读取 cap.set(cv2.CAP_PROP_POS_FRAMES, 100) ret, frame cap.read()参数说明CAP_PROP_FPS得到的是浮点数别在计算帧间隔时直接用整型CAP_PROP_FRAME_WIDTH和CAP_PROP_FRAME_HEIGHT对应视频宽高CAP_PROP_FRAME_COUNT是文件内总帧数对不稳定的网络流或某些压缩格式可能不准确。cap.set(cv2.CAP_PROP_POS_FRAMES, 100)是随机跳转但不是所有编码器都支持精确跳帧如果发现跳到奇怪的位置可以用连续读取替代。3.3 用背景建模处理 tree.avi 和 Megamind.avi多模态特征拼接后下一步是检测视频中的运动目标。tree.avi这种场景摄像机不动只有树在风中摇晃适合用背景差分把前景分离出来Megamind.avi是动画目标轮廓清晰背景建模速度也会快很多。OpenCV 提供了createBackgroundSubtractorMOG2不需要每帧都手工差分。back_sub cv2.createBackgroundSubtractorMOG2( history500, varThreshold16, detectShadowsTrue ) cap cv2.VideoCapture(tree.avi) while cap.isOpened(): ret, frame cap.read() if not ret: break # 多模态用灰度作为输入也可以换成 3.1 拼接后的多通道数据 gray cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) fg_mask back_sub.apply(gray) # 去除噪声 fg_mask cv2.medianBlur(fg_mask, 5) cv2.imshow(foreground, fg_mask) if cv2.waitKey(30) 0xFF ord(q): break cap.release() cv2.destroyAllWindows()这里history500表示用于背景建模的帧数值越大对光线变化越不敏感但初始适应越慢varThreshold16是像素值变化的阈值值越小对前景越敏感容易把阴影也当成前景。detectShadowsTrue会生成灰色阴影标记后续可以通过只保留白色像素来过滤阴影。注意apply可以直接传入彩色帧内部会转灰度这里手动转是为了保持与前面多模态代码一致。waitKey(30)控制每帧显示 30 毫秒约 33fps如果你的屏幕卡顿可以调大到 50 或 100。3.4 不同视频文件的差异决定了参数必须调整tree.avi的叶子晃动属于小幅度运动varThreshold默认的 16 可能会产生大量噪点而Megamind.avi角色移动幅度大同样的阈值就能得到干净的前景。遇到Megamind_bugy.avi时如果视频解码出现绿屏或花屏问题大概率不在算法而在编码格式。我的处理方式是先用 OpenCV 读参数确认fourcc编码再统一用cv2.VideoCapture解码如果解码失败用 FFmpeg 转成 MP4 再继续不纠结于原文件格式。下表总结了调整方向视频特征建议设置树叶/水波等细碎运动varThreshold调大到 2540medianBlur核调大到 7明显的大目标移动varThreshold保持 16history减小到 300 以加快适应带阴影的室内场景开启detectShadows后续用fg_mask 255过滤灰色分辨率不是 768x576cv2.resize统一到 224x224 或 512x512再进网络完成背景建模后可以用cv2.findContours拿到每个前景目标的边框这样就把多模态特征和运动目标检测接在了一起。而这正为下一章的分类和检测任务提供数据来源。4. 从 SVM 到深度学习CASIS 数据集上的分类与目标检测实验这一章是整个项目的重头戏。CASIS 包里同时提供了传统机器学习模型文件和深度学习 Notebook正好用来对比「特征工程 轻量模型」和「端到端神经网络」两条路线。先看 SVM再转 Keras最后把它们组装到一个简单的目标检测流程里。4.1 用 OpenCV 的 SVM 模型识别手写数字digits_svm.dat是 OpenCV 自带的预训练模型可以直接加载并预测 20x20 的手写数字图像。它属于传统的支持向量机输入是 HOG 或原始像素特征输出是 0-9 的分类。很多学生上来就写cv2.SVM()但在 OpenCV 4 中 SVM 类在cv2.ml命名空间下必须用cv2.ml.SVM_load加载。下面是一段可运行的预测代码假设你有一张 28x28 的灰度手写数字digit.pngimport cv2 import numpy as np # 加载项目提供的模型 svm_model cv2.ml.SVM_load(digits_svm.dat) # 读取并预处理输入图像 img cv2.imread(digit.png, cv2.IMREAD_GRAYSCALE) img cv2.resize(img, (20, 20)) # OpenCV 官方训练用 20x20 img img.reshape(1, 400).astype(np.float32) # 拉平为一行特征 img img / 255.0 # 归一化到 [0,1] _, result svm_model.predict(img) print(预测结果:, int(result[0][0]))逻辑很简单SVM_load从.dat文件恢复模型参数之后predict会返回一个二维数组第一维是样本数第二维是预测类别。这里把图像缩放到20x20是因为模型训练时用的就是 400 维特征如果尺寸不匹配会出现特征维度错误。归一化用img / 255.0而不是img - 255因为 SVM 对特征尺度比较敏感保持 [0,1] 能避免某些样本距离计算被大数主导。如果你拿到的是letter-recognition.data可以通过numpy.loadtxt读取最后一列是字母标签前 16 列是特征训练一个线性 SVM 也能达到 90% 左右准确率这一步留给 Notebook 里的练习去验证。4.2 用 TensorFlow/Keras 构造 CNN 分类模型SVM 需要人工设计特征而 TensorFlow 和 Keras 能自动从原始像素中学习特征。下面的代码定义了一个轻量卷积网络适配 CASIS 视频中裁剪出来的目标区域。Keras 默认张量顺序是(batch, height, width, channels)所以这里把单通道灰度图也显式保留为最后一维。from tensorflow import keras from tensorflow.keras import layers model keras.Sequential([ layers.Input(shape(32, 32, 1)), layers.Conv2D(32, kernel_size(3, 3), activationrelu), layers.MaxPooling2D(pool_size(2, 2)), layers.Conv2D(64, kernel_size(3, 3), activationrelu), layers.MaxPooling2D(pool_size(2, 2)), layers.Flatten(), layers.Dense(64, activationrelu), layers.Dense(10, activationsoftmax) # 10 类数字或目标类别 ]) model.compile( optimizeradam, losssparse_categorical_crossentropy, metrics[accuracy] ) model.summary()这个网络包含两个卷积层第一个 32 个卷积核捕捉简单边缘第二个 64 个卷积核捕捉更复杂的纹理。MaxPooling2D把特征图缩小一半减少参数并增加平移不变性。Flatten把二维特征图拉成一维Dense(64)做非线性组合最后输出 10 类概率。训练时要用整数标签所以损失函数用sparse_categorical_crossentropy如果标签是 one-hot就要换回categorical_crossentropy。model.summary()打印参数量你可以看到结构是否合理例如输入 32x32 单通道经过两层池化后特征图尺寸会变成 8x8如果你觉得分类结果差可以增加卷积核数量。训练的数据可以直接从视频帧中裁剪 ROI也可以使用 sklearn 的train_test_split对letter-recognition.data划分。建议先跑通上面的结构再把学习率从默认的 0.001 调低到 0.0001防止在小型数据集上过拟合。4.3 目标检测的最小可用流程背景差分 剪裁 CNN由于 CASIS 课程不是让每个学生从零训练目标检测网络而是希望你把前面的模块组合起来所以这里给出一个工程上最常用的 检测 分类 级联方案先用背景建模从Megamind.avi中找出运动区域再对每个区域做resize和 CNN 分类。这个流程在算力受限的教学环境里跑得动也方便你验证算法效果。def detect_and_classify(video_path, svm_model, cnn_model): cap cv2.VideoCapture(video_path) back_sub cv2.createBackgroundSubtractorMOG2(history200, varThreshold25) while cap.isOpened(): ret, frame cap.read() if not ret: break fg back_sub.apply(frame) # 找到所有运动区域的外包矩形 contours, _ cv2.findContours(fg, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) for cnt in contours: if cv2.contourArea(cnt) 500: # 滤除小噪点 continue x, y, w, h cv2.boundingRect(cnt) roi frame[y:yh, x:xw] roi cv2.cvtColor(roi, cv2.COLOR_BGR2GRAY) roi cv2.resize(roi, (32, 32)) # 三维数组batch_size1, height32, width32, channels1 roi_tensor roi.reshape(1, 32, 32, 1).astype(float32) / 255.0 score cnn_model.predict(roi_tensor, verbose0) label int(score.argmax(axis1)[0]) cv2.rectangle(frame, (x, y), (xw, yh), (0, 255, 0), 2) cv2.putText(frame, str(label), (x, y-10), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 255, 0), 2) cv2.imshow(detection, frame) if cv2.waitKey(30) ord(q): break cap.release() cv2.destroyAllWindows()这段代码把前面三章的知识全部串了起来。findContours在 OpenCV 4 中返回两个值和 3.x 的三返回值不同所以这里写contours, _。cv2.contourArea(cnt) 500表示只保留面积大于 500 像素的连通域这个阈值要根据视频分辨率调整768x576 下 500 像素相当于极小目标如果你处理的是 1280x720建议改成 1500。roi frame[y:yh, x:xw]是 Python 的切片索引注意行列顺序是[y, x]翻转时会出错。CNN 的predict每次只处理一张图速度较慢实际项目中可以用model.predict_batch或改用 TensorFlow Serving但教学场景这样写最直观。4.4 对比SVM 和 CNN 在 CASIS 数据上的取舍传统 SVM 模型digits_svm.dat的大小只有几百 KB推理极快即使没有 GPU 也能在视频上实时跑而 Keras CNN 虽然准确率更高但模型参数多、推理慢尤其在纯 CPU 环境下每帧预测会卡顿。CASIS 教学项目同时保留两者目的就是让你体会当训练数据少、类别固定时SVM 往往够用当数据量增大、场景多变时CNN 的特征泛化能力更强。这也是我建议在实验报告中同时给出两种模型的 FPS 和准确率的原因。在转移到下一环节前务必保存训练好的模型svm_model.save(mysvm.dat) # cv2.ml.SVM 类型可直接保存 cnn_model.save(cnn_model.keras) # Keras 3 推荐的格式 # 也可以用 HDF5 格式兼容旧代码 # cnn_model.save(cnn_model.h5)保存模型时OpenCV 的 SVM 和 Keras 使用两种完全不同的序列化方式不要混用。.dat是 OpenCV 专有.keras或.h5是 Keras 的格式。如果你要把模型传给同学最好附上模型结构、输入尺寸和归一化方式否则对方不知道输入是 32x32 还是 20x20。5. 迁移与验证把 Python 2.7 的 Windows 演示脚本改成现代流程最后一章落到一个很实际的技巧如何让_run_winpack_demo_python27.cmd在你的电脑上重新变得可执行以及怎样快速判断迁移是否成功。这个脚本的核心功能大概率是设置工作目录、把 Notebook 临时转成.py文件然后调用 Python 执行它。既然我们已经在虚拟环境里完全可以用一个简化脚本替代它。5.1 用等价的 bash 脚本替代 cmd下面是 Linux/macOS 下的自验证脚本Windows 用户可以把它改写成run_demo.bat逻辑一致#!/bin/bash # 切换到项目根目录防止相对路径失效 cd $(dirname $0) # 激活虚拟环境 source .venv/bin/activate # 用 nbconvert 把三个 Session 转成可执行脚本再逐个执行 jupyter nbconvert --to script --execute \ --ExecutePreprocessor.timeout120 \ CASIS-OpenCV-Course_Session1.ipynb \ CASIS-OpenCV-Course_Session2.ipynb \ CASIS-OpenCV-Course_Session3.ipynb echo 如果以上输出没有抛异常说明环境迁移成功。关键参数是--ExecutePreprocessor.timeout120它指定每个单元格最长执行 120 秒。CASIS 项目中如果包含 GPU 训练120 秒可能不够可以改成600或直接None。nbconvert --to script会把.ipynb转为同名.py但生成的代码会包含 Jupyter 的魔术命令比如%matplotlib inline会报错所以更稳妥的做法是删掉脚本中的魔术命令或者直接使用jupyter nbconvert --execute保持 Notebook 环境。5.2 验证视频和模型是否真正可用迁移后不要直接开始写新代码先跑一组快速检查import cv2 test_videos [768x576.avi, tree.avi, Megamind.avi, Megamind_bugy.avi] for name in test_videos: cap cv2.VideoCapture(name) if not cap.isOpened(): print(f[FAIL] {name} 无法打开) else: ret, frame cap.read() print(f[OK] {name}, shape{frame.shape if ret else decode error}) cap.release()这段代码用isOpened确认视频文件可以被 OpenCV 解码再用read取一帧验证实际数据是否能完整读到。frame.shape会输出(576, 768, 3)表示高、宽、通道数顺序和很多同学的直觉相反注意别在之后编写代码时把宽高写反。5.3 把传统视频帧输出为 MP4 的技巧最终课程作业经常需要提交结果视频旧脚本的 AVI 格式在新的浏览器里可能无法直接播放。用 OpenCV 写 MP4 时要注意编码器匹配out cv2.VideoWriter( result.mp4, cv2.VideoWriter_fourcc(*mp4v), fps30, frameSize(768, 576) ) # 循环中写入处理后的帧 out.write(frame_with_box) out.release()fourcc必须用四个字符的编码标签*mp4v解包成四个字母。如果播放器读不出文件请检查frameSize是否与写入的帧尺寸完全一致不一致时VideoWriter不会报错但生成的文件会损坏或黑屏。此外cv2.waitKey(30)是毫秒数写视频时不要把waitKey和VideoWriter的帧率混搞。至此CASIS 这个课程包就不再是一个“下载完就吃灰”的压缩包而是一套可以继续扩展的基线代码。你可以在同一份视频数据上尝试更换不同的 CNN 结构、调整 SVM 的核函数或者把背景建模换成更贴合目标的检测器逐步形成自己的计算机视觉项目。最后记得把视频统一转为 MP4 编码用cv2.VideoWriter_fourcc(*mp4v)输出便于在作业或博客中直接展示。本文还有配套的精品资源点击获取
返回列表