日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Qt与OpenCV编程:在子线程打开摄像头用主线程显示

發(fā)布時間:2025/3/21 编程问答 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Qt与OpenCV编程:在子线程打开摄像头用主线程显示 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

前言

1.在做圖像處理開發(fā)中,比例做目標(biāo)跟蹤識別的時候,用OpenCV一直在處理攝像頭傳入的數(shù)據(jù),有時候會出現(xiàn)界面卡死或者未響應(yīng)的狀態(tài),這是因為事件循環(huán)一直等待處理函數(shù)的返回而導(dǎo)致阻塞事件循環(huán),這樣一來GUI線程所有的繪制和交互都被阻塞在事件隊列中,無法執(zhí)行重繪等事件,整個程序就失去響應(yīng)了。
2.在這種狀態(tài)下,為了保證程序的正常運(yùn)行,最好的方法是把費(fèi)時的數(shù)據(jù)處理函數(shù)放到別一個線程,處理完成之后再把結(jié)果返回給主線程。
在Qt界面中,主線程只要做界面的相關(guān)繪制就可以了。
3.在Qt里面,開多線程有幾種方法,其中一種是繼承QThread類之后重寫run函數(shù),還有一種是把繼承于QObject的類轉(zhuǎn)移到一個Thread里,后面這種是Qt官方在Qt4.8之后推薦的用法。
4.我這里使用QThread打開一個攝像頭,之后用信號把每一幀圖像傳回主線程顯示。

代碼

CameraThread.h

#ifndef CAMERATHREAD_H #define CAMERATHREAD_H #include <QThread> #include <QDebug> #include <vector> #include <QString> #include <opencv2/opencv.hpp>class CameraThread : public QThread {Q_OBJECTpublic:void stop();explicit CameraThread(QObject *parent = 0);cv::VideoCapture cv_cap;int camera_index;cv::Mat cv_src;protected:void run();private:volatile bool stopped;signals:void getImage(const cv::Mat&);public slots:};#endif // CAMERATHREAD_H

CameraThread.cpp

#include "CameraThread.h"CameraThread::CameraThread(QObject *parent) :QThread(parent) {stopped = false; }void CameraThread::run() {qDebug() << "Current thread:" << QThread::currentThreadId();if (!cv_cap.isOpened()){cv_cap.open(0);}while (!stopped){cv_cap >> cv_src;if(!cv_src.data){continue;}emit getImage(cv_src);cv_src.release();}cv_cap.release(); }void CameraThread::stop() {stopped = true; }

調(diào)用代碼:
Camera.cpp

#include "Camera.h"Camera::Camera(QWidget *parent): QMainWindow(parent) {ui.setupUi(this);scene = new QGraphicsScene;//不是QT的類型要注冊信號qRegisterMetaType<cv::Mat>("cv::Mat");connect(ui.actionCamera, SIGNAL(triggered()), this, SLOT(openCamera()));connect(ui.actionClose, SIGNAL(triggered()), this, SLOT(closeCamera())); }void Camera::openCamera() {thread = new CameraThread();connect(thread, SIGNAL(getImage(cv::Mat)), this, SLOT(getImage(cv::Mat)));thread->start(); }void Camera::closeCamera() {if (thread->isRunning()){thread->stop(); thread->destroyed();}ui.DisplayLabel->close(); }void Camera::getImage(cv::Mat image) {qt_image = MatImageToQimage(image);qt_pixmap = QPixmap::fromImage(qt_image);ui.DisplayLabel->setPixmap(qt_pixmap);displayImage(ui.DisplayLabel, qt_pixmap);ui.DisplayLabel->show(); }//顯示圖片到label窗口 void Camera::displayImage(QLabel *label, QPixmap &pixmap) {//對齊方式,水平與垂直label->setAlignment(Qt::AlignLeft);//圖像自適應(yīng)窗口大小QSize imageSize = pixmap.size();QSize labelSize = label->size();double widthRatio = 1.0*imageSize.width() / labelSize.width();double heightRatio = 1.0*imageSize.height() / labelSize.height();if (widthRatio > heightRatio){pixmap = pixmap.scaledToWidth(labelSize.width());}else{pixmap = pixmap.scaledToHeight(labelSize.height());}//這個設(shè)置是整個圖片跟著窗口改變,鋪滿label->setScaledContents(true);//label->resize(QSize(pixmap.width(),pixmap.height()));label->setPixmap(pixmap); } //Mat轉(zhuǎn)成QImage QImage Camera::MatImageToQimage(const cv::Mat &src) {//CV_8UC1 8位無符號的單通道---灰度圖片if (src.type() == CV_8UC1){//使用給定的大小和格式構(gòu)造圖像//QImage(int width, int height, Format format)QImage qImage(src.cols, src.rows, QImage::Format_Indexed8);//擴(kuò)展顏色表的顏色數(shù)目qImage.setColorCount(256);//在給定的索引設(shè)置顏色for (int i = 0; i < 256; i++){//得到一個黑白圖qImage.setColor(i, qRgb(i, i, i));}//復(fù)制輸入圖像,data數(shù)據(jù)段的首地址uchar *pSrc = src.data;//for (int row = 0; row < src.rows; row++){//遍歷像素指針uchar *pDest = qImage.scanLine(row);//從源src所指的內(nèi)存地址的起始位置開始拷貝n個//字節(jié)到目標(biāo)dest所指的內(nèi)存地址的起始位置中memcmp(pDest, pSrc, src.cols);//圖像層像素地址pSrc += src.step;}return qImage;}//為3通道的彩色圖片else if (src.type() == CV_8UC3){//得到圖像的的首地址const uchar *pSrc = (const uchar*)src.data;//以src構(gòu)造圖片QImage qImage(pSrc, src.cols, src.rows, src.step, QImage::Format_RGB888);//在不改變實際圖像數(shù)據(jù)的條件下,交換紅藍(lán)通道return qImage.rgbSwapped();}//四通道圖片,帶Alpha通道的RGB彩色圖像else if (src.type() == CV_8UC4){const uchar *pSrc = (const uchar*)src.data;QImage qImage(pSrc, src.cols, src.rows, src.step, QImage::Format_ARGB32);//返回圖像的子區(qū)域作為一個新圖像return qImage.copy();}else{return QImage();} }

總結(jié)

以上是生活随笔為你收集整理的Qt与OpenCV编程:在子线程打开摄像头用主线程显示的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。