国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

【Qt】用QWidget顯示opencv采集的攝像頭圖像

這篇具有很好參考價(jià)值的文章主要介紹了【Qt】用QWidget顯示opencv采集的攝像頭圖像。希望對大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

寫在前面

本案例用QWidget容器重寫paintEvent函數(shù)來顯示OpenCv采集的攝像頭畫面,圖像還可以自適應(yīng)QWidget的大小,還可以檢測相機(jī)斷開失聯(lián)的情況(可能是掉電、線被拔了等待)。在改變窗口大小時(shí)暫停顯示圖像,防止莫名其妙的卡頓奔潰錯(cuò)誤?。@示圖像的方式有很多種,可以用QLabel顯示圖像,雖然簡單但是對于這種視頻畫面不建議用QLabel;還可以用QGraphicsView顯示,下一篇文章更新)

qt+opencv采集攝像頭,Qt,OpenCV,qt

一、新建工程

1、新建一個(gè)Qt工程,在UI中添加一個(gè)Widget容器和兩個(gè)按鈕,并添加合適的布局。把Widget的ObjectName設(shè)置為CameraWidget,兩個(gè)按鈕分別是“打開相機(jī)openCamera”、“關(guān)閉相機(jī)closeCamera
qt+opencv采集攝像頭,Qt,OpenCV,qt
2、新建一個(gè)任務(wù)類,用于Opencv采集攝像頭圖像并發(fā)送信號(hào)。用moveToThread將該任務(wù)類添加到子線程中。
3、在Qt中新建一個(gè)類CameraWidget繼承QWidget,并將UI中的Widget控件提升為該類。

二、采集圖像

1、在Qt項(xiàng)目中配置OpenCv環(huán)境(本文默認(rèn)您已經(jīng)配置完成,否則看我另一篇文章:QT配置opencv346環(huán)境(MinGw編譯器)。
2、新建一個(gè)任務(wù)類,該類主要的任務(wù)是:采集圖像、發(fā)送信號(hào),關(guān)閉相機(jī)退出線程。
3、代碼如下

Camera.h

#ifndef CAMERA_H
#define CAMERA_H

#include <QObject>
#include <QTimer>
#include <QPixmap>

#include <opencv2/opencv.hpp>
using namespace cv;

class Camera : public QObject
{
    Q_OBJECT
public:
    explicit Camera(QObject *parent = nullptr);

    void openCamera();      // 打開相機(jī)
    void closeCamera();     // 關(guān)閉相機(jī)

private:
    VideoCapture *cap;     // 相機(jī)
    QTimer *capTimer;       // 采集圖像定時(shí)器
    bool cameraIsOpened = false;        // 相機(jī)打開標(biāo)志位

signals:
    void cameraShowImage(QPixmap);      // 發(fā)送圖像信號(hào)
    void cameraIsOpen(bool);            // 相機(jī)打開信號(hào)
};

#endif // CAMERA_H

Camera.cpp

#pragma execution_character_set("utf-8")
#include "camera.h"
#include <QDebug>
#include <QThread>

Camera::Camera(QObject *parent) : QObject(parent)
{

}

void Camera::openCamera()
{
    qDebug() << "子線程:" << QThread::currentThreadId();
    // 打開相機(jī)
    int cameraDevId = 0;
    this->cap = new VideoCapture;
    this->cap->open(cameraDevId, cv::CAP_DSHOW);     // 必須帶上 CAP_DSHOW ,否則會(huì)報(bào)錯(cuò) [ WARN:1] terminating async callback,然后再次打開就打不開了
    if(!this->cap->isOpened()){
        this->cap->release();		// 釋放相機(jī)
        qDebug() << "相機(jī)打開失??!";
        return;
    }
    this->cameraIsOpened = true;
    emit this->cameraIsOpen(true);     // 相機(jī)打開

    qDebug() << QString("相機(jī)參數(shù): (%1, %2), %3 FPS").arg(cap->get(3)).arg(cap->get(4)).arg(cap->get(5));

    this->capTimer = new QTimer;
    connect(this->capTimer, &QTimer::timeout, [=]() {
//        qDebug() << "子線程:" << QThread::currentThreadId();
        Mat frame;
        // 采集圖像
        this->cap->read(frame);
        if(frame.empty()){
            qDebug() << "相機(jī)可能斷開";
            this->closeCamera();        // 關(guān)閉相機(jī)
            return ;
        }
        // 將OpenCv的BGR圖像轉(zhuǎn)換成正常的RGB圖像
        cvtColor(frame, frame, cv::COLOR_BGR2RGB);
        // 將OpenCv的圖像轉(zhuǎn)換成Qt的QImage
        QPixmap showImage = QPixmap::fromImage(QImage((const uchar*)(frame.data),
                                                      frame.cols,
                                                      frame.rows,
                                                      frame.step,
                                                      QImage::Format_RGB888));
        // 將QPixmap圖像通過信號(hào)發(fā)送出去
        emit this->cameraShowImage(showImage);
    });
    // 采樣時(shí)間可以根據(jù)相機(jī)的FPS修改
    this->capTimer->start(40);
}

void Camera::closeCamera()
{
    qDebug() << "子線程:" << QThread::currentThreadId();
    if(!this->cameraIsOpened) return;

    if(this->capTimer->isActive()){
        this->capTimer->stop();
        this->capTimer->deleteLater();

        this->cameraIsOpened = false;
        emit this->cameraIsOpen(false);     // 相機(jī)關(guān)閉

        this->cap->release();		// 釋放相機(jī)
        cv::destroyAllWindows();	// 銷毀OpenCv的窗口
    }
}

三、顯示圖像

1、新建一個(gè)類繼承QWidget,并將UI中的Widget控件提升為該類。
qt+opencv采集攝像頭,Qt,OpenCV,qt

2、重寫paintEvent函數(shù),根據(jù)widget的大小對圖像進(jìn)行縮放并繪制;設(shè)計(jì)一個(gè)變量showCameraImage,如果為true時(shí)才顯示繪制圖像。
3、新建一個(gè)定時(shí)器,重寫resizeEvent函數(shù);在窗口大小變化將showCameraImage設(shè)置為false,然后不斷刷定時(shí)器。當(dāng)窗口大小不再變化,定時(shí)器不刷新,時(shí)間到了之后將showCameraImage設(shè)置為true重新繪制圖像。
4、創(chuàng)建幾個(gè)成員函數(shù)用來更新圖像。
5、代碼如下:

CameraWidget.h

#ifndef CAMERAWIDGET_H
#define CAMERAWIDGET_H

#include <QWidget>
#include <QTimer>
#include <QPixmap>

class CameraWidget : public QWidget
{
    Q_OBJECT
public:
    explicit CameraWidget(QWidget *parent = nullptr);

    void showImage(bool b);      // 顯示圖像
    void setImage(QPixmap img);     // 更新圖像

protected:
    void resizeEvent(QResizeEvent *event) override;
    void paintEvent(QPaintEvent *event) override;

private:
    QPixmap cvImage;                // 相機(jī)圖像
    QTimer *noShowCameraImage;      // 不顯示圖像定時(shí)器
    bool showCameraImage = true;    // 顯示圖像
    
    bool camerIsOpened = false;     // 相機(jī)打開

signals:

};

#endif // CAMERAWIDGET_H

CameraWidget.cpp

#pragma execution_character_set("utf-8")
#include "camerawidget.h"
#include <QDebug>
#include <QPainter>

#define CAMERA_IMAGE_WIDTH 640
#define CAMERA_IMAGE_HEIGHT 480

CameraWidget::CameraWidget(QWidget *parent) : QWidget(parent)
{
    this->noShowCameraImage = new QTimer;
    connect(this->noShowCameraImage, &QTimer::timeout, this, [=](){
        this->showCameraImage = true;
        this->noShowCameraImage->stop();
        this->update();
    }); 

    this->update();
}

void CameraWidget::showImage(bool b)
{
    this->camerIsOpened = b;
    update();
}

void CameraWidget::setImage(QPixmap img)
{
    this->cvImage = img;
    update();
}

/**********************************************************
 * @brief label大小變化事件
**********************************************************/
void CameraWidget::resizeEvent(QResizeEvent *event)
{
    this->showCameraImage = false;
    // 定時(shí)器刷新時(shí)間,當(dāng)窗口大小不變后多長時(shí)間恢復(fù)圖像
    // 這涉及到用戶體驗(yàn),設(shè)置適當(dāng)?shù)闹导纯?/span>
    this->noShowCameraImage->setInterval(200);
    this->noShowCameraImage->start();

    QWidget::resizeEvent(event);
}

void CameraWidget::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);

    // 背景顏色
    painter.setPen(QColor(192, 192, 192));
    painter.setBrush(QColor(192, 192, 192));
    painter.drawRect(0, 0, this->width(), this->height());

    // 等比縮放,繪制圖像
    if(this->showCameraImage && this->camerIsOpened){
        // 尋找圖像大小和widget大小的縮放關(guān)系
        QRectF imgRect = this->cvImage.rect();
        QRectF widgetRect = this->rect();
        double factor = qMin(widgetRect.width() / imgRect.width(), widgetRect.height() / imgRect.height());
        // 計(jì)算新的Rect
        int imgWidth = imgRect.width() * factor;
        int imgHeight = imgRect.height() * factor;
        int startX = (this->width() - imgWidth) / 2;
        int startY = (this->height() - imgHeight) / 2;
        // 顯示圖像
        painter.drawPixmap(startX, startY, imgWidth, imgHeight, this->cvImage);
    }

    QWidget::paintEvent(event);
}

四、主窗口

在主線程里面主要是創(chuàng)建子線程已經(jīng)信號(hào)槽綁定。文章來源地址http://www.zghlxwxcb.cn/news/detail-538244.html

#pragma execution_character_set("utf-8")
#include "mainwindow.h"
#include "ui_mainwindow.h"

#include <QDebug>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    qDebug() << "主線程:" << QThread::currentThreadId();

    // 相機(jī)子線程
    this->camera = new Camera;
    this->cameraThread = new QThread;
    this->camera->moveToThread(this->cameraThread);
    connect(this->cameraThread, &QThread::finished, this->cameraThread, &QThread::deleteLater);
    connect(this->cameraThread, &QThread::finished, this->camera, &Camera::deleteLater);
    connect(this->camera, &Camera::cameraShowImage, ui->cameraWidget, &CameraWidget::setImage);		// 更新圖像
    this->cameraThread->start();

    connect(ui->openCamera, &QPushButton::clicked, this->camera, &Camera::openCamera);      // 打開相機(jī)
    connect(ui->closeCamera, &QPushButton::clicked, this->camera, &Camera::closeCamera);    // 關(guān)閉相機(jī)

    connect(this->camera, &Camera::cameraIsOpen, ui->cameraWidget, &CameraWidget::showImage);
}

MainWindow::~MainWindow()
{
    if(this->cameraThread->isRunning()){
        this->cameraThread->quit();
        this->cameraThread->wait();
    }
    delete ui;
}

到了這里,關(guān)于【Qt】用QWidget顯示opencv采集的攝像頭圖像的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • Pyqt5+Opencv實(shí)現(xiàn)攝像頭圖像的實(shí)時(shí)讀取并顯示

    Pyqt5+Opencv實(shí)現(xiàn)攝像頭圖像的實(shí)時(shí)讀取并顯示

    QTimer在界面中不可見,在UI設(shè)計(jì)器中也找不到它,只能通過純代碼實(shí)現(xiàn),主要作用是定時(shí)特定的時(shí)間。 想要掌握QTimer只需掌握setInterval(設(shè)置定時(shí)時(shí)間,單位ms)、start(啟動(dòng)定時(shí)器),和定時(shí)時(shí)間到時(shí)所發(fā)出的信號(hào)timeout()即可。程序設(shè)計(jì)的思路: 1.先設(shè)定定時(shí)周期 2.綁定timeout()信號(hào)

    2024年02月04日
    瀏覽(27)
  • VC++中使用OpenCV讀取圖像、讀取本地視頻、讀取攝像頭并實(shí)時(shí)顯示

    VC++中使用OpenCV讀取圖像、讀取本地視頻、讀取攝像頭并實(shí)時(shí)顯示

    最近閑著跟著油管博主murtazahassan,學(xué)習(xí)了一下LEARN OPENCV C++ in 4 HOURS | Including 3x Projects | Computer Vision,對應(yīng)的Github源代碼地址為:Learn-OpenCV-cpp-in-4-Hours OpenCV是一個(gè)開源的計(jì)算機(jī)視覺庫,其官網(wǎng)地址為:https://opencv.org/,對應(yīng)Github源碼地址為:https://github.com/opencv/opencv,目前來說

    2024年01月17日
    瀏覽(36)
  • 4. QT環(huán)境下使用OPenCV(視頻或攝像頭讀取顯示在QLabel控件上)

    4. QT環(huán)境下使用OPenCV(視頻或攝像頭讀取顯示在QLabel控件上)

    1. 說明 在用opencv處理圖像時(shí),圖像的來源大部分情況下是從視頻中讀取過來的,視頻可以是本地保存的視頻,也可以是本地?cái)z像頭或者網(wǎng)絡(luò)攝像頭實(shí)時(shí)拍攝的視頻。 效果展示: opencv讀取視頻 2. 具體操作 關(guān)于視頻的讀取,實(shí)際上也是從視頻中將每一幀圖像加載后,顯示到Q

    2024年02月04日
    瀏覽(25)
  • 5. QT環(huán)境下使用OPenCV(基于TCP實(shí)現(xiàn)攝像頭圖像數(shù)據(jù)的多線程傳輸)

    5. QT環(huán)境下使用OPenCV(基于TCP實(shí)現(xiàn)攝像頭圖像數(shù)據(jù)的多線程傳輸)

    1. 說明 通常情況下對于圖像數(shù)據(jù)的采集可以放在后端進(jìn)行,采集到的圖像數(shù)據(jù)如果有需要可以通過通信將數(shù)據(jù)傳輸?shù)角岸诉M(jìn)行顯示,這其中需要使用到TCP數(shù)據(jù)傳輸協(xié)議和QT下的多線程開發(fā)技術(shù)。 QT當(dāng)中主線程一般是界面層次的,在主線程中執(zhí)行耗時(shí)較長的數(shù)據(jù)操作,會(huì)引起界

    2024年02月11日
    瀏覽(49)
  • [Python] pyqt6+opencv實(shí)現(xiàn)攝像頭圖像的實(shí)時(shí)讀取并顯示(完整源代碼)

    [Python] pyqt6+opencv實(shí)現(xiàn)攝像頭圖像的實(shí)時(shí)讀取并顯示(完整源代碼)

    本文將會(huì)介紹如何通過opencv來實(shí)時(shí)捕獲攝像頭的圖像,并通過pyqt6進(jìn)行圖像視頻呈現(xiàn)。 1. 通過opencv的VideoCapture類讀取攝像頭的每一幀圖像,通過pyqt6的QLabel來顯示圖像 2. 根據(jù)獲取的圖像的寬和高大小以及QLabel的大小來動(dòng)態(tài)調(diào)整最后輸出的圖像的寬和高 3. 調(diào)整窗體大小,動(dòng)態(tài)調(diào)

    2024年01月24日
    瀏覽(89)
  • OpenCv:采集攝像頭視頻、讀取視頻幀與視頻錄制

    目錄 一、涉及OpenCv函數(shù) 二、什么是幀、幀的大小代表什么 三、攝像頭獲取視頻數(shù)據(jù) 四、錄制視頻并保存 從設(shè)備,可以是攝像頭可以是本地視頻, 獲取視頻的函數(shù) cv.VideoCapture()。 本函數(shù)作用在于創(chuàng)建一個(gè)VideoCapture或者VideoWriter對象,真正的讀取和寫入是通過創(chuàng)建的對象進(jìn)行

    2024年02月16日
    瀏覽(31)
  • qt cpp結(jié)合VideoOutput顯示攝像頭數(shù)據(jù)

    qt cpp結(jié)合VideoOutput顯示攝像頭數(shù)據(jù)

    運(yùn)行效果如下:

    2024年02月11日
    瀏覽(14)
  • FPGA 20個(gè)例程篇:19.OV7725攝像頭實(shí)時(shí)采集送HDMI顯示(一)

    FPGA 20個(gè)例程篇:19.OV7725攝像頭實(shí)時(shí)采集送HDMI顯示(一)

    ? ? ? ?在例程“OV7725攝像頭實(shí)時(shí)采集送HDMI顯示”中,我們將走近FPGA圖像處理的世界,圖像處理、數(shù)字信號(hào)、高速接口也一直被業(yè)界公認(rèn)為FPGA應(yīng)用的三大主流領(lǐng)域,這個(gè)例程主要基于OV7725攝像頭的視頻圖像采集項(xiàng)目,進(jìn)行了詳細(xì)地需求分析,從頂層到底層,從框架到功能,

    2024年02月02日
    瀏覽(46)
  • FPGA 20個(gè)例程篇:19.OV7725攝像頭實(shí)時(shí)采集送HDMI顯示(三)

    FPGA 20個(gè)例程篇:19.OV7725攝像頭實(shí)時(shí)采集送HDMI顯示(三)

    ? ? ? ?在詳細(xì)介紹過OV7725 CMOS Sensor的相關(guān)背景知識(shí)和如何初始化其內(nèi)部寄存器達(dá)到輸出預(yù)期視頻流的目的后,就到了該例程的核心內(nèi)容即把OV7725輸出的視頻流預(yù)先緩存到外部DDR3顆粒,接著按照HDMI的視頻格式把DDR3顆粒內(nèi)存儲(chǔ)的一幀一幀圖像數(shù)據(jù)送顯到屏幕上顯示,如圖1所示

    2024年01月17日
    瀏覽(46)
  • FPGA 20個(gè)例程篇:19.OV7725攝像頭實(shí)時(shí)采集送HDMI顯示(四)

    FPGA 20個(gè)例程篇:19.OV7725攝像頭實(shí)時(shí)采集送HDMI顯示(四)

    ? ? ? ? 在介紹完OV7725初始化配置和視頻采集模塊后,就到了整個(gè)項(xiàng)目的核心部分即DDR3乒乓存儲(chǔ)圖像模塊,為了實(shí)現(xiàn)整個(gè)FPGA項(xiàng)目工程當(dāng)中良好的實(shí)時(shí)性,乒乓操作在廣泛應(yīng)用在FPGA視頻加速處理和數(shù)字信號(hào)處理中。 ? ? ? ?關(guān)于乒乓操作,有很多的FPGA相關(guān)書籍都多多少少做了

    2024年02月02日
    瀏覽(44)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包