控件選型對比
| 方案 | 優點 | 缺點 | 適用場景 |
| QLabel + QPixmap |
最簡單、無額外依賴、支持縮放 setScaledContents(true) |
高幀率 (>30fps) 重繪開銷大、無硬件加速、難以覆蓋繪圖 (ROI、十字線) |
低幀率監控、快速原型 |
| QGraphicsView + QGraphicsScene + QGraphicsPixmapItem |
支持縮放/平移/旋轉/覆蓋項目 (矩形、文字)、視圖座標映射方便 |
場景圖元過多時性能下降、需手動管理 Item 更新 |
需交互標註、測量、多層覆蓋 |
| OpenCV + cv::imshow |
極高性能、原生硬件加速、圖像處理算法豐富 |
與 Qt 事件循環融合差、界面風格不一、難以嵌入 Qt 佈局 |
純算法驗證、無 GUI 需求 |
| OpenCV + QOpenGLWidget / QQuickView (Qt Quick) |
GPU 加速渲染、支持著色器特效、Qt Quick 流動界面 |
開發難度高、需 OpenGL/Shader 基礎 |
高性能實時視頻、AR/濾鏡、多視頻流融合 |
| 推薦:OpenCV 采集處理 + QLabel/QGraphicsView 顯示 |
算法用 OpenCV,GUI 用 Qt,邊界清晰 |
需格式轉換 (cv::Mat → QImage) |
**大多數工業/科研項目首選** |
核心代碼:OpenCV + QLabel 實時顯示 (線程分離)
// CameraThread.h
class CameraThread : public QThread {
Q_OBJECT
public:
explicit CameraThread(int camIndex = 0) : index(camIndex), running(false) {}
void startCapture() { running = true; start(); }
void stopCapture() { running = false; wait(); }
signals:
void frameReady(const QImage& img);
protected:
void run() override {
cv::VideoCapture cap(index);
if (!cap.isOpened()) return;
cv::Mat frame;
while (running) {
cap >> frame;
if (frame.empty()) continue;
// BGR -> RGB
cv::cvtColor(frame, frame, cv::COLOR_BGR2RGB);
// 深拷貝構建 QImage (避免數據指針失效)
QImage img(frame.data, frame.cols, frame.rows, frame.step, QImage::Format_RGB888);
emit frameReady(img.copy()); // copy() 確保數據所有權轉移
msleep(10); // 限制幀率 ~100fps
}
}
private:
int index;
bool running;
};
// MainWindow.cpp
void MainWindow::onStartClicked() {
cameraThread = new CameraThread(0);
connect(cameraThread, &CameraThread::frameReady, this, [this](const QImage& img) {
ui.label->setPixmap(QPixmap::fromImage(img.scaled(ui.label->size(),
Qt::KeepAspectRatio, Qt::SmoothTransformation)));
});
cameraThread->startCapture();
}
QGraphicsView 去除滾動條 + 自適應縮放
ui.graphicsView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
ui.graphicsView->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
ui.graphicsView->setRenderHint(QPainter::SmoothPixmapTransform);
void MainWindow::onFrameReady(const QImage& img) {
scene->clear(); // 或更新現有 item
item = scene->addPixmap(QPixmap::fromImage(img));
ui.graphicsView->fitInView(scene->sceneRect(), Qt::KeepAspectRatio);
// 或手動縮放:item->setScale(factor);
}
性能優化清單
- 格式轉換零拷貝:OpenCV 4.0+ 支持
cv::Mat 直接構建 QImage 共享數據 (需保證 Mat 生命周期 > QImage)。
- 降低分辨率:采集 1920x1080,顯示縮放至 640x480,減少內存帶寬。
- 幀率控制:
QTimer::singleShot(33, ...) 實現 ~30fps,避免佔滿 CPU。
- 異步處理:耗時算法 (檢測/識別) 放在 Worker Thread,僅將結果 (矩形框/特徵點) 發送給 GUI 線程繪製。
- 硬件加速:
cv::VideoCapture(cv::CAP_DSHOW) (Windows DirectShow) 或 CAP_V4L2 (Linux) + cap.set(cv::CAP_PROP_FOURCC, cv::VideoWriter::fourcc('M','J','P','G')) 啟用 MJPG 硬解。
參考資源
- Qt + OpenCV 經典教程:CSDN 博客
- Qt 官方範例:
examples/multimediawidgets/videographicsitem