Aplicação com câmera usando Qt5

câmera

Introdução

QCamera é uma classe do Qt5 que prove para o desenvolvedor toda estrutura necessária para listar dispositivos webcams e cada câmera conectada ao PC, selecionar o dispositivo desejado e executar tarefas como capturar imagem, reproduzir ou até mesmo gravar.

Configuração do sistema

Para sucesso na execução deste artigo, utilizarei a distribuição Linux Mint 17 Qiana 64 bits, mas não há problemas em realizar o procedimento em um Ubuntu ou outra distribuição suportada pelo Qt5. A seguir são listados os seus pré-requisitos:

  • Qt5.4 ou Qt5.5 instalado com o Qt Creator;
  • QCamera instalado;
  • Distribuição Linux suportada pelo Qt5.

O básico do QCamera

Para utilizar o QCamera, que não é um Widget para arrastar e soltar na aplicação, devemos incluir algumas dependências em nosso projeto. Então, vamos criar nosso projeto.

Clique em File > New File or Project…, selecione Application, em seguida Qt Widgets Application e prossiga. Na janela seguinte dê um nome para o projeto (estarei usando o nome myCam) e avance, deixe selecionado os Kits default e avance. Em Base Classe selecione QWidget, avance e Finish.

Primeira alteração que devemos realizar é adicionar multimedia ao QT do myCam.pro.

QT       += core gui multimedia

Em seguida no widget.cpp adicionar o header QCamera:

#include "widget.h"
#include "ui_widget.h"
#include <QCameraInfo>

Pronto, as dependências eram essas, agora vamos a uma primeira aplicação, onde irei listar as câmeras e imprimir no output do console.

O seu widget.h deve ficar como abaixo:

#ifndef WIDGET_H
#define WIDGET_H

#include <Qwidget>
#include <QCamera>

namespace Ui {
class Widget;
}
class Widget : public QWidget
{
    Q_OBJECT
public:
    explicit Widget(QWidget *parent = 0);
    ~Widget();
private:
    Ui::Widget *ui;
    bool checkCameras(void);
};
#endif // WIDGET_H

E agora o widget.cpp:

#include "widget.h"
#include "ui_widget.h"

#include <QCameraInfo>
#include <QDebug>

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
    if(checkCameras()){
            //codigo
    }

}
Widget::~Widget()
{
    delete ui;
}

bool Widget::checkCameras()
{
    int camCount = QCameraInfo::availableCameras().count();
    if ( camCount > 0) {
        qDebug() << "Cameras encontradas: " << camCount << endl;
        return true;
    }
    else {
        qDebug() << "Nenhuma camera foi detectada!" << endl;
        return false;
    }
}

Pressionando Ctrl+b construímos a aplicação e Ctrl+r a executamos. A saída da aplicação, no meu caso sem câmera, conectando 1 câmera e depois 2 câmeras:

Starting 
../Projetos/build-myCam-Desktop_Qt_5_5_0_GCC_64bit-Debug/myCam...
Nenhuma camera foi detectada! 

Starting 
../Projetos/build-myCam-Desktop_Qt_5_5_0_GCC_64bit-Debug/myCam...
Cameras encontradas: 1 

Starting 
../Projetos/build-myCam-Desktop_Qt_5_5_0_GCC_64bit-Debug/myCam...
Cameras encontradas: 2 

Para realizar estes testes em meu notebook, primeiro eu removi o módulo uvcvideo:

$ sudo rmmod uvcvideo

Executei a aplicação e nenhuma câmera foi detectada. Em seguida, subi o módulo novamente:

$ sudo modprobe uvcvideo

Executei a aplicação e uma câmera foi detectada. Na sequência pluguei uma webcam na porta USB e executei novamente a aplicação. Ela detectou 2 dispositivos.

Quem fez todo o trabalho foi o QCameraInfo::availableCameras() e usando a função count() conseguimos saber quantos dispositivos foram detectados. Validar essa verificação antes de iniciar a aplicação é importante.

Obtendo informações das câmeras

Acima conseguimos listar as câmeras presentes no notebook no qual estamos executando a aplicação, e se quiséssemos obter mais detalhes sobre cada dispositivo, como o nome do dispositivo e descrição.

Vamos editar o widget.cpp da seguinte maneira:

#include "widget.h"
#include "ui_widget.h"

#include <QCameraInfo>
#include <QDebug>

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
    if(checkCameras()){
        QList<QCameraInfo> cameras = QCameraInfo::availableCameras();
        foreach (const QCameraInfo &cameraInfo, cameras) {
            qDebug() << "Device Name  : " << cameraInfo.deviceName() << endl;
            qDebug() << "Description  : " << cameraInfo.description() << endl;
            qDebug() << "Position     : " << cameraInfo.position() << endl;
            qDebug() << "Cam Default  : " << cameraInfo.defaultCamera() << endl;
            qDebug() << "Orientation  : " << cameraInfo.orientation() << endl;
        }
    }
}

Widget::~Widget()
{
    delete ui;
}

/**
 * @brief Widget::checkCameras
 * @return
 */
bool Widget::checkCameras()
{
    int camCount = QCameraInfo::availableCameras().count();
    if ( camCount > 0) {
        qDebug() << "Cameras encontradas: " << camCount << endl;
        return true;
    }
    else {
        qDebug() << "Nenhuma camera foi detectada!" << endl;
        return false;
    }
}

Usei a mesma aplicação, mas caso sejam encontradas câmeras, irei montar uma QList e imprimir na tela varias informações, que pode ser vista na lista 13 a 19.

Starting 
../Projetos/build-myCam-Desktop_Qt_5_5_0_GCC_64bit-Debug/myCam...
Cameras encontradas: 2 

Device Name : "/dev/video0" 
Description : "Lenovo EasyCamera" 
Position    : QCamera::UnspecifiedPosition 
Cam Default : "QCameraInfo(deviceName=/dev/video0, position=UnspecifiedPosition, orientation=0)" 
Orientation : 0 

Device Name : "/dev/video1" 
Description : "USB2.0 Camera" 
Position    : QCamera::UnspecifiedPosition 
Cam Default : "QCameraInfo(deviceName=/dev/video0, position=UnspecifiedPosition, orientation=0)" 
Orientation : 0 

Uma análise rápida que podemos fazer é que a webcam do meu notebook é o device /dev/video0 e a webcam USB é /dev/video1. A câmera default é a do meu notebook /dev/video0, tenho a description de cada uma, que facilita saber quem é quem. Position não tem definido, mas é algo muito útil, pois podemos ter QCamera::BackFace e QCamera::FrontFace, uma forma de dizer se a câmera esta atrás da tela ou na frente, igual nos celulares. Além do parâmetro orientation.

Existem 4 possíveis maneiras de selecionar uma câmera com o QCamera():

  • QCamera() : Sendo a default selecionada;
  • QCamera(const QbyteArray &devicename) : Fornecendo um device name da câmera;
  • QCamera(const QcameraInfo &cameraInfo) : Fornecendo o camerainfo da câmera;
  • QCamera(QCamera::Position position) : Fornecendo QCamera::FrontFace ou QCamera::BackFace.

Construindo aplicação básica com QCamera

Em poucas linhas vamos desenvolver uma aplicação para abrir nossa câmera padrão e mostrar no Widget de nossa aplicação.

Vamos criar o projeto myCamDefault em File > New File or Project… > Application > Qt Widgets Application > name: myCamDefault > Base Class selecione Qwidget > Finish.

Caso tenha dúvida no procedimento para criar uma aplicação Widget, acesse o artigo Qt5 Console e Widgets.

Editando o arquivo myCamDefault.pro:

QT       += core gui multimedia multimediawidgets

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

TARGET = myCamDefault
TEMPLATE = app

SOURCES += main.cpp\
        widget.cpp

HEADERS  += widget.h

FORMS    += widget.ui

No .pro adicionamos multimedia e multimediawidgets, que são dependências para QCamera, e agora vamos ao widget.cpp:

#include "widget.h"
#include <QApplication>

#include <QCamera>
#include <QCameraViewfinder>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Widget w;

    /* Construtor Camera com QObject parent e/ou especificação do
     * device Camera
     */
    QCamera cam(&w);

    /* Iniciando o objeto da classe QCameraViewfinder para a visualização
     * do nosso device Camera
     */
    QCameraViewfinder viewf(&w);

    /*
     * Setando nosso visualizador para o tamanho Largura x Altura
     */
    viewf.setFixedWidth(w.geometry().width());
    viewf.setFixedHeight(w.geometry().height());

    /*
     * Passando para nosso objeto cam o visualizador que
     * criamos e setamos as dimensões
     */
    cam.setViewfinder(&viewf);

    /* Iniciando visualização do nosso device Camera */
    cam.start();

    /* Exibindo nosso Widget */
    w.show();

    return a.exec();
}

Tudo começa na linha 15 onde crio o objeto QCamera cam e passo o w, que é o widget atual da minha aplicação. Na linha 20 crio um objeto QCameraViewFinder viewf, que é nosso visualizador, e passo o w novamente. Na linha 25 e 26 é uma macete para que o QCameraViewFinder ocupe o Widget inteiro, ou melhor, seja do tamanho dele. Na linha 32 passo para meu objeto cam quem será meu visualizado, no caso, viewf e logo em seguida inicio a câmera.

Construindo e executando nossa aplicação (Ctrl+b e Ctrl+r), temos a aplicação com a reprodução da câmera, conforme a Figura 1.

camera usando Qt5: QCamera e ViewFinder
Figura 1: Qt5 Widget com QCameraViewFinder reproduzindo webcam

Selecionando uma câmera e visualizando

Agora vamos criar outro projeto, onde podemos listar as câmeras disponíveis, escolher uma e reproduzir na aplicação.

Vamos criar o projeto myCamSelect em File > New File or Project… > Application > Qt Widgets Application > name: myCamSelect > Base Class selecione Qwidget > Finish.

OBS: Deve-se adicionar multimediawidgets ao QT do myCamSelect.pro, para trabalhar com o QCameraViewFinder como Widget.

QT         += core gui multimedia multimediawidgets

greaterThan(QT_MAJOR_VERSION, 4):  QT += widgets

TARGET = myCamSelect
TEMPLATE - app

SOURCES += main.cpp \
          widget.cpp

HEADERS  += widget.h

FORMS += widget.ui

Primeiramente vamos “desenhar” nossa tela clicando no widget.ui, que possuirá:

ComponenteNome
QpushButtonbtnOpenCam
QpushButtonbtnCloseCam
QpushButtonbtnCaptureImage
QpushButtonbtnClose
QComboBoxcbListCam
QStackedWidgetstackedWidget
QWidgetviewfinderPage
QCameraViewFindercamViewFinder

Caso tenha alguma dificuldade em posicionar ou configurar a interface gráfica (.ui), o projeto completo será disponibilizado no final do artigo. Segue na Figura 2 como ficou a tela.

camera usando Qt5: Qt5UIQCamera
Figura 2: Desenho da tela Cameras no Qt5 com QCamera

Agora segue o código com comentários em cada função ou uma importante etapa da aplicação, começando pelo widget.h:

#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>

#include <QList>
#include <QCameraInfo>
#include <QCameraViewfinder>

namespace Ui {
class Widget;
}
class Widget : public QWidget
{
    Q_OBJECT
public:
    explicit Widget(QWidget *parent = 0);
    ~Widget();
    void SetCbListCam(QList<QCameraInfo> &cams);
private slots:
    void on_btnOpenCam_clicked();
    void on_btnCloseCam_clicked();
    void on_btnCaptureImage_clicked();
    void on_btnClose_clicked();
private:
    Ui::Widget *ui;
    QCameraViewfinder *viewFinder;
    QCamera *camera;
    bool checkCameras(void);
    void OpenCam(void);
protected:
    QList<QCameraInfo> devCameras;
};
#endif // WIDGET_H

Editando  o widget.cpp:

#include "widget.h"
#include "ui_widget.h"

#include <QCameraInfo>
#include <QDebug>
#include <QMessageBox>

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);

    QMessageBox msgApp;

    /* Check if find device cameras here */
    if(checkCameras()){
        devCameras = QCameraInfo::availableCameras();
        foreach (const QCameraInfo &cameraInfo, devCameras) {
            qDebug() << "Device Name  : " << cameraInfo.deviceName() << endl;
            qDebug() << "Description  : " << cameraInfo.description() << endl;
            qDebug() << "Position     : " << cameraInfo.position() << endl;
            qDebug() << "Cam Default  : " << cameraInfo.defaultCamera() << endl;
            qDebug() << "Orientation  : " << cameraInfo.orientation() << endl;
        }
    }

    /* Set in ComboxBox list of device cameras */
    this->SetCbListCam(devCameras);

    /* If find camera OK, enable button Conectar
     * else Message Box "Not Found Device Camera"
     */
    if(ui->cbListCam->count() < 1) {
        msgApp.setWindowTitle("Informação");
        msgApp.setInformativeText("Nenhuma camera foi encontrada...");
        msgApp.setIcon(QMessageBox::Information);
        msgApp.exec();
    }
    else {
        ui->btnOpenCam->setEnabled(true);
    }
}


/**
 * @brief Widget::~Widget
 * Object Destructor Class Widget
 */
Widget::~Widget()
{
    delete ui;
}


/**
 * @brief Widget::SetCbListCam
 * @param cams
 * Function to load device cameras in ComboBox
 */
void Widget::SetCbListCam(QList<QCameraInfo> &cams)
{
    QStringList AllCams;
    foreach (const QCameraInfo &cam, cams) {
        /* Set Description in ComboBox */
        //AllCams.append(cam.description());
        /* Set DeviceName in ComboBox */
        AllCams.append(cam.deviceName());
    }
    ui->cbListCam->addItems(AllCams);
}


/**
 * @brief Widget::on_btnOpenCam_clicked
 */
void Widget::on_btnOpenCam_clicked()
{
    QByteArray myDeviceCam;
    /* Enable Button "Capturar Image" and "Desconectar" */
    ui->btnCaptureImage->setEnabled(true);
    ui->btnCloseCam->setEnabled(true);
    /* Trick: Convert to QString to QByteArray using .toUtf8() */
    myDeviceCam = ui->cbListCam->itemText(ui->cbListCam->currentIndex()).toUtf8();
    /* Set device select in ComboxBox */
    camera = new QCamera(myDeviceCam);
    /*
     * Create ViewFinder "Visualizador" to device camera
     */
    viewFinder = new QCameraViewfinder(ui->camViewfinder);
    /* Call function OpenCam() */
    this->OpenCam();
}


/**
 * @brief Widget::checkCameras
 * @return True or False if find device cameras
 */
bool Widget::checkCameras()
{
    int camCount = QCameraInfo::availableCameras().count();
    if ( camCount > 0) {
        qDebug() << "Cameras encontradas: " << camCount << endl;
        return true;
    }
    else {
        qDebug() << "Nenhuma camera foi detectada!" << endl;
        return false;
    }
}


/**
 * @brief Widget::OpenCam
 */
void Widget::OpenCam(void)
{ 
    /*
     * Set resize screen width x heigth with size my ViewFinder
     */
    viewFinder->setFixedWidth(ui->camViewfinder->width());
    viewFinder->setFixedHeight(ui->camViewfinder->height());
    /*
     * Set my ViewFinder Widget in ViewFinder object QCamera
     */
    camera->setViewfinder(viewFinder);
    /*
     * Show ViewFinder
     */
     viewFinder->show();
    /*
     * Start capture video
     */
     camera->start();
}


/**
 * @brief Widget::on_btnCloseCam_clicked
 */
void Widget::on_btnCloseCam_clicked()
{
    /*
     * Stop capture video
     */
    camera->stop();
    /* Destruct objects created in OpenCam */
    delete camera;
    delete viewFinder;
    /*
     * Enable button "Conectar"
     * Disable buttons "Descontar" and "Captura Image"
     */
    ui->btnOpenCam->setEnabled(true);
    ui->btnCloseCam->setEnabled(false);
    ui->btnCaptureImage->setEnabled(false);
}


/**
 * @brief Widget::on_btnCaptureImage_clicked
 */
void Widget::on_btnCaptureImage_clicked()
{
    /* Implement Code Here! */
    /* Future Implementation */
}


void Widget::on_btnClose_clicked()
{
    ui->btnCloseCam->click();
    close();
}

Em main.cpp não houve alterações.

Para entender o que foi feito, criamos dois ponteiros, um para QCamera que será o objeto cam e um para QCameraViewFinder que será o objeto viewFinder. No widget.cpp setamos o cam com o device selecionado no QComboBox e configuramos nossa viewFinder com o QCameraViewFinder no QStackedWidget, e os botões possuem ações de iniciar e parar a câmera. O botão Captura Image é um aperitivo para o próximo artigo.

Compilando e executando nossa aplicação:

câmera usando Qt5: câmera externa
Figura 3: Selecionando /dev/video1 no Qt5 QCamera
câmera usando Qt5: câmera onboard
Figura 4: Selecionando /dev/video0 no Qt5 QCamera

Como não tenho mais um Tux, o Sidney (Figura 3) auxiliou na captura da webcam externa 🙂 e eu na webcam onboard.

As aplicações aqui apresentadas têm por fim mostrar as possibilidades da ferramenta em uma abordagem didática. A partir desta base pode-se customizar e explorar os recursos de acordo com a necessidade da aplicação ou projeto.

[wpdm_asset id=’12’]

Referências

Licença Creative Commons Esta obra está licenciada com uma Licença Creative Commons Atribuição-CompartilhaIgual 4.0 Internacional.
Comentários:
Notificações
Notificar
3 Comentários
recentes
antigos mais votados
Inline Feedbacks
View all comments
SSL
SSL
03/12/2020 09:32

Parabéns, companheiro! Este tutorial me foi verdadeiramente útil.

MIGUEL EDUARDO GUTIERREZ PAREDES
MIGUEL EDUARDO GUTIERREZ PAREDES
05/05/2020 20:55

O arquivo de descarga nao esta disponivel, acho que o link ficou no html errado

MIGUEL EDUARDO GUTIERREZ PAREDES
MIGUEL EDUARDO GUTIERREZ PAREDES
05/05/2020 20:55

O arquivo deste tuto nao esta disponivel?

Home » Software » Interface Gráfica » Aplicação com câmera usando Qt5

EM DESTAQUE

WEBINARS

VEJA TAMBÉM

JUNTE-SE HOJE À COMUNIDADE EMBARCADOS

Talvez você goste: