OpenCv读取视频

import cv2
import numpy as np

window_name = "figure"
cap = cv2.VideoCapture("./2.mp4")
# 告诉OpenCv使用人脸识别分类器
# 获取人脸识别训练数据
classfier = cv2.CascadeClassifier(r"D:\Program Files\Abacibda36\Lib\site-packages\cv2\data\haarcascade_frontalface_alt_tree.xml")

# 识别出人脸后要画的边框的颜色,RGB格式
color = (0, 255, 0)

while(1):
    # get a frame
    ret, frame = cap.read()
    if not ret:
        break
    # 将当前帧转换成灰度图像
    grey = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

    # 人脸检测,1.1和2分别为图片缩放比例和需要检测的有效点数
    faceRects = classfier.detectMultiScale(grey, scaleFactor=1.1, minNeighbors=3,minSize=(10,10))

    if len(faceRects) > 0:  # 大于0则检测到人脸
        for faceRect in faceRects:  # 单独框出每一张人脸q
            x, y, w, h = faceRect
            cv2.rectangle(frame, (x - 10, y - 10), (x + w + 10, y + h + 10), color, 2)

    # 显示图像
    cv2.imshow(window_name, frame)
    if cv2.waitKey(100) & 0xFF == ord('q'):
        break

cap.release()
cv2.destroyAllWindows()

源码解析:


C/C++原函数

     void detectMultiScale( InputArray image,
                      CV_OUT std::vector<Rect>& objects,
                      double scaleFactor = 1.1,
                      int minNeighbors = 3, int flags = 0,
                      Size minSize = Size(),
                      Size maxSize = Size() );
参数意义:

参数1:image–待检测图片,一般为灰度图像加快检测速度;
参数2:objects–被检测物体的矩形框向量组;为输出量,如人脸检测矩阵Mat
参数3:scaleFactor–表示在前后两次相继的扫描中,搜索窗口的比例系数。默认为1.1即每次搜索窗口依次扩大10%;一般设置为1.1
参数4:minNeighbors–表示构成检测目标的相邻矩形的最小个数(默认为3个)。
如果组成检测目标的小矩形的个数和小于 min_neighbors - 1 都会被排除。
如果min_neighbors 为 0, 则函数不做任何操作就返回所有的被检候选矩形框,
这种设定值一般用在用户自定义对检测结果的组合程序上;
参数5:flags–要么使用默认值,要么使用CV_HAAR_DO_CANNY_PRUNING,如果设置为CV_HAAR_DO_CANNY_PRUNING,那么函数将会使用Canny边缘检测来排除边缘过多或过少的区域,因此这些区域通常不会是人脸所在区域;
参数6、7:minSize和maxSize用来限制得到的目标区域的范围。也就是我本次训练得到实际项目尺寸大小

函数介绍

多尺度:通常搜索目标的模板尺寸大小是固定的,但是不同图片大小不同,所以目标对象的大小也是不定的,所以多尺度即不断缩放图片大小(缩放到与模板匹配),通过模板滑动窗函数搜索匹配;同一副图片可能在不同尺度下都得到匹配值,所以多尺度检测函数detectMultiscale是多尺度合并的结果。
多目标:通过检测符合模板匹配对象,可得到多个目标,均输出到objects向量里面。

detectMultiScale函数中目标检测对象的最大尺寸和最小尺寸:

#include "stdafx.h" #include"highgui.h" int main(int argc,char* argv[]) { cvNamedWindow( "avi"); CvCapture* capture = cvCreateFileCapture( "D:\\sample.avi"); IplImage* frame; while(1) { frame = cvQueryFrame(capture); if(!frame) break ; cvShowImage( "avi",frame); char c = cvWaitKey(33); if(c == 27) break; } cvReleaseCapture(&capture); cvDestroyWindow( "avi"); return 0; } 结构体 CvCapture CvCapture 是一个结构体,用来保存图像捕获所需要的信息。 opencv提供两种方式从外部捕获图像: 一种是从摄像头中, 一种是通过解码视频得到图像。 两种方式都必须从第一帧开始一帧一帧的按顺序获取,因此每获取一帧后都要保存相应的状态和参数。 比如从视频文件中获取,需要保存视频文件的文件名,相应的解码器类型,下一次如果要 获取将需要解码哪一帧等。 这些信息都保存在CvCapture结构中,每获取一帧后,这些信息 都将被更新,获取下一帧需要将新信息传给获取的 api接口 cvCreateFileCapture(char*name) 通过输入要读取的avi文件的路径,然后,该函数返回一个指向 CvCapture结构体的指针。 cvQueryFrame(capture) 输入一个CvCapture 类型的指针,该函数主要功能是将视频文件的下一帧加载到内存。与 cvLoadImage的不同之处是,该函数不重新分配内存空间。 C=cvWaitKey(33) 当前帧被显示后,等待 33毫秒。如果用户触发了一个按键, c会被设置成这个按键的 ASCII码,否则会被设置成 -1。 cvWaitKey(33) 在此处的另外一个作用是,控制帧率。 cvReleaseCapture(&capture) 释放为 CvCapture结构体开辟的内存空间 关闭打开的 AVI文件相关的文件句柄 读取摄像头 只需把 cvCreateFileCapture 改成cvCreateCameraCapture即可。 该函数的输入参数是一个 ID号,只有存在多个摄像头时才起作用。当 ID=-1时,表示 随机选择一个。 HighGUI做了很多工作,使得摄像机图像序列像一个视频文件一样。 cvCreateFileCapture返回空的问题 ( 1)视频文件路径没写对( 2)没有安装解码器( 3)如果使用的是 Opencv2.0或更高版本,那么,能否正确加载 opencv_ffmpeg210.dll( 4)尽管是 AVI文件,但也可能使用了某种 codec,例如 :MJPEG Decompressor。 需要把它转换 OpenCV支持的 AVI文件 . OpenCV支持的AVI。例如使用狸窝全能视频转换器,在《预置方案》处,选择 AVI-Audio_Video Interleaved(*.avi)。或者使用格式工厂也可以。( 5)读摄像头数据,需要安装与摄像头相应的驱动程序。
<think>好的,我现在需要帮助用户解决如何使用Qt和OpenCV读取视频的问题。用户还要求提供示例代码和教程。首先,我得回忆一下Qt和OpenCV的相关知识,确保自己理解正确。 首先,Qt是一个跨平台的C++框架,常用于开发图形用户界面。而OpenCV是一个开源的计算机视觉库,提供了丰富的图像和视频处理功能。用户想要结合这两者来读取视频,可能需要用到Qt的界面组件来显示视频,同时用OpenCV处理视频流。 接下来,我应该考虑如何用OpenCV读取视频OpenCV中的VideoCapture类是用来处理视频的,可以捕获摄像头输入或者读取视频文件。用户可能需要示例代码来展示如何打开视频文件,逐帧读取,并在Qt的界面中显示这些帧。 然后,Qt部分需要考虑如何显示图像。通常,QImage和QPixmap用于处理图像数据,而QLabel或自定义的QWidget可以用来显示图像。可能需要将OpenCV的Mat格式转换为QImage,以便在Qt中显示。 另外,视频的实时显示可能需要用到定时器(QTimer)来定期读取下一帧,保持视频流畅播放。同时,还要注意线程问题,避免界面卡顿,但可能用户暂时不需要多线程,基础示例可以先使用单线程。 现在需要检查是否有相关的引用资料。根据用户提供的引用[1]和[2],里面提到Qt和OpenCV结合进行图像和视频操作,例如读取和显示图像,捕获视频。引用[2]还提到应用举例,说明可能有示例代码可以参考。虽然具体的代码可能没有在引用中给出,但可以基于这些信息构建示例。 开始编写示例代码的结构: 1. 包含必要的头文件,比如OpenCV的core和highgui,Qt的QApplication, QLabel, QTimer等。 2. 创建VideoCapture对象,打开视频文件。 3. 检查是否成功打开视频。 4. 创建Qt的窗口和标签用于显示。 5. 使用定时器每隔一定时间读取一帧,并更新标签内容。 6. 将Mat转换为QImage时需要注意颜色空间的转换,因为OpenCV默认是BGR,而Qt是RGB。 7. 处理循环,直到视频结束。 需要注意的问题:是否正确处理视频路径,转换颜色空间,释放资源,以及错误处理。例如,如果视频打不开,需要提示用户。 可能还需要说明如何配置项目,比如在.pro文件中添加OpenCV的库链接,不过用户可能已经配置好了环境,所以示例代码可能不需要这部分,但可以建议用户检查环境配置。 现在,将这些步骤转化为具体的代码。例如: 在Qt的主窗口类中,初始化VideoCapture,设置定时器,连接定时器的信号到槽函数,在槽函数中读取帧并显示。 同时,确保代码中的错误处理,比如使用isOpened()检查视频是否打开成功。 最后,测试代码是否可行,是否有内存泄漏,比如正确释放VideoCapture和Qt的资源。 总结:用户的请求是读取视频的方法和示例代码,结合Qt和OpenCV。需要分步骤说明,并确保代码正确,包括必要的转换和Qt的界面更新机制。同时,根据引用资料,可以引用提到的应用举例作为支持。</think>以下是如何使用Qt和OpenCV实现视频读取的详细步骤及示例代码: --- ### **1. 环境配置** 确保项目中已正确配置OpenCV库。在Qt的`.pro`文件中添加: ```makefile INCLUDEPATH += /path/to/opencv/include LIBS += -L/path/to/opencv/lib -lopencv_core -lopencv_videoio -lopencv_highgui ``` --- ### **2. 视频读取核心代码** 通过OpenCV的`VideoCapture`类读取视频,结合Qt的`QTimer`实现逐帧显示: ```cpp #include <QApplication> #include <QLabel> #include <QTimer> #include <opencv2/opencv.hpp> int main(int argc, char *argv[]) { QApplication app(argc, argv); // 创建视频捕获对象 cv::VideoCapture cap("input.mp4"); if (!cap.isOpened()) { qDebug() << "Error: Failed to open video!"; return -1; } // 创建Qt显示组件 QLabel label; label.setFixedSize(640, 480); label.show(); // 定时器用于触发帧更新 QTimer timer; QObject::connect(&timer, &QTimer::timeout, [&]() { cv::Mat frame; if (cap.read(frame)) { // 将BGR格式转换为RGB cv::cvtColor(frame, frame, cv::COLOR_BGR2RGB); // 创建QImage并显示 QImage qimg(frame.data, frame.cols, frame.rows, QImage::Format_RGB888); label.setPixmap(QPixmap::fromImage(qimg.scaled(label.size()))); } else { timer.stop(); // 视频结束停止定时器 } }); timer.start(33); // 按30fps间隔触发(约33ms/帧) return app.exec(); } ``` --- ### **3. 关键步骤说明** 1. **视频捕获初始化** `VideoCapture`支持从文件(如`input.mp4`)或摄像头(参数填`0`)读取视频流,需检查`isOpened()`确认是否成功[^1]。 2. **颜色空间转换** OpenCV默认使用BGR格式,Qt的`QImage`需要RGB格式,通过`cv::cvtColor`转换。 3. **帧率控制** 使用`QTimer`以固定间隔(如33ms对应30fps)触发帧读取,确保流畅播放。 4. **资源释放** Qt和OpenCV对象会在作用域结束时自动释放,无需手动删除。 --- ### **4. 扩展功能** - **添加播放控制**:通过按钮实现开始/暂停,动态调整`timer.start()`和`timer.stop()`。 - **实时处理**:在读取帧后添加图像处理逻辑(如边缘检测、滤镜等)。 - **多线程优化**:将视频读取和界面更新分离到不同线程,避免卡顿[^2]。 ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值