How to open usb camera using openCV and paint it into a custom widget?



  • Hello, I'm quite new on qt. I'm trying to create a tab on my ui that can give the option to count how many usb cameras are connected to computer and list then using OPENCV. After that, I want to select one of then and start streaming a video into a custom widget, using paintEvent. My main difficulties are: how to start and stop a streaming one the buttons are presses. Below i'm posting my code.

    mainwindow.h

    //includes...
    namespace Ui {
    class MainWindow;
    }
    
    class MainWindow : public QMainWindow
    {
        Q_OBJECT
    
    public:
        explicit MainWindow(QWidget *parent = 0);
        ~MainWindow();
    
    public slots:
        void on_CheckCamerasButton_clicked();
        void on_StartStreamingButton_clicked();
    
    private:
        Ui::MainWindow *ui;
        cameraimage camera;
    };
    #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);
    }
    
    MainWindow::~MainWindow(){
        delete ui;
    }
    
    void MainWindow::on_StartStreamingButton_clicked(){
        camera.startStreaming();
    }
    
    void MainWindow::on_CheckCamerasButton_clicked(){
        camera.stopStreaming();
    }
    

    camerawindow.h

    //includes...
    class cameraimage : public QWidget
    {
        Q_OBJECT
    public:
        explicit cameraimage(QWidget *parent = nullptr);
    
    private:
        QPoint mPoint;
        QTimer *timer;
        cv::VideoCapture captureVideo;
    
    public slots:
        void paintEvent(QPaintEvent * event);
        void startStreaming();
        void stopStreaming();
    };
    #endif // CAMERAIMAGE_H
    

    cameraimage.cpp

    #include "cameraimage.h"
    
    cameraimage::cameraimage(QWidget *parent) : QWidget(parent)
    {
        setMouseTracking(true); 
    
        captureVideo.open(0);
        if (captureVideo.isOpened() == false){
               qDebug() << "Camera can't open";
                return;
          }
          timer = new QTimer(this);
          connect(timer, SIGNAL(timeout()), this, SLOT(update()));
    
    void cameraimage::startStreaming(){
            qDebug() << "Starting Streaming";
            timer->start(1);
    }
    
    void cameraimage::stopStreaming(){
            captureVideo.release();
            qDebug() << "Stop Streaming";
            timer->stop();
    }
    
    void cameraimage::paintEvent(QPaintEvent *){
        cv::Mat tmpImage;
        cv::Mat image;
        captureVideo.read(tmpImage);
    
        if (tmpImage.empty() == true){
            qDebug() << "EMPTY!";
            return;
        }
    
        cv::cvtColor(tmpImage, image, CV_BGR2RGB);
        QImage img((const unsigned char*)(image.data), image.cols, image.rows, QImage::Format_RGB888);
    
        QPixmap pixmap = QPixmap::fromImage(img);
        QPainter painter(this);
    
        float comprimento = 1.0*width()/pixmap.width();
        float altura = 1.0*height()/pixmap.height();
        float ratio = 0.;
    
        if (comprimento<=altura)
            ratio = comprimento;
        else
            ratio = altura;
    
        QSize size = ratio*pixmap.size();
        size.setHeight(size.height()-10);
    
        QPoint p;
        p.setX(0 + (width()-size.width())/2);
        p.setY(5);
    
        painter.drawPixmap(QRect(p, size), pixmap.scaled(size, Qt::KeepAspectRatio));
        painter.setPen(QPen(Qt::red, 20, Qt::SolidLine));
    
    }
    

    The start and top buttons are on mainwindow, when i click, image do not appear.

    Can someone help me?

    Thank you for your attention.

    Regards :D



  • @gabrielschubert
    Hi, friend,welcome.

    Can you show some debug info below code?

    void cameraimage::paintEvent(QPaintEvent *){
        cv::Mat tmpImage;
        cv::Mat image;
        captureVideo.read(tmpImage);
    
        if (tmpImage.empty() == true){
            qDebug() << "EMPTY!";
            return;
        }
    
        cv::cvtColor(tmpImage, image, CV_BGR2RGB);
        QImage img((const unsigned char*)(image.data), image.cols, image.rows, QImage::Format_RGB888);
    
    #if 1
        qDebug() << "img Size: "<< img.size();
    #endif
    
        QPixmap pixmap = QPixmap::fromImage(img);
        QPainter painter(this);
    
        float comprimento = 1.0*width()/pixmap.width();
        float altura = 1.0*height()/pixmap.height();
        float ratio = 0.;
    
        if (comprimento<=altura)
            ratio = comprimento;
        else
            ratio = altura;
    
        QSize size = ratio*pixmap.size();
        size.setHeight(size.height()-10);
    
        QPoint p;
        p.setX(0 + (width()-size.width())/2);
        p.setY(5);
    #if 1
        qDebug() << "p: " << p;
        qDebug() << "size:" << size;
    #endif
        painter.drawPixmap(QRect(p, size), pixmap.scaled(size, Qt::KeepAspectRatio));
        painter.setPen(QPen(Qt::red, 20, Qt::SolidLine));
    


  • Hello @joeQ , thank you for your answer.

    When you say debug info you're saying the app output? If yes, here it is:

    Starting Streaming
    Starting Streaming
    VIDEOIO ERROR: V4L2: Pixel format of incoming image is unsupported by OpenCV
    Unable to stop the stream: Device or resource busy
    Camera can't open
    EMPTY!
    EMPTY!
    

    When I pass the mouse on the cameraimage widget, it keeps printing "EMPTY!", cause of the "mouseTracking(true)".

    If it is not debug info, could you tell me how can I get this?

    Thank you again :)



  • @gabrielschubert

    Camera can't open

    Your camera didn't open, how to get the pixmap ?



  • @joeQ, now camera is opened. I made a mistake and was opening camera twice. But still not starting steaming when I click on start streaming button, that is on mainwindow. Below the code and output.

    #include "cameraimage.h"
    
    cameraimage::cameraimage(QWidget *parent) : QWidget(parent)
    {
        setMouseTracking(true);
    }
    
    void cameraimage::startStreaming(){
        qDebug() << "Starting Streaming";
        captureVideo.open(-1);
        if (captureVideo.isOpened() == false){
            qDebug() << "Camera can't open";
            return;
        }
        timer = new QTimer(this);
        connect(timer, SIGNAL(timeout()), this, SLOT(update()));
    
        timer->start(1);
    }
    
    void cameraimage::stopStreaming(){
        captureVideo.release();
        timer->stop();
    }
    
    void cameraimage::paintEvent(QPaintEvent *){
            cv::Mat tmpImage;
            cv::Mat image;
            captureVideo.read(tmpImage);
    
            if (tmpImage.empty() == true){
                qDebug() << "EMPTY!";
                return;
            }
    
            cv::cvtColor(tmpImage, image, CV_BGR2RGB);
            QImage img((const unsigned char*)(image.data), image.cols, image.rows, QImage::Format_RGB888);
    
        #if 1
            qDebug() << "img Size: "<< img.size();
        #endif
    
            QPixmap pixmap = QPixmap::fromImage(img);
            QPainter painter(this);
    
            float comprimento = 1.0*width()/pixmap.width();
            float altura = 1.0*height()/pixmap.height();
            float ratio = 0.;
    
            if (comprimento<=altura)
                ratio = comprimento;
            else
                ratio = altura;
    
            QSize size = ratio*pixmap.size();
            size.setHeight(size.height()-10);
    
            QPoint p;
            p.setX(0 + (width()-size.width())/2);
            p.setY(5);
        #if 1
            qDebug() << "p: " << p;
            qDebug() << "size:" << size;
        #endif
            painter.drawPixmap(QRect(p, size), pixmap.scaled(size, Qt::KeepAspectRatio));
    }
    

    output after button clicked:

    Starting Streaming...
    EMPTY!
    EMPTY!
    EMPTY!
    ...
    


  • Problem solved, changed line

    camera.startStreaming()
    

    on mainwindow.cpp to

    ui->cameraWidget->startString()
    

    Now it's running.

    Thank you. :)


Log in to reply
 

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