首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

VS2010 OpenCV + Qt5 顯示視訊:主迴圈阻塞 UI 執行緒導致介面凍結

     編輯:程式設計綜合問答

問題現象

在 Qt5 視窗的 QLabel 上顯示 OpenCV 攝影機畫面。
若註解掉 cvNamedWindow/cvShowImage/cvDestroyWindow,程式進入 while(1) 迴圈後 **Qt 介面完全凍結,按鈕無反應**,必須強制關閉。

根本原因

  1. while(1) 迴圈跑在 **Qt 主執行緒(GUI 執行緒)**,持續佔用 CPU,不讓 Qt 事件迴圈 (QApplication::exec()) 處理重繪、滑鼠、鍵盤事件。
  2. cvWaitKey(330) 雖有延遲,但屬於 OpenCV 高層 API,內部仍在同一執行緒忙等,不會釋放 Qt 事件迴圈控制權。
  3. 保留 cvNamedWindow 時,OpenCV 內部可能啟動獨立視窗執行緒處理 cvShowImage,間接讓 Qt 主執行緒獲得喘息機會(非標準行為,不可依賴)。

正確架構:視訊擷取移至工作執行緒

class VideoThread : public QThread {
    Q_OBJECT
public:
    void run() override {
        cv::VideoCapture cap(0);
        cv::Mat frame;
        while (!isInterruptionRequested()) {
            if (cap.read(frame)) {
                cv::cvtColor(frame, frame, cv::COLOR_BGR2RGB);
                QImage img(frame.data, frame.cols, frame.rows, frame.step, QImage::Format_RGB888);
                emit frameReady(img.copy()); // 傳遞深拷貝,避免跨執行緒資料競爭
            }
            msleep(30); // 約 30 FPS
        }
    }
signals:
    void frameReady(const QImage &img);
};

// 主視窗
MainWindow::MainWindow() {
    auto *thread = new VideoThread(this);
    connect(thread, &VideoThread::frameReady, this, [this](const QImage &img){
        ui.label_JK->setPixmap(QPixmap::fromImage(img));
    });
    thread->start();
}

關鍵細節

  • QThread 子類別重寫 run():執行緒進入點,迴圈中檢查 isInterruptionRequested() 優雅退出。
  • 訊號/槽跨執行緒傳遞 QImage:Qt 自動排隊到主執行緒執行槽函數,安全更新 UI。
  • img.copy() 深拷貝:cv::Mat 資料在迴圈中會被覆寫,必須複製一份給 QImage,否則顯示花屏或崩潰。
  • 關閉視窗時:thread->requestInterruption(); thread->wait(); 確保執行緒乾淨結束。
  • OpenCV 4.x 建議用 cv::VideoCapture + cv::Mat,棄用 IplImage/CvCapture 舊 C 介面。

進階優化

  • 使用 QVideoSink / QMediaDevices (Qt 6 Multimedia) 完全替代 OpenCV 擷取,效能更好、原生支援硬體加速。
  • 若需 OpenCV 處理(如輪廓偵測),在工作執行緒完成處理後只傳送結果 QImage 給 UI。
  • 雙緩衝/三緩衝機制避免幀撕裂。

結論:**任何耗時迴圈(視訊、串口、網路)絕不能寫在 Qt 主執行緒**,必須移至 QThread/QRunnable + 訊號槽,才能保持介面流暢回應。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved