VideoCapture is really slow (OpenCv)



  • I have opened a camera using OpenCv function, and designed everything via the timer, so when the timer runs out the vide image gets update, the timer is set to 1(ms), so the stream has to be really fast, but the result is that that the stream is really slow it's like 15fps. What can be the problem? But when I use imshow of OpenCV the stream speed is ok.
    OS: Windows 7
    Compiler: MinGW 5.5.1
    Code:

    Camera.h

    #ifndef _CAMERA_H
     #define _CAMERA_H
     #include <QThread>
     #include <QCamera>
     #include <QCameraInfo>
     #include <QList>
     #include <QDebug>
     #include <QVector>
     #include <QCameraViewfinder>
     #include "opencv2/opencv.hpp"
     #include  <opencv2/highgui/highgui.hpp>
     #include <QTimer>
     #include <QLabel>
     #include <QImage>
     using namespace cv;
     class _Camera: public QThread
     {  
     Q_OBJECT
     private:
      void StartTimer();
      QTimer timer_;
      VideoCapture cap_;
      Mat frame_;
      QLabel screen;
    private slots:
      void UpdateFrame();
    signals:
      void sendImage(QImage image);
    public:
        void close();
        void StartCamera(int camera_num);
        virtual ~_Camera(){}
         _Camera();
    };
    
    #endif // _CAMERA_H
    

    --------------------------------Camera.cpp

    #include "_camera.h"
    _Camera::_Camera()
    {
    QObject::connect(&timer_,SIGNAL(timeout()),this,SLOT(UpdateFrame()));
    }
    void _Camera::StartTimer(){
       timer_.start(1);
       timer_.setSingleShot(false);
    }
    void _Camera::UpdateFrame(){
        cap_.read(frame_);
        if(frame_.empty()){
            return;
        }
        cvtColor(frame_,frame_, COLOR_BGR2RGB);
        QImage qimgOriginal((uchar*)frame_.data,frame_.cols,frame_.rows, frame_.step,QImage::Format_RGB888);
        emit sendImage(qimgOriginal);
    }
    void _Camera::StartCamera(int camera_num){
        cap_.open(camera_num);
        if(!cap_.isOpened()){ qDebug()<<"Could not open"; return;}
        StartTimer();
    }
    void _Camera::close(){
        cap_.release();
    }
    

    ----------------------------------- mainwindow.h

    #ifndef MAINWINDOW_H
    #define MAINWINDOW_H
    
    #include <QMainWindow>
    #include <_camera.h>
    #include <QDebug>
    namespace Ui {
    class MainWindow;
    }
    
    class MainWindow : public QMainWindow
    {
        Q_OBJECT
    
    public:
        explicit MainWindow(QWidget *parent = 0);
        ~MainWindow();
    private slots:
          void on_SettingsButton_clicked();
          void ReceiveImage(QImage img);
          void closeEvent(QCloseEvent *event);
    
    private:
        _Camera obj;
        Ui::MainWindow *ui;
    };
    
    #endif // MAINWINDOW_H
    

    -----------------------------------------MainWindow.cpp

    #include "mainwindow.h"
    #include "ui_mainwindow.h"
    
    MainWindow::MainWindow(QWidget *parent) :
        QMainWindow(parent),
        ui(new Ui::MainWindow)
    {
        ui->setupUi(this);
        ui->FirstDisplayLabel->clear();
        connect(&obj,SIGNAL(sendImage(QImage)),this,SLOT(ReceiveImage(QImage)));
    }
    
    
    MainWindow::~MainWindow()
    {
        delete ui;
    }
    void MainWindow::ReceiveImage(QImage img){
        img =  img.scaled(ui->FirstDisplayLabel->width(),ui->FirstDisplayLabel->height());
        ui->FirstDisplayLabel->setPixmap(QPixmap::fromImage(img));
    }
    void MainWindow::closeEvent(QCloseEvent *event){
        obj.close();
    }
    void MainWindow::on_SettingsButton_clicked()
    {
    obj.StartCamera(0);
    }
    

  • Lifetime Qt Champion

    Hi,

    Do you realise that you are trying to refresh a 1kHz ? Current quality hardware can get up to 60fps.



  • @SGaist Don't really understand what do you mean. That the fps is to high?
    UPD:
    You mean that the timer is set to 1ms? I tried to set it to 60fps(1000/60) but the stream is to slow



  • I guess the culprit is ReceiveImage

    img =  img.scaled(ui->FirstDisplayLabel->width(),ui->FirstDisplayLabel->height());
    ui->FirstDisplayLabel->setPixmap(QPixmap::fromImage(img));
    

    1 : Use resize function of opencv instead of QImage, I remember it is much faster than scaled function of QImage, you can pass the Mat object to the slot , call the resize function of opencv. If you do not want to register metatype, you can pass by pointer. Although I think register by metatype is better, because maintainers do not need to wonder who should handle the resource of that pointer.

    2 : fromImage is an expensive operation, try this function, may save one copy

    3 : Store a Mat object in MainWindow, this way the resize function may avoid reallocation when you try to resize the image.

    QPixmap::fromImage(std::move(img))
    

    To get more insight, please run profiler to find out the bottleneck


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.