Tutorial para criação de uma aplicação
com Python , Qt e OpenCV
Autor: Leonardo Nogueira Matos
Data: fevereiro/2022
Neste material apresentamos uma solução para usar OpenCV e Qt com linguagem Python .
Usaremos como estudo de caso a apresentação da webcam numa GUI com Qt .
OpenCV e Qt são bibliotecas famosas, maduras, com inúmeros usuários, mantidos por grandes
empresas, com ampla documentação e binding para linguagem Python . Cada uma delas tem sua
linha de atuação própria, enquanto Qt é usada principalmente para construir interfaces gráficas (GUI -
Graphic User Interface), OpenCV é usada para realizar processamento de imagem e vídeo. Ambas
possuem a API original em linguagem compilada, a primeira API de OpenCV foi desenvolvida para
linguagem C enquanto que a de Qt , em C++ .
Existe mais de um binding do Qt para a linguagem Python . Neste tutorial iremos explorar o PyQt5 .
Uma alternativa ao PyQt é o PySide , desenvolvido e mantido pela própria corporação qeu mantém
o Qt . Quanto ao OpenCV há apenas um binding, que é mantido pela organização que também
mantém o OpenCV .
Neste tutorial não iremos abordar o processo de instalação de nenhuma das bibliotecas. Contamos
que, para que este exemplo possa ser reproduzido, você tenha instalado em sua máquina o
Qt Designer e os módulos PyQt e OpenCV da sua distribuição Python . Neste exemplo usamos a
distribuição Anaconda.
leonardo@pangeia: python
Python 3.7.4 (default, Aug 13 2019, [Link])
[GCC 7.3.0] :: Anaconda, Inc. on linux
Type "help", "copyright", "credits" or "license" for more information.
>>>
Construção da GUI com Qt Designer
O Qt Designer é uma aplicação para editar uma GUI estática de forma rápida e amigável. Através
dela é possível construir uma GUI complexa e incorporá-la ao código Python livrando o programador
de saber e memorizar detalhes sobre o código correspondente em linguagem de programação. O uso
do QtDesigner torna a tarefa bem mais simples e por esta razão será discutido neste tutorial.
Ao instanciar o QtDesigner você verá uma janela como esta.
Para construir a janela principal, uma janela que possa iniciar o processamento do laço de eventos, é
preciso escolher a opção Main Window . Caso já exista uma janela principal e esta seja uma
adicional, você pode escolher outra opção.
Ao criar o layout da janela principal, realize os seguintes passos:
1. Remova a barra de menus;
2. Remova a barra de status.
Em seguida, adicione os seguintes widgets: dois Horizontal Spacers e um Scroll Area. Estes
componentes podem ser encontrados na lista de widgets no lado esquerdo.
O passo seguinte consiste em organizar o layout dos componentes.
Por último, adicione um label à área de scroll.
Geração do código correspondente em Python
Ao salvar a GUI, você verá o surgimento de um arquivo com extensão .ui . Trata-se de um arquivo
xml com todo o conteúdo e configurações aplicadas pelo QtDesigner . Utilize o utilitário de linha de
comando pyuic5 para gerar o código em Python correspondente.
leonardo@pangeia: pyuic5 [Link] -o [Link]
leonardo@pangeia: head -20 [Link]
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file '[Link]'
# Created by: PyQt5 UI code generator 5.9.2
# WARNING! All changes made in this file will be lost!
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
[Link]("MainWindow")
[Link](600, 400)
[Link] = [Link](MainWindow)
[Link]("centralwidget")
[Link] = [Link]([Link])
[Link]("verticalLayout")
[Link] = [Link]()
[Link]("horizontalLayout")
Geração de uma aplicação Python
Você agora pode gerar código Python desacoplado da interface do usuário produzida com o
QtDesigner . Isto é feito criando uma classe descendente daquela gerada pelo aplicativo puic5 .
Assim, a parte com as funções e regras da aplicação, não precisarão ser mexidas sempre que for
feito alguma alteração no arquivo de interface.
from [Link] import *
from [Link] import *
from [Link] import *
from MainWindow import Ui_MainWindow
import sys
class MainWindow(QMainWindow, Ui_MainWindow):
def __init__(self, *args, **kwargs):
super(MainWindow, self).__init__(*args, **kwargs)
[Link](self)
[Link]("Box Filter")
app = QApplication([Link])
window = MainWindow()
[Link]()
[Link]()
A aplicação tem um texto na barra de títulos e ajusta automaticamente a disposição dos wigets
quando sua dimensão é alterada pelo usuário. Entretanto não tem nenhuma funcionalidade.
Streaming da web cam
A captura dos quadros de vídeo da web cam é feita pela biblioteca OpenCV e sua ligação com a GUI,
pelo PyQt , segundo os seguintes passos:
1. Criação de um objeto que representa o dispositivo da câmera ( OpenCV );
2. Criação de um cronômetro para disparar em intervalos de tempo regular ( PyQt );
3. A cada disparo, a aplicação deve ler um quadro de vídeo ( OpenCV );
4. Cada quadro deve ser usado atribuído ao pixmap do label existente na aplicação ( PyQt ).
from [Link] import *
from [Link] import *
from [Link] import *
from MainWindow import Ui_MainWindow
import sysimport cv2
class MainWindow (QMainWindow, Ui_MainWindow):
def __init__(self, *args, **kwargs):
super(QMainWindow,self).__init__ (*args, **kwargs)
[Link] (self)
[Link] ("Box Filter")
[Link] = [Link](0) # objeto que representa a webcam
# objeto que representa um cronometro
[Link] = QTimer()
# ligacao dos disparos do cronometro a uma funcao em Python
[Link] (self.processar_frame)
# start do cronometro com disparos regulares a cada 50 ms
[Link] (50)
# funcao de callback, chamada de slot na literatura do Qt
def processar_frame(self):
# leitura de um frame do video
ret, frame = [Link]()
# conversao de uma imagem do opencv para o formato qt
pixmap = self.convert_cv_qt (frame)
# atribuicao do novo valor do pixmap do label
[Link] (pixmap)
# funcao usada para converter opencv para qt
def convert_cv_qt(self, cv_img):
"""Convert from an opencv image to QPixmap"""
rgb_image = [Link](cv_img, cv2.COLOR_BGR2RGB)
h, w, ch = rgb_image.shape
bytes_per_line = ch * w
convert_to_Qt_format = QImage(rgb_image.data, w, h, bytes_per_line, [Link]
return [Link](convert_to_Qt_format)
app = QApplication ([Link])
window = MainWindow ()
[Link]()
[Link]()
Fontes de consulta
1.[Link]
2.[Link]