QT+Opencv实现视频流播放

左手的ㄟ右手 2022-12-10 02:26 488阅读 0赞

1.简单流程

首先通过opencv打开视频流,获取到数据帧,然后将数据帧转换为QT可识别的图像,显示到QT界面上。

2.opencv解码线程源码

  1. //DecodeOpencv.h
  2. #pragma once
  3. #include <QThread>
  4. #include <QObject>
  5. #include "opencv2/core/core.hpp"
  6. #include "opencv2/highgui/highgui.hpp"
  7. #include "opencv2/imgproc/imgproc.hpp"
  8. class DecodeOpencv : public QThread
  9. {
  10. Q_OBJECT
  11. Q_SIGNALS:
  12. void sigSendFrame(cv::Mat mat);
  13. public:
  14. DecodeOpencv(QObject *parent = nullptr);
  15. ~DecodeOpencv();
  16. public:
  17. void setUrl(QString url);
  18. void setStoped(bool stop);
  19. protected:
  20. void run();
  21. private:
  22. QString m_rtsp;
  23. bool m_isStop = false;
  24. };
  25. //DecodeOpencv.cpp
  26. #include "DecodeOpencv.h"
  27. #include <QDebug>
  28. DecodeOpencv::DecodeOpencv(QObject *parent)
  29. : QThread(parent)
  30. {
  31. qRegisterMetaType<cv::Mat>("cv::Mat");
  32. }
  33. DecodeOpencv::~DecodeOpencv()
  34. {
  35. m_isStop = true;
  36. }
  37. void DecodeOpencv::setUrl(QString url)
  38. {
  39. m_rtsp = url;
  40. }
  41. void DecodeOpencv::setStoped(bool stop)
  42. {
  43. m_isStop = stop;
  44. }
  45. void DecodeOpencv::run()
  46. {
  47. cv::VideoCapture cap;
  48. if (m_rtsp.isEmpty())
  49. {
  50. qDebug() << "未找到视频流地址";
  51. return;
  52. }
  53. bool suc = false;
  54. if (m_rtsp.contains("localhost:camera"))
  55. {
  56. suc = cap.open(0); //打开本地摄像头
  57. }
  58. else
  59. {
  60. suc = cap.open(m_rtsp.toStdString()); //打开网络流地址
  61. }
  62. if (!suc)
  63. {
  64. qDebug() << "播放失败";
  65. return;
  66. }
  67. while (true)
  68. {
  69. if (!m_isStop)
  70. {
  71. cv::Mat frame;
  72. cap >> frame;
  73. if (frame.empty())
  74. {
  75. qDebug() << "播放帧解析失败";
  76. continue;
  77. }
  78. emit sigSendFrame(frame);
  79. }
  80. else
  81. {
  82. qDebug() << "停止播放";
  83. break;
  84. }
  85. }
  86. }

3.QT界面

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3d6ejk1MzIwMDQ2Mw_size_16_color_FFFFFF_t_70

  1. //ShowMatWidget.h
  2. #pragma once
  3. #include <QWidget>
  4. #include "ui_ShowMatWidget.h"
  5. #include "DecodeOpencv.h"
  6. class ShowMatWidget : public QWidget
  7. {
  8. Q_OBJECT
  9. public:
  10. ShowMatWidget(QWidget *parent = Q_NULLPTR);
  11. ~ShowMatWidget();
  12. private Q_SLOTS:
  13. void slotBtnConnected();
  14. void slotGetFrame(cv::Mat mat);
  15. QImage cvMat2QImage(const cv::Mat& mat);
  16. private:
  17. Ui::ShowMatWidget ui;
  18. DecodeOpencv *m_thread = nullptr;
  19. };
  20. //ShowMatWidget.cpp
  21. #include "ShowMatWidget.h"
  22. #include <QDebug>
  23. ShowMatWidget::ShowMatWidget(QWidget *parent)
  24. : QWidget(parent)
  25. {
  26. ui.setupUi(this);
  27. m_thread = new DecodeOpencv(this);
  28. connect(m_thread, &DecodeOpencv::sigSendFrame, this, &ShowMatWidget::slotGetFrame);
  29. connect(ui.pushButton, &QPushButton::clicked, this, &ShowMatWidget::slotBtnConnected);
  30. }
  31. ShowMatWidget::~ShowMatWidget()
  32. {
  33. }
  34. void ShowMatWidget::slotBtnConnected()
  35. {
  36. m_thread->setUrl(ui.lineEdit->text());
  37. m_thread->start();
  38. }
  39. void ShowMatWidget::slotGetFrame(cv::Mat mat)
  40. {
  41. QImage image = cvMat2QImage(mat);
  42. ui.label->setPixmap(QPixmap::fromImage(image));
  43. }
  44. QImage ShowMatWidget::cvMat2QImage(const cv::Mat& mat)
  45. {
  46. //8位,通道数为1
  47. if (mat.type() == CV_8UC1)
  48. {
  49. QImage image(mat.cols, mat.rows, QImage::Format_Indexed8);
  50. image.setColorCount(256);
  51. for (int i = 0; i < 256; i++)
  52. {
  53. image.setColor(i, qRgb(i, i, i));
  54. }
  55. uchar *pSrc = mat.data;
  56. for (int row = 0; row < mat.rows; row++)
  57. {
  58. uchar *pDest = image.scanLine(row);
  59. memcpy(pDest, pSrc, mat.cols);
  60. pSrc += mat.step;
  61. }
  62. return image;
  63. }
  64. //8位,通道数为3
  65. else if (mat.type() == CV_8UC3)
  66. {
  67. const uchar *pSrc = (const uchar*)mat.data;
  68. QImage image(pSrc, mat.cols, mat.rows, mat.step, QImage::Format_RGB888);
  69. return image.rgbSwapped();
  70. }
  71. //8位,通道数为4
  72. else if (mat.type() == CV_8UC4)
  73. {
  74. qDebug() << "CV_8UC4";
  75. const uchar *pSrc = (const uchar*)mat.data;
  76. QImage image(pSrc, mat.cols, mat.rows, mat.step, QImage::Format_ARGB32);
  77. return image.copy();
  78. }
  79. //32位,通道数为3
  80. else if (mat.type() == CV_32FC3)
  81. {
  82. cv::Mat temp;
  83. mat.convertTo(temp, CV_8UC3);
  84. const uchar *pSrc = (const uchar*)temp.data;
  85. QImage image(pSrc, temp.cols, temp.rows, temp.step, QImage::Format_RGB888);
  86. return image.rgbSwapped();
  87. }
  88. else
  89. {
  90. qDebug() << "ERROR: Mat could not be converted to QImage.";
  91. return QImage();
  92. }
  93. }

发表评论

表情:
评论列表 (有 0 条评论,488人围观)

还没有评论,来说两句吧...

相关阅读

    相关 FFMPEG 播放 RTSP视频

    功能简介: 使用QT+FFMPEG实现了RTSP视频流播放的基础操作,点击按钮后,将拉取指定地址的RTSP流,并在QT界面中通过Label显示 开发环境: 系统环境:U