Qt 摄像头
Qt 攝像頭
關鍵詞: Qt QCamera QCameraViewfinder 攝像頭
Qt多媒體API提供了許多與攝像頭相關的類,使用這些類可以很容易的從移動設備攝像頭或網絡攝像頭獲取圖像和視頻。
主要內容:
- 相機的工作方式
- QCamera 相關類
- 相機Demo UI實現
- 基本功能實現
文檔參考:
- camera理論基礎和工作原理 https://www.cnblogs.com/fjutacm/p/220631977df995512d136e4dbd411951.html
- 攝像頭原理 https://blog.csdn.net/qq_40732350/article/details/88541417
最新地址: https://taotaodiy-qt.readthedocs.io/en/latest/project/camera.html
攝像頭
光線通過鏡頭Lens進入攝像頭內部,然后經過IRFilter過濾紅外光,最后到達sensor(傳感器),senor按照材質可以分為CMOS和CCD兩種,
可以將光學信號轉換為電信號,再通過內部的ADC電路轉換為數字信號,然后傳輸給DSP(如果有的話,如果沒有則以DVP的方式傳送數據到基帶芯片baseband
此時的數據格式Raw Data),經過加工處理這些數據被轉換成RGB、YUV等格式輸出。
Lens
相機中的透鏡組件(一個或多個透鏡,裝置將光聚焦到傳感器上)。
理論上,鏡頭可以只由一個鏡片組成,但由于光學原因,單個鏡片的成像不可避免的存在色差、球差、彗差、像散等等一些列像差問題,
尤其在邊緣部分,成像很差。多個鏡片的組合可以在一定程度上校正像差。
其次,如果鏡頭變焦需要多個鏡片改變間距來實現。而且變焦后,像差會發生變化,
因而變焦鏡頭普遍需要更多鏡片才能完成變焦和不同焦距的像差校正。
再者,很多鏡頭的對焦也是通過鏡片位置改變實現的。一些鏡頭組件可以自動調整,以便與相機不同距離的物體可以保持對焦。
這通常是通過測量鏡框特定區域的銳度來實現的,并且通過調整透鏡組件直到它達到最大銳度。
在某些情況下,相機將始終使用該幀的中心。其他相機也可以允許指定聚焦區域(用于"觸摸縮放"或"面部縮放"特征)。
傳感器
一旦光到達傳感器,它就被轉換成數字像素。這個過程需要做很多事情,但最終歸結為兩件事:采集的數據經過多長時間的轉換,以及如何獲取更多的光。
轉換時間越長,質量就越好,使用閃光燈有助于讓更多的光線照射到傳感器上,使其能夠更快地轉換像素,在相同的時間內提供更好的質量。
相反,只要相機穩定,允許較長的轉換時間可以讓您在較暗的環境中拍照。
圖像處理
傳感器捕獲圖像后,相機固件對其執行各種圖像處理任務,以補償各種傳感器特性、當前照明和所需的圖像特性。
更快的傳感器像素轉換時間往往會引入數字噪聲,因此可以根據相機傳感器設置進行一定量的圖像處理以消除這種噪聲。
圖像的顏色也可以在這個階段進行調整,以補償不同的光源-閃光燈和陽光給同一物體提供非常不同的效果,
因此可以根據圖片的白平衡來調整圖像(由于光源的不同色溫)。
在此階段還可以執行某些形式的"特殊效果"。可以產生黑白,棕褐色或"負"樣式的圖像。
后期處理
最后,一個完美的聚焦,曝光和處理后的圖像形成,它就可以被我們所用。
例如,相機圖像可以由應用程序代碼進一步處理(例如,檢測條形碼,或將全景圖像縫合在一起),或保存為JPEG等通用格式,或用于創建錄像。
在Qt中,有許多這樣的類可以幫助我們完成這樣的工作。
相關類
Qt中使用相機主要會用到這四個類:QCamera、QCameraViewfinder、QMediaRecorder、QCameraImageCapture。
QCameraViewfinder一起用于取景器顯示,QMediaRecorder用于視頻記錄,QCameraImageCapture用于圖像拍攝。
要想使用這些類需要在pro中添加 QT += multimedia multimediawidgets。
QCameraInfo
QCameraInfo列出可用的攝像機并選擇要使用的攝像機。
const QList<QCameraInfo> availableCameras = QCameraInfo::availableCameras(); for (const QCameraInfo &cameraInfo : availableCameras) {if (cameraInfo == QCameraInfo::defaultCamera())qDebug()<<"defaultCamera ok"; } QScopedPointer<QCamera> m_camera; m_camera.reset(new QCamera(cameraInfo));上面代碼就為我們創建了一個相機實例。
QCameraViewfinder
QCameraViewfinder類提供了一個相機取景器窗口,用法如下:
camera = new QCamera;viewfinder = new QCameraViewfinder(); viewfinder->show();camera->setViewfinder(viewfinder);QMediaRecorder
QMediaRecorder類是一個高級媒體錄制類。它和其他媒體對象(如QRadioTuner或QCamera)配合使用實現錄像功能。其用法如下:
recorder = new QMediaRecorder(camera);QAudioEncoderSettings audioSettings; audioSettings.setCodec("audio/amr"); audioSettings.setQuality(QMultimedia::HighQuality);recorder->setAudioSettings(audioSettings);recorder->setOutputLocation(QUrl::fromLocalFile(fileName)); recorder->record();QCameraImageCapture
QCameraImageCapture類是高級圖像記錄類。它和其他媒體對象(例如QCamera)配合使用實現拍照功能。其用法如下:
camera = new QCamera;viewfinder = new QCameraViewfinder(); viewfinder->show();camera->setViewfinder(viewfinder);imageCapture = new QCameraImageCapture(camera);camera->setCaptureMode(QCamera::CaptureStillImage); camera->start();//on half pressed shutter button camera->searchAndLock();//on shutter button pressed imageCapture->capture();//on shutter button released camera->unlock();UI 實現
UI是在網上隨便找的一個圖片,然后PS把控件摳出來,做了兩個界面布局。
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-L8s9Xc5H-1622038444832)(https://taotaodiy-qt.readthedocs.io/en/latest/_images/camera_ui001.png)]
整個布局,初始化如下:
void MainWindow::setCamera(const QCameraInfo &cameraInfo) {m_camera.reset(new QCamera(cameraInfo));m_mediaRecorder.reset(new QMediaRecorder(m_camera.data()));m_imageCapture.reset(new QCameraImageCapture(m_camera.data()));m_mediaRecorder->setMetaData(QMediaMetaData::Title, QVariant(QLatin1String("Test Title")));QWidget *firstWidget = new QWidget();QWidget *firstrightWidget = new QWidget();QWidget *firstleftWidget = new QWidget();QWidget *secondWidget = new QWidget();ui->stackedWidget->addWidget(firstWidget);ui->stackedWidget->addWidget(secondWidget);QHBoxLayout *firstLayout = new QHBoxLayout;QHBoxLayout *secondLayout = new QHBoxLayout;firstWidget->setLayout(firstLayout);secondWidget->setLayout(secondLayout);viewfinder = new QCameraViewfinder();m_viewfinder = new QtViewFinder();connect(m_viewfinder,SIGNAL(on_changeView()),this,SLOT(setcurView()));connect(m_viewfinder,SIGNAL(on_showConfigWidget()),this,SLOT(showConfigWidget()));connect(m_viewfinder,SIGNAL(on_takeImage()),this,SLOT(takeImage()));firstLayout->addWidget(firstrightWidget);firstLayout->addWidget(viewfinder);firstLayout->addWidget(firstleftWidget);secondLayout->addWidget(m_viewfinder);firstrightWidget->setFixedSize(50,m_height);firstleftWidget->setFixedSize(100,m_height);btn_1=new QPushButton(firstrightWidget);connect(btn_1,SIGNAL(clicked()),this,SLOT(setcurView()));btn_2=new QPushButton(firstrightWidget);btn_3=new QPushButton(firstrightWidget);btn_4=new QPushButton(firstrightWidget);btn_5=new QPushButton(firstrightWidget);connect(btn_5,SIGNAL(clicked()),this,SLOT(showConfigWidget()));btn_1->setStyleSheet(QString("QPushButton {border-image: url(:/image/change.png);}""QPushButton:pressed {border-image: url(:/image/change_press.png);}"));btn_2->setStyleSheet(QString("QPushButton {border-image: url(:/image/setting.png);}""QPushButton:pressed {border-image: url(:/image/setting_press.png);}"));btn_3->setStyleSheet(QString("QPushButton {border-image: url(:/image/picture.png);}""QPushButton:pressed {border-image: url(:/image/picture_press.png);}"));btn_4->setStyleSheet(QString("QPushButton {border-image: url(:/image/tooletc.png);}""QPushButton:pressed {border-image: url(:/image/tooletc_press.png);}"));btn_5->setStyleSheet(QString("QPushButton {border-image: url(:/image/tool.png);}""QPushButton:pressed {border-image: url(:/image/tool_press.png);}"));btn_1->setGeometry(0,0,50,50);btn_2->setGeometry(0,m_height/5,50,50);btn_3->setGeometry(0,m_height/5*2,50,50);btn_4->setGeometry(0,m_height/5*3,50,50);btn_5->setGeometry(0,m_height/5*4,50,50);btn_6=new QPushButton(firstleftWidget);btn_7=new QPushButton(firstleftWidget);btn_8=new QPushButton(firstleftWidget);btn_6->setStyleSheet(QString("QPushButton {border-image: url(:/image/toolbtn_camera.png);}""QPushButton:pressed {border-image: url(:/image/toolbtn_video.png);}"));btn_7->setStyleSheet(QString("QPushButton {border-image: url(:/image/takephoto.png);}""QPushButton:pressed {border-image: url(:/image/takephoto_press.png);}"));btn_8->setStyleSheet(QString("QPushButton {border-image: url(:/image/picturebtn_none.png);}""QPushButton:pressed {border-image: url(:/image/picturebtn_none_press.png);}"));btn_6->setGeometry(0,0,100,200);btn_7->setGeometry(0,m_height/5*2,100,100);btn_7->setEnabled(false);connect(btn_7,SIGNAL(clicked()),this,SLOT(takeImage()));btn_8->setGeometry(0,m_height/5*4,100,100);// config=new CameraConfig(this); // config->hide();this->setFixedSize(m_width+150,m_height);QCameraViewfinderSettings set;set.setResolution(m_width, m_height);m_camera->setViewfinderSettings(set);m_imageCapture.reset(new QCameraImageCapture(m_camera.data()));connect(m_imageCapture.data(), &QCameraImageCapture::readyForCaptureChanged, this, &MainWindow::readyForCapture);connect(m_imageCapture.data(), &QCameraImageCapture::imageCaptured, this, &MainWindow::processCapturedImage);connect(m_imageCapture.data(), &QCameraImageCapture::imageSaved, this, &MainWindow::imageSaved);connect(m_imageCapture.data(), QOverload<int, QCameraImageCapture::Error, const QString &>::of(&QCameraImageCapture::error),this, &MainWindow::displayCaptureError);m_camera->setViewfinder(viewfinder);m_camera->start();}在主界面上我是用了一個stackedWidget,在其中添加了兩個QWidget,用于展示上面兩種效果。
第一種效果,控件和viewfinder是分離的,分別是用setGeometry固定其顯示位置。
第二種效果,則是新建了一個m_viewfinder類,這個類繼承自viewfinder,在這個類中,分別實現了控件布局和功能。
當我們點擊布局切換的時候,重新調用 m_camera->setViewfinder(m_viewfinder) 設置畫布,便可以切換攝像頭畫面預覽。
基本功能
例程源碼下載 camera_2 https://taotaodiy-qt.readthedocs.io/en/latest/common/download.html
拍照功能
void MainWindow::takeImage() {//獲取程序當前運行目錄QString filepath = QCoreApplication::applicationDirPath();qDebug()<<filepath;m_imageCapture->capture(filepath); }照片預覽的小窗口加載照片,實際上就是一個QLabel,完成照相后,將圖片顯示在QLabel上。
void MainWindow::imageSaved(int id, const QString &fileName) {Q_UNUSED(id);qDebug()<<fileName;btn_8->setStyleSheet(QString("background-image: url(%1);").arg(fileName));m_viewfinder->loadSavedImage(fileName); close(); }其他
除了這個,還有一個效果更好一點,不過里面用到了別人的代碼,
這個Demo經過了精簡,例程源碼下載 camera_1
https://taotaodiy-qt.readthedocs.io/en/latest/common/download.html
效果如下:
總結
- 上一篇: 【Pytorch】torch.backe
- 下一篇: 线性与非线性的理解