【QT中实现摄像头播放、以及视频录制】

news2024/11/16 13:54:32

学习分享

  • 1、效果图
  • 2、camerathread.h
  • 3、camerathread.cpp
  • 4、mainwindow.h
  • 5、mainwindow.cpp
  • 6、main.cpp

1、效果图

在这里插入图片描述

2、camerathread.h

#ifndef CAMERATHREAD_H
#define CAMERATHREAD_H

#include <QObject>
#include <QThread>
#include <QDebug>
#include <QImage>
#include <unistd.h>
#include <iostream>
#include <QDateTime>
#include <opencv2/opencv.hpp>
using namespace  std;
using namespace  cv;
class CameraThread :public QThread
{
    Q_OBJECT
public:
    static CameraThread *camerathread;
    static CameraThread *getInstance();
    void run();
    bool getIsRun() const;
    void setIsRun(bool value);
    int getFrame_width() const;
    int getFrame_height() const;
    void detecCarDaw(Mat &frame,CascadeClassifier &cascade,double scale);
    bool getIsStop() const;
    void setIsStop(bool value);
    bool getIsRecord() const;
    void setIsRecord(bool value);
    VideoWriter getWriter() const;
    bool getIsPersistent() const;
    void setIsPersistent(bool value);
    bool getIsRun_s() const;
    void setIsRun_s(bool value);
signals:
    void sendQImage(Mat frame);
private:
    CameraThread();
    CascadeClassifier cascade;//级联分类器的过滤器
    VideoCapture cap;
    Mat frame;
    VideoWriter writer;//OpenCV视频录制类
    bool isRun;//控制线程是否运行
    int frame_width;
    int frame_height;
    int recordNum; //录制帧率,设定为300帧
    bool isRun_s; //控制线程是否运行
    bool isStop; //控制线程结束
    bool isRecord; //控制线程是否开始录制
    bool isPersistent;
};

#endif // CAMERATHREAD_H

3、camerathread.cpp

#include "camerathread.h"

CameraThread * CameraThread::camerathread =nullptr;
CameraThread * CameraThread::getInstance()
{
    if(CameraThread::camerathread ==nullptr)
    {
        CameraThread::camerathread =new CameraThread ();
    }
    return CameraThread::camerathread;
}
CameraThread::CameraThread()
{

    this->isRun =true;
    cap.open(0);
    // 获取摄像头的宽度和高度
    this->frame_width = static_cast<int>(cap.get(CAP_PROP_FRAME_WIDTH));
    this->frame_height = static_cast<int>(cap.get(CAP_PROP_FRAME_HEIGHT));

    // 定义视频编码格式、帧率和画面尺寸
     int fourcc = VideoWriter::fourcc('X', 'V', 'I', 'D');
     Size frameSize(frame_width, frame_height);
     this->isRun_s=false;
     this->isStop=false;
     this->isRecord=false;
     this->isPersistent=false;
     this->recordNum=0;

}


bool CameraThread::getIsStop() const
{
    return isStop;
}

void CameraThread::setIsStop(bool value)
{
    isStop = value;
}



bool CameraThread::getIsRecord() const
{
    return isRecord;
}

void CameraThread::setIsRecord(bool value)
{
    isRecord = value;
    if(this->isRecord == false && writer.isOpened())
    {
        qDebug()<<"手动关闭"<<endl;
        writer.release();
        this->recordNum =0;
    }
}

VideoWriter CameraThread::getWriter() const
{
    return writer;
}

bool CameraThread::getIsPersistent() const
{
    return isPersistent;
}

void CameraThread::setIsPersistent(bool value)
{
    isPersistent = value;
}

bool CameraThread::getIsRun_s() const
{
    return isRun_s;
}

void CameraThread::setIsRun_s(bool value)
{
    isRun_s = value;
}
void CameraThread::detecCarDaw(Mat &frame, CascadeClassifier &cascade, double scale)
{
    //灰度处理
    Mat gray;
    cvtColor(frame,gray,CV_BGR2GRAY);
    //将灰度图缩小一半
    //cvRound()用于四舍五入       CV_8UC1:单通道
    Mat smalling(cvRound(frame.rows/scale),cvRound(frame.cols/scale),CV_8UC1);
    //resize()改变大小      INTER_LINEAR 等比例缩小
    resize(gray,smalling,smalling.size(),0,0,INTER_LINEAR);

    //直方图均衡化:利用直方图函数将图像黑白分明  (结果跟二值化类似)
    equalizeHist(smalling,smalling);
    //进行模型检测
    vector<Rect>cars;
    cascade.detectMultiScale(smalling,cars,1.1,2,0|CV_HAAR_SCALE_IMAGE,Size(30,30));

    //绘制边框
    vector<Rect>::const_iterator iter;//系统默认迭代器
    for(iter =cars.begin();iter!=cars.end();iter++)
    {
        rectangle(
                  frame,//原图
                  cvPoint(cvRound(iter->x*scale),cvRound(iter->y*scale)),//左上角坐标
                  cvPoint(cvRound((iter->x+iter->width)*scale),cvRound((iter->y+iter->height)*scale)),//右下角坐标
                  Scalar(0,255,0),//绿色
                  2,//像素大小
                  8//亮度
                  );
    }
}


int CameraThread::getFrame_height() const
{
    return frame_height;
}

int CameraThread::getFrame_width() const
{
    return frame_width;
}

bool CameraThread::getIsRun() const
{
    return isRun;
}

void CameraThread::setIsRun(bool value)
{
    isRun = value;
}
void CameraThread::run()
{
    cascade.load("D:/OpenCV/cars.xml");//识别级联分类器  车辆
    while(this->isRun ==true)
    {
        if(cap.read(frame))
        {
            cvtColor(frame,frame,CV_BGR2RGB);
            detecCarDaw(frame,cascade,2);
            emit sendQImage(frame);

            if(this->isStop ==false)//控制线程结束
            {
                if(this->isRun_s == true)//控制线程是否运行
                {
                    if(cap.read(frame))
                    {
                        if(this->isRecord==true)
                        {
                            if(this->recordNum ==0)
                            {
                                QDateTime current_date_time =QDateTime::currentDateTime();
                                QString current_date =current_date_time.toString("yyyy-MM-dd-hh-mm-ss");
                                //QString filename ="../data/"+current_date+".avi";
                                QString filename ="D:/Qtsoft/videoDemo/data/"+current_date+".avi";
                                qDebug()<<"filename="<<filename;
                                writer.open(filename.toStdString().c_str(),CV_FOURCC('M','J','P','G'),30.0,Size(frame.cols,frame.rows),true);
                            }
                            if(!writer.isOpened())
                            {
                                qDebug()<<"录制路径失败!!!"<<endl;
                            }
                            else
                            {
                                if(this->recordNum<300)
                                {
                                        //当前帧不等于总帧数,录制300帧还没有结束
                                        //qDebug()<<"录制中..."<<endl;
                                        writer<<frame;
                                        this->recordNum++;
                                }
                                else
                                {
                                    qDebug()<<"已经到300帧结束录制";
                                    writer.release();
                                    this->recordNum =0;
                                    if(this->isPersistent==true)
                                    {
                                         this->isRecord =true;
                                    }else if(this->isPersistent ==false)
                                    {
                                        this->isRecord =false;
                                    }

                                }
                            }
                        }
                        cvtColor(frame,frame,CV_BGR2RGB);
                    }
                    msleep(10);
                }
            }
        }
    }

}

4、mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include "camerathread.h"
namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = nullptr);
    ~MainWindow();
    void paintEvent(QPaintEvent * Eevent);
private:
    Ui::MainWindow *ui;
    CameraThread *ct;
//    VideoThread *vt;
    QImage image;
    Mat frame;
private slots:
    void isChecked(Mat frame);
    void on_pushButton_clicked();
    void on_checkBox_clicked(bool checked);
};

#endif // MAINWINDOW_H

5、mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    this->ct =CameraThread::getInstance();
    connect(this->ct,SIGNAL(sendQImage(Mat)),this,SLOT(isChecked(Mat)),Qt::BlockingQueuedConnection);
    this->ct->start();
//    this->vt =new VideoThread(0);
//    this->vt->start();
    waitKey(40);
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::paintEvent(QPaintEvent *Eevent)
{
    ui->label->setPixmap(QPixmap::fromImage(this->image));
    QImage q_image = QImage(frame.data,frame.cols,frame.rows,QImage::Format_RGB888);
    ui->label->setPixmap(QPixmap::fromImage(q_image));
    ui->label->setScaledContents(true);
}

void MainWindow::isChecked(Mat frame)
{
    this->image =QImage(frame.data,frame.cols,frame.rows,QImage::Format_RGB888);
    this->image = this->image.scaled(ui->label->width(),ui->label->height());//以UI中的界面大小进行等比例缩放
    this->frame = frame.clone();
    this->update();
}

void MainWindow::on_pushButton_clicked()
{

    if(this->ct->getWriter().isOpened())
    {
               qDebug()<<"已经有录制项目:请先结束录制,再操作";
               return;
     }


    this->ct->setIsRun_s(true);
    this->ct->setIsRecord(true);

}

void MainWindow::on_checkBox_clicked(bool checked)
{
    if(checked==true)
    {
         //qDebug()<<"true";
        this->ct->setIsRecord(true);
        this->ct->setIsPersistent(true);
    }else if(checked==false)
    {
         //qDebug()<<"false";
         this->ct->setIsPersistent(false);
    }
}

6、main.cpp

#include "mainwindow.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();


    return a.exec();
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1911930.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

OpenFWI代码

重点关注文章第4部分 一、代码模块概览 这一部分了解代码主要实现的功能有哪些。 二、运行 这一部分关注如何跑通。 三、数据集 12个数据集&#xff08;11个2D1个3D&#xff09; 对计算机而言&#xff0c;上述输入、输出维度大小是按次数定义的。 以“Vel&#xff0c;F…

Celery,一个实时处理的 Python 分布式系统

大家好&#xff01;我是爱摸鱼的小鸿&#xff0c;关注我&#xff0c;收看每期的编程干货。 一个简单的库&#xff0c;也许能够开启我们的智慧之门&#xff0c; 一个普通的方法&#xff0c;也许能在危急时刻挽救我们于水深火热&#xff0c; 一个新颖的思维方式&#xff0c;也许能…

Spring-AOP(二)

作者&#xff1a;月下山川 公众号&#xff1a;月下山川 1、什么是AOP AOP&#xff08;Aspect Oriented Programming&#xff09;是一种设计思想&#xff0c;是软件设计领域中的面向切面编程&#xff0c;它是面向对象编程的一种补充和完善&#xff0c;它以通过预编译方式和运行期…

MySQL:TABLE_SCHEMA及其应用

MySQL TABLE_SCHEMA及其应用 - 文章信息 - Author: 李俊才 (jcLee95) Visit me at CSDN: https://jclee95.blog.csdn.netMy WebSite&#xff1a;http://thispage.tech/Email: 291148484163.com. Shenzhen ChinaAddress of this article:https://blog.csdn.net/qq_28550263/ar…

持久化存储与设备环境查询的最佳实践

ArkUI框架中的PersistentStorage和Environment 在ArkUI框架中&#xff0c;持久化存储和设备环境查询是应用开发中不可或缺的两个重要功能。在本文中&#xff0c;我们将深入了解框架提供的PersistentStorage和Environment&#xff0c;它们的用途、限制条件以及在应用开发中的使…

SDIO CMD 数据部分 CRC 计算规则

使用的在线 crc 计算工具网址&#xff1a;http://www.ip33.com/crc.html CMD CRC7 计算 如下图为使用逻辑分析仪获取的SDIO读写SD卡时&#xff0c;CMD16指令发送的格式&#xff0c;通过逻辑分析仪总线分析&#xff0c;可以看到&#xff0c;该部分的CRC7校验值得0x05,大多数情况…

二战架构师,拿下

前言 已经许久更新文章了&#xff0c;并不是因为我懒了&#xff0c;而是在备考系统架构师考试。个人感觉还是比较幸运的&#xff0c;低分飘过。现阶段任务也算完成了&#xff0c;记录一下感受。 什么是软考 软考&#xff0c;全称“计算机技术与软件专业技术资格&#xff08…

Agent如何帮助大模型“增强记忆”?

Agent如何帮助大模型“增强记忆”&#xff1f; 原创 格林 神州问学 2024年07月08日 17:50 日本 记忆反馈 >规划&#xff1f; 来源|神州问学 引言 去年6月份&#xff0c;Lilian发布了关于LLM驱动的Agent的结构和组件&#xff0c;其中包括规划、行动、工具还有记忆&#xff…

去除Win32 Tab Control控件每个选项卡上的深色对话框背景

一般情况下&#xff0c;我们是用不带边框的对话框来充当Tab Control的每个选项卡的内容的。 例如&#xff0c;主对话框IDD_TABBOX上有一个Tab Control&#xff0c;上面有两个选项卡&#xff0c;第一个选项卡用的是IDD_DIALOG1充当内容&#xff0c;第二个用的则是IDD_DIALOG2。I…

C++相关概念和易错语法(17)(适配器模式、仿函数)

1.stack和queue stack和queue的相关接口如下&#xff1a; stack queue 我们发现不管是stack还是queue&#xff0c;它们都有push和pop&#xff0c;不区分push_back和push_front&#xff0c;这是由它们的入栈特定顺序特性决定的&#xff0c;并且它们都没有迭代器&#xff0c;st…

【系统架构设计】计算机组成与体系结构(一)

计算机组成与体系结构 计算机系统组成计算机硬件组成控制器运算器主存储器辅助存储器输入设备输出设备 计算机系统结构的分类存储程序的概念Flynn分类 复杂指令集系统与精简指令集系统总线 存储器系统流水线 兜兜转转&#xff0c;最后还是回到了4大件&#xff0c;补基础&#x…

【力扣】数组中的第K个最大元素

一、题目描述 给定整数数组 nums 和整数 k&#xff0c;请返回数组中第 k 个最大的元素。 请注意&#xff0c;你需要找的是数组排序后的第 k 个最大的元素&#xff0c;而不是第 k 个不同的元素。 你必须设计并实现时间复杂度为 O(n) 的算法解决此问题。 示例 1: 输入: [3,2,1,5,…

图片像素坐标转实际坐标的一种转换方案

原图 红色的点是我们标注的像素点&#xff0c;这些红色的点我们知道它的像素坐标&#xff0c;以及以右下角相机位置为原点的x y 实际坐标数值 通过转换&#xff0c;可以得到整个图片内部其余像素点的实际坐标&#xff0c; 这些红色的点是通过转换关系生成的&#xff0c;每隔一米…

python破解密码·筛查和选择

破解密码时可能遇到的几种情况 ① 已知密码字符&#xff0c;破排序 ② 已知密码位数&#xff0c;破字符 ③ 已知密码类型&#xff0c;破字位 ④ 已知部分密码&#xff0c;破未知 ⑤ 啥都不知道&#xff0c;盲破&#xff0c;玩完 ⑥ 已知位数、字符、类型、部分密码中的几个&am…

2024全网最全面及最新且最为详细的网络安全技巧五 之 SSRF 漏洞EXP技巧,典例分析以及 如何修复 (下册)———— 作者:LJS

五.SSRF 漏洞EXP技巧&#xff0c;典例分析以及 如何修复 (下册) 目录 五.SSRF 漏洞EXP技巧&#xff0c;典例分析以及 如何修复 (下册) 5.4gopher 协议初探 0x01 Gopher协议 0x02 协议访问学习 复现环境 centos7 kali 2018 发送http get请求 发送http post请求 5.5 SSRF…

☺初识c++(语法篇)☺

目录 一命名空间&#xff08;namespace&#xff09;&#xff1a; 二cout与cin简述&#xff1a; 三缺省参数&#xff1a; 四函数重载&#xff1a; 五引用&#xff1a; 六内联函数: 七c中的nullptr简述&#xff1a; 一命名空间&#xff08;namespace&#xff09;&#xff1…

Chromium编译指南2024 Linux篇-同步Chromium第三方库(四)

1.引言 在成功拉取Chromium源码并创建新分支后&#xff0c;我们需要进一步配置开发环境。这包括拉取必要的第三方库以及设置hooks&#xff0c;以确保我们能够顺利进行编译和开发工作。以下步骤将详细介绍如何进行这些配置。 2.拉取第三方库以及hooks Chromium 使用了大量的第…

2024第六届上海国际新材料展览会-12月精彩呈现

2024第六届上海国际新材料展览会 The 6th shanghai International New Materials Exhibition in 2024 时 间&#xff1a;2024年12月18-20日 地 点&#xff1a;上海新国际博览中心 CIME 2024专业、权威&#xff0c;涵盖整个新材料行业的国际盛会。 期待与您在CIME 2024现场相…

24-7-9-读书笔记(九)-《爱与生的苦恼》[德]叔本华 [译]金玲

文章目录 《爱与生的苦恼》阅读笔记记录总结 《爱与生的苦恼》 《爱与生的苦恼》叔本华大佬的名书&#xff0c;里面有其“臭名昭著”的《论女人》&#xff0c;抛开这篇其他的还是挺不错的&#xff0c;哲学我也是一知半解&#xff0c;这里看得也凭喜好&#xff0c;这里记录一些自…

大模型/NLP/算法面试题总结2——transformer流程//多头//clip//对比学习//对比学习损失函数

用语言介绍一下Transformer的整体流程 1. 输入嵌入&#xff08;Input Embedding&#xff09; 输入序列&#xff08;如句子中的单词&#xff09;首先通过嵌入层转化为高维度的向量表示。嵌入层的输出是一个矩阵&#xff0c;每一行对应一个输入单词的嵌入向量。 2. 位置编码&…