reconhecimento de padrões em tempo real utilizando a

46
Reconhecimento de Padrões em Tempo Real Utilizando a Biblioteca OpenCV João Paulo Silva do Monte Lima 1 Daliton da Silva 1 Veronica Teichrieb 1 Judith Kelner 1 Resumo: Reconhecimento de padrões em tempo real é uma tarefa crucial em várias áreas, tais como Realidade Aumentada, Robótica e Interação Homem Computador. A biblioteca OpenCV é uma solução open source para visão computacional que provê várias funcionalidades adequadas para esse tipo de aplicação. A implementação do OpenCV contém várias otimizações que favorecem uma boa performance. Ela também provê funcionalidades simples de usar (out of the box) para interface com o usuário, carregamento de imagens e captura de vídeo. O objetivo deste minicurso é mostrar o potencial do OpenCV para reconhecimento de padrões com restrições de tempo real. Serão apresentadas as principais funções de processamento de imagem presentes no OpenCV que podem ser usadas em sistemas de reconhecimento de padrões, em tempo real. Os algoritmos implementados serão explicados, juntamente com informações sobre como eles podem ser utilizados e sua aplicabilidade a 1 Grupo de Pesquisa em Realidade Virtual e Multimídia, Centro de Informática, UFPE, Av. Professor Moraes Rego S/N, Prédio da Positiva, 1º Andar, Cidade Universitária, Recife, Pernambuco, CEP 50670-901 {jpsml, ds2, vt, jk @cin.ufpe.br}

Upload: others

Post on 18-Apr-2022

3 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Reconhecimento de Padrões em Tempo Real Utilizando a

Reconhecimento de Padrões em Tempo Real Utilizando a

Biblioteca OpenCV

João Paulo Silva do Monte Lima1

Daliton da Silva1

Veronica Teichrieb1

Judith Kelner1

Resumo: Reconhecimento de padrões em tempo real é uma tarefa crucial em

várias áreas, tais como Realidade Aumentada, Robótica e Interação Homem

Computador. A biblioteca OpenCV é uma solução open source para visão

computacional que provê várias funcionalidades adequadas para esse tipo de

aplicação. A implementação do OpenCV contém várias otimizações que

favorecem uma boa performance. Ela também provê funcionalidades simples

de usar (out of the box) para interface com o usuário, carregamento de imagens

e captura de vídeo. O objetivo deste minicurso é mostrar o potencial do

OpenCV para reconhecimento de padrões com restrições de tempo real. Serão

apresentadas as principais funções de processamento de imagem presentes no

OpenCV que podem ser usadas em sistemas de reconhecimento de padrões,

em tempo real. Os algoritmos implementados serão explicados, juntamente

com informações sobre como eles podem ser utilizados e sua aplicabilidade a

1 Grupo de Pesquisa em Realidade Virtual e Multimídia, Centro de Informática, UFPE, Av.

Professor Moraes Rego S/N, Prédio da Positiva, 1º Andar, Cidade Universitária, Recife, Pernambuco,

CEP 50670-901 {jpsml, ds2, vt, jk @cin.ufpe.br}

Page 2: Reconhecimento de Padrões em Tempo Real Utilizando a

Reconhecimento de padrões em tempo real utilizando a biblioteca OpenCV

2 RITA Volume XXXX Número X 20XX

problemas reais. Exemplos de aplicações também serão apresentadas de forma

a ilustrar o uso das funcionalidades de visão computacional descritas.

Abstract: Real-time pattern recognition is a crucial task of systems applied

to several fields, such as Augmented Reality, Robotics and Human Computer

Interaction. The OpenCV library is an open source solution for computer

vision that provides many features suitable for this kind of applications.

OpenCV implementation contains many optimizations that favor a good

processing performance. It also provides out of the box functionalities for user

interface, image loading and video capture. The goal of this tutorial is to show

OpenCV’s potential for pattern recognition with real-time constraints. A

number of image processing functions featured by OpenCV that can be used in

real-time pattern recognition systems will be enumerated. The implemented

algorithms will be explained, along with information of how they can be

utilized and their applicability to real life problems. Example applications will

also be presented in order to illustrate the use of the described computer vision

features.

Page 3: Reconhecimento de Padrões em Tempo Real Utilizando a

Reconhecimento de padrões em tempo real utilizando a biblioteca OpenCV

RITA Volume XXXX Número X 20XX 3

1 Introdução

O OpenCV é uma biblioteca open source para processamento de imagens offline e em

tempo real. Ela pode ser utilizada em diversas e diferentes áreas, como em interação homem-

máquina (Human-Computer Interaction, HCI), identificação de objetos, segmentação e

reconhecimento, reconhecimento de faces, reconhecimento de gestos, rastreamento de

movimentos, ego motion, compreensão de movimentos e Structure from Motion (SfM), e

robótica móvel. A Tabela 1 apresenta uma descrição mais detalhada das funções suportadas

pelo OpenCV. A biblioteca é desenvolvida pela Intel, e está em desenvolvimento desde

2001, com a primeira versão liberada em outubro de 2006. Existem versões do OpenCV

tanto para o sistema operacional Windows quanto para o Linux.

Tabela 1. Principais funções do OpenCV

Funçaõ Descrição

Manipulação de imagens Alocação, desalocação, cópia, modificação, conversão

IO de vídeo e imagem Input e output baseado em arquivo e câmera

Manipulação de matrizes e

vetores e retinas de álgebra

linear

Produto, solução, single value decomposition (SVD)

Diversas estruturas de dados

dinâmicas

Listas, filas, pilhas, árvores, grafos

Processamento de imagens

básico

Fitragem, detecção de bordas, detecção de cantos,

interpolação e amostragem, conversão de cor, operações

morfológicas, histogramas, pirâmides de imagens.

Análise estrutural Componentes conexos, processamento de contornos,

transformação de distância, momento diverso, casamento

de templates, aproximação poligonal, montagem de linha,

montagem de elipse, triangularização de Delaunay

Calibração de câmera Busca, rastreamento e calibração de padrões, calibração,

estimação de matrizes fundamentais, estimação

homográfica, correspondência estéreo.

Análise de movimentos Fluxo óptico, segmentação de movimentos, rastreamento

Reconhecimento de objetos. Métodos-eigen, Hidden Markov Models (HMM)

GUI básica Exibição de vídeo e imagens, tratamento de entrada do

teclado e do mouse, barras de rolagens

Labeling de imagens Linha, cônica, polígono, texto, desenho de texto

O código do OpenCV encontra-se disponível para download e é aberto para modificações,

desde que as cláusulas da licença sejam obedecidas. O OpenCV foi escrito em C/C++, e

provê suporte para desenvolvedores que utilizam o Microsoft Visual Studio, Eclipse Project

e C++ Builder (quando utilizando Windows) e make files (quando utilizando Linux).

OpenCV pode ser dividido em quatro módulos: cv, cvaux, cxcore e highgui. O módulo cv

Page 4: Reconhecimento de Padrões em Tempo Real Utilizando a

Reconhecimento de padrões em tempo real utilizando a biblioteca OpenCV

4 RITA Volume XXXX Número X 20XX

contém as funções padrões podendo ser considerado o coração da biblioteca. O módulo

cvaux, como o nome sugere, implementa funções que suportam o uso do OpenCV. O módulo

cxcore é responsável pelas estruturas de dados e operações de álgebra linear. Por fim, o

módulo highgui provê suporte para funções de GUI, como a exibição de janela contendo

imagens capturadas pela webcam, por exemplo.

1.1 Motivação

Reconhecimento de padrões em tempo real representa uma importante tarefa de

aplicações em diversas áreas, como realidade aumentada, robótica e HCI. OpenCV provê

funcionalidades para construção de interfaces com o usuário, leitura de imagens e captura de

vídeo, por exemplo. A biblioteca OpenCV é uma solução de código aberto para visão

computacional que provê funcionalidades adequadas para aplicações dos tipos listados

anteriormente. A biblioteca foi definida para prover uma interface de programação simples,

podendo ser facilmente integrada em outros projetos que já existam.

Um importante problema envolvendo o reconhecimento de padrões é o pesado

processamento exigido por esse tipo de tarefa. Por causa disto, o OpenCV contém

otimizações que resultam em bom desempenho para as suas aplicações. Como o OpenCV é

implementado pela Intel, ele contém otimizações especificamente desenvolvidas para os

processadores da Intel.

A Intel tem realizado investimentos de larga escala no desenvolvimento do OpenCV. Seus

pesquisadores se dedicam ao desenvolvimento de novas funcionalidades para o OpenCV,

que são incorporadas a biblioteca a cada nova versão distribuída. Como exemplo, pode-se

citar a função cvGoodFeaturesToTrack, baseada no trabalho de Carlo Tomasi [1].

1.2 Licença

A licença do OpenCV permite a modificação e a livre distribuição do seu código fonte e

binários, desde que certas condições sejam observadas. Entre essas condições, as seguintes

são relevantes:

- O código fonte e os binários distribuídos devem conter todas as informações listadas na

licença original do OpenCV;

- O nome da Intel ou qualquer uma de suas marcas não podem ser utilizados para

promover o uso de aplicações que utilizem OpenCV sem a prévia autorização.

1.3 Instalação

O OpenCV pode ser instalado através de um wizard, disponível em

http://sourceforge.net/projects/opencvlibrary/, ou pode ser adquirido diretamente do CVS. As

instruções para o uso do CVS estão disponíveis em

http://sourceforge.net/cvs/?group_id=22870. Em ambos os casos podem ser copiados o

código fonte e os binários.

Na sequência, a instalação passo a passo do OpenCV é descrita. A Figura 1 mostra a tela

que aparece na instalação do OpenCV. Clicando no botão “Next”, a licença de usuário é

Page 5: Reconhecimento de Padrões em Tempo Real Utilizando a

Reconhecimento de padrões em tempo real utilizando a biblioteca OpenCV

RITA Volume XXXX Número X 20XX 5

exibida. Para aceitar os termos listados, o usuário deve clicar na opção “I accept the

agreement” e clicar no botão next novamente. As três telas seguintes do processo de

instalação exibem as configurações de instalação padrões. A Figura 1 ilustra a primeira

dessas telas. Depois de confirmar todas as opções, o OpenCV é copiado para o disco rígido e

estará pronto para o uso.

Figura 1. A primeira tela da instalação do OpenCV.

Para recompilar o código do OpenCV utilizando o Microsoft Visual Studio, é necessário

abrir o arquivo “opencv.sln”, localizado dentro da pasta “_make”. Desta forma todo o

ambiente de desenvolvimento é configurado para a correta compilação do código. Na

sequência, o usuário clica em “Build Solution”, do menu “Build”, como ilustrado na Figura

2. Cada módulo do OpenCV é compilado em duas Iink libraries (.dll e .lib). Elas integram o

OpenCV com projetos desenvolvidos pelo usuário.

Page 6: Reconhecimento de Padrões em Tempo Real Utilizando a

Reconhecimento de padrões em tempo real utilizando a biblioteca OpenCV

6 RITA Volume XXXX Número X 20XX

Figura 2. Compilando o código fonte do OpenCV.

1.4 Documentação

O OpenCV possui uma documentação completa, muitos fóruns e grupos de discussão,

resultando em um suporte eficiente para os usuários da biblioteca. A aplicação de instalação

automaticamente copia uma série de documentos de suporte ao usuário. Dentre estes

documentos, o “opencvman_old.pdf” merece uma atenção especial, este é o manual de

referência da biblioteca. Neste documento pode ser encontrada a descrição em detalhes das

funções do OpenCV e códigos de exemplos. O manual também explica conceitos gerais

referentes ao OpenCV, como a definição de tipos de dados específicos e guias de

implementação utilizados e processamento de imagens. O grupo de discussão sobre OpenCV

está disponível em http://tech.groups.yahoo.com/group/OpenCV. A documentação também

está disponível na instalação do OpenCV como um arquivo HTML, que é uma versão mais

simples porém mais freqüentemente atualizada do manual.

Quando o usuário se registra (o registro no grupo de discussão é grátis) ele pode acessar

uma extensa base de dados envolvendo questões práticas. O usuário tem a possibilidade de

postar suas questões que não podem ser resolvidas utilizando a documentação existente.

Existe uma grande chance de que a questão seja resolvida, pois a comunidade do OpenCV

possui um grande número de membros ativos.

2 Funcionalidades

Este capítulo explica um conjunto de funções do OpenCV relativas a vários passos do

pipeline de processamento de imagens. As funções relativas a pré-processamento,

Page 7: Reconhecimento de Padrões em Tempo Real Utilizando a

Reconhecimento de padrões em tempo real utilizando a biblioteca OpenCV

RITA Volume XXXX Número X 20XX 7

segmentação, representação e reconhecimento são inseridas em um contexto e sua utilização

é explicada.

2.1 Realce de imagens e seleção de características

O principal objetivo do realce de imagens é processar uma imagem de forma que o

resultado seja mais adequado do que a imagem original para um conjunto de aplicações

específicas.

Existem basicamente duas abordagens para o realce de imagens: métodos do domínio

espacial e métodos do domínio de freqüência. O termo domínio espacial se refere ao próprio

plano de imagem, e abordagens nesta categoria são baseadas na manipulação direta de pixels

de uma imagem. Técnicas do domínio de freqüência são baseadas em modificar a

transformada de Fourier de uma imagem. A biblioteca OpenCV trata somente um

subconjunto de técnicas do domínio espacial.

Além disso, neste capítulo algumas funções relacionadas a seleção de características (por

exemplo, arestas e cantos) são apresentadas.

Suavização. Filtros de suavização são usados para borramento e redução de ruído. O

borramento é usado em etapas de pré-processamento, tais como remoção de pequenos

detalhes de uma imagem. Além disso, a redução de ruído pode ser feita através de um

borramento usando um filtro linear e através de uma filtragem não-linear. Um exemplo de

uso do borramento é mostrado na Figura 3.

Figura 3. Imagem original (esquerda), um kernel uniforme (centro) e um kernel Gaussiano (direita).

Na biblioteca OpenCV, existe uma função relativa a filtragem de suavização chamada

cvSmooth, e como a operação de suavização nada mais é que uma convolução com uma

matriz específica, é possível usar a função cvFilter2D.

Ambas as funções são explicadas abaixo.

void cvSmooth( const CvArr* src, CvArr* dst,

int smoothtype,int param1, int param2,

double param3 );

O argumento src é a imagem de origem, dst é a imagem de destino, smoothtype é o

tipo da suavização que pode ser aplicada (todos os tipos estão listados na Tabela 2).

Page 8: Reconhecimento de Padrões em Tempo Real Utilizando a

Reconhecimento de padrões em tempo real utilizando a biblioteca OpenCV

8 RITA Volume XXXX Número X 20XX

Tabela 2. Tipos de suavização do OpenCV.

Tipo de suavização Descrição

CV_BLUR_NO_SCALE Somatório em uma vizinhança de pixels param1×param2

CV_BLUR Somatório em uma vizinhança de pixels

param1×param2 com subseqüente escala

por 1/(param1×param2)

CV_GAUSSIAN Convolução da imagem com um kernel

Gaussiano param1×param2

CV_MEDIAN Mediana de uma vizinhança de pixels

param1×param1 (ou seja, a vizinhança é

quadrada)

CV_BILATERAL Aplicação de um filtro 3x3 bilateral com cor

sigma=param1 e espaço sigma=param2,

como descrito em [2]

Quando o smoothtype Gaussiano é usado, param3 indica o sigma da Gaussiana (isto

é, o desvio padrão). E se ele for zero, ele é calculado a partir do tamanho do kernel, usando a

fórmula:

8.03.0*)12/(nsigma ,

onde sigma é param1 ou param2, dependendo da orientação do kernel (horizontal ou

vertical).

Outra função relacionada com convoluções é cvFilter2D, que é uma função que

convolui qualquer kernel linear com uma imagem, e sua assinatura é:

void cvFilter2D( const CvArr* src, CvArr* dst,

const CvMat* kernel, CvPoint anchor);

onde src é a imagem de origem, dst é a imagem de destino e kernel é o kernel de

convolução, uma matriz de ponto flutuante mono-canal. O anchor indica a posição relativa

de um ponto filtrado com o kernel, a única preocupação é que o ponto da âncora deve estar

dentro do kernel. O valor padrão especial (-1,-1) significa que ele está no centro do kernel.

Detecção de arestas. As técnicas de detecção de arestas são inerentemente fáceis de

implementar e possuem uma complexidade computacional baixa. Como um exemplo de

aplicação de detecção de arestas para rastreamento, o RAPiD [3] é comumente citado, e pode

ser visto na Figura 4.

Este capítulo apresenta todas as funções relativas a detecção de arestas do OpenCV. Os

operadores de Sobel, de Canny e Laplaciano são apresentados.

Page 9: Reconhecimento de Padrões em Tempo Real Utilizando a

Reconhecimento de padrões em tempo real utilizando a biblioteca OpenCV

RITA Volume XXXX Número X 20XX 9

Figura 4. Alguns pontos são amostrados ao longo das arestas do modelo (esquerda), estes pontos são

utilizados para inferir a pose (centro). Oclusões podem ser tratadas de uma forma robusta (direita).

Operador de Sobel. O operador de Sobel realiza uma medida do gradiente espacial 2D de

uma imagem e enfatiza regiões de alto gradiente espacial que correspondem a arestas.

Tipicamente ele é usado para encontrar a magnitude absoluta aproximada do gradiente em

cada ponto de uma imagem em tons de cinza de entrada. Um exemplo de uso do operador de

Sobel é ilustrado na Figura 5.

Figura 5. Imagem em tons de cinza (esquerda), imagem do gradiente x de Sobel (centro) e imagem do

gradiente y de Sobel (direita).

Pelo menos na teoria, o operador consiste em um par de máscaras de convolução 3x3

como as mostradas na Figura 6. Uma máscara é simplesmente a outra após sofrer uma

rotação de 90°.

Figura 6. Máscaras de convolução de Sobel.

Estas máscaras são designadas para responder maximamente a arestas verticais e

horizontais com relação à grade de pixels, uma máscara para cada uma das duas orientações

Page 10: Reconhecimento de Padrões em Tempo Real Utilizando a

Reconhecimento de padrões em tempo real utilizando a biblioteca OpenCV

10 RITA Volume XXXX Número X 20XX

perpendiculares. As máscaras podem ser aplicadas independentemente na imagem de entrada

para produzir medidas separadas da componente do gradiente em cada orientação (chamadas

Gx e Gy ). Elas podem ser combinadas para encontrar a magnitude absoluta do gradiente

em cada ponto e a orientação desse gradiente. A magnitude do gradiente é dada por:

x yG G G,

embora tipicamente uma magnitude aproximada pode ser computada rapidamente usando:

x yG G G

Na biblioteca OpenCV, o operador de Sobel é implementado através da função

cvSobel, e sua assinatura é:

void cvSobel( const CvArr* src, CvArr* dst, int xorder,

int yorder, int aperture_size );

O argumento src é a imagem de origem, dst é a imagem de destino, xorder é a ordem

da derivada x , yorder é a ordem da derivada no eixo y . O parâmetro aperture_size

é o tamanho do kernel de Sobel estendido, ele precisa ser 1, 3, 5 ou 7. Em todos os casos,

exceto quando ele é 1, um kernel aperture_size x aperture_size será usado para

calcular a derivada. Existe também um valor especial para aperture_size CV_SCHARR

que corresponde ao filtro 3x3 de Scharr [4].

Operador Laplaciano. O Laplaciano é uma medida isotrópica 2D da derivada segunda

espacial de uma imagem. O Laplaciano de uma imagem destaca regiões de rápida mudança

de intensidade e portanto é comumente usado para detecção de arestas.

O Laplaciano é freqüentemente aplicado em uma imagem que foi primeiramente

suavizada com um filtro Gaussiano aproximado de forma a reduzir sua sensibilidade a ruído,

e por isso as duas variantes serão descritas em conjunto neste texto. O operador normalmente

toma uma única imagem em tons de cinza como entrada e produz outra imagem em tons de

cinza como saída.

O Laplaciano ),( yxL de uma imagem com valores de intensidade de pixel ),( yxI é

dado por: 2 2

2 2( , )

I IL x y

x y

Este operador pode ser aproximado por um filtro de convolução. Visto que a imagem de

entrada é representada por um conjunto de pixels discretos, é necessário encontrar um kernel

de convolução discreta que possa aproximar as derivadas segundas na definição do

Laplaciano. Dois kernels pequenos comumente utilizados são mostrados na Figura 7.

Page 11: Reconhecimento de Padrões em Tempo Real Utilizando a

Reconhecimento de padrões em tempo real utilizando a biblioteca OpenCV

RITA Volume XXXX Número X 20XX 11

Figura 7. Duas aproximações discretas do filtro Laplaciano comumente usadas.

A função do OpenCV que implementa o Laplaciano de uma imagem é cvLaplace, e

sua assinatura é:

void cvLaplace( const CvArr* src, CvArr* dst,

int aperture_size );

O argumento src é a imagem de entrada, dst é a imagem resultante, e

aperture_size é o mesmo argumento usado no operador de Sobel.

Operador de Canny. O operador de Canny foi projetado para ser um detector de arestas

ótimo (de acordo com critérios particulares, isto é, existem outros detectores que também

afirmam ser ótimos de acordo com critérios ligeiramente diferentes). Ele usa como entrada

uma imagem em tons de cinza e produz como saída uma imagem mostrando as posições das

descontinuidades de intensidade rastreadas. Um exemplo do operador de Canny é a Figura 8.

Como pode ser visto nesta figura, as arestas da imagem foram destacadas.

Figura 8. Imagem crua (esquerda), imagem resultante (direita).

O operador de Canny funciona como um processo multi-estágio. Primeiramente, a

imagem é suavizada usando convolução Gaussiana. Então, uma derivada primeira 2D

simples é aplicada à imagem suavizada para destacar regiões da imagem com derivadas

primeiras espaciais altas. Arestas dão origem a picos na imagem da magnitude do gradiente.

O algoritmo então rastreia ao longo do topo desses picos e seta para zero todos os pixels que

não estão no topo dos picos, de forma a gerar linhas finas na saída, um processo conhecido

Page 12: Reconhecimento de Padrões em Tempo Real Utilizando a

Reconhecimento de padrões em tempo real utilizando a biblioteca OpenCV

12 RITA Volume XXXX Número X 20XX

como supressão de não-máximos. O processo de rastreamento utiliza uma histerese

controlada por dois limiares: 1T e 2T , com 1T > 2T . O processo de rastreamento só pode

começar em um ponto de pico maior que 1T . O rastreamento então continua em ambas as

direções a partir desse ponto até que a altura do pico fique abaixo de 2T . Esta histerese ajuda

a garantir que arestas com ruído não sejam quebradas em múltiplos fragmentos.

O operador de Canny é implementado no OpenCV através da função cvCanny e sua

assinatura é a seguinte:

void cvCanny( const CvArr* image, CvArr* edges,

double threshold1, double threshold2,

int aperture_size );

O argumento image é a imagem de entrada, edges é a imagem que irá guardar os

resultados, threshold1 e threshold2 são os dois limiares usados nesse operador,

aperture_size é o parâmetro de abertura, assim como no operador de Sobel.

Detecção de cantos. Uma das abordagens da literatura de visão computacional para

extrair certos tipos de características de uma imagem é a detecção de cantos, ou mais

genericamente detecção de pontos de interesse. A Figura 9 mostra uma aplicação de

realidade aumentada sem marcadores baseada em pontos de interesse [5] que é capaz de

rastrear, por exemplo, a posição e orientação de um computador usando alguns pontos de

interesse. E como pode ser notado na Figura 9 acima e à direita, a maioria dos pontos de

interesse estão localizados ao redor de cantos. Na Figura 9 abaixo e à esquerda, é possível

ver que o algoritmo é robusto a rotação e translação, uma vez que a posição da placa é

rastreada corretamente.

Alguns usos da detecção de características incluem detecção de movimento, mosaicos de

imagens, colagem de imagens panorâmicas, modelagem 3D e reconhecimento de objetos.

Page 13: Reconhecimento de Padrões em Tempo Real Utilizando a

Reconhecimento de padrões em tempo real utilizando a biblioteca OpenCV

RITA Volume XXXX Número X 20XX 13

Figura 9. Inicialmente, o aramado é casado com o computador (acima, à esquerda), oito pontos são

rastreados (acima, à direita) e finalmente a placa no computador é rastreada (abaixo, à esquerda e à

direita).

Na biblioteca OpenCV, existem três maneiras de detectar pontos de interesse: (1)

diretamente calculando autovetores e autovalores, (2) através do operador de Harris e (3)

usando a função Good Features to Track. As alternativas (1) e (2) se preocupam em detectar

cantos na imagem, e embora a (3) seja baseada na (2), a classe de características que o

algoritmo é capaz de tratar abrange mais elementos do que apenas cantos.

Autovetores e autovalores. A maioria dos algoritmos de detecção de características são

baseados no cálculo de autovalores e autovetores, e esta operação é implementada no

OpenCV através de duas funções, cvCornerEigenValsAndVects e

cvCornerMinEigenVal. Ambas as funções são relativas à matriz de covariação das

derivadas em torno de certo pixel. A matriz de covariação é da forma: 2

2

dI dI dI

dx dx dyC

dI dI dI

dx dy dy

,

Page 14: Reconhecimento de Padrões em Tempo Real Utilizando a

Reconhecimento de padrões em tempo real utilizando a biblioteca OpenCV

14 RITA Volume XXXX Número X 20XX

onde ),( yxI é a intensidade do pixel nas coordenadas ),( yx .

A função cvCornerEigenValsAndVects calcula tanto os autovalores como os

autovetores da matriz de covariação e cvCornerMinEigenVal apenas calcula e guarda

os autovalores desta.

A assinatura de cvCornerEigenValsAndVects é:

void cvCornerEigenValsAndVecs( const CvArr* image,

CvArr* eigenvv,

int block_size,

int aperture_size );

O argumento image é a imagem de entrada, eigenvv é uma imagem que guarda os

resultados e precisa ser seis vezes mais larga que image, block_size é o tamanho da

vizinhança e aperture_size é o parâmetro de abertura como no operador de Sobel.

A assinatura da função cvCornerMinEigenVal é:

void cvCornerMinEigenVal ( const CvArr* image,

CvArr* eigenval, int block_size,

int aperture_size );

Os parâmetros desta função são os mesmos da cvCornerEigenValsAndVecs, com

exceção de eigenval, porque esta função apenas calcula e guarda os menores autovalores

associados com os pixels. Isso significa que cada autovalor é do mesmo tamanho de image,

ao contrário da função cvCornerEigenValsAndVecs que é seis vezes maior, além de

calcular e guardar tanto os autovalores como os autovetores.

Detector de cantos de Harris. O detector de cantos de Harris computa a matriz de

momento com média local a partir dos gradientes da imagem, e então combina os

autovalores da matriz de momento para computar a “força” do canto, da qual valores

máximos indicam as posições dos cantos.

Esse detector também é baseado na matriz de covariação. A chave desta equação está em

examinar seus autovalores. Quando a matriz possui dois autovalores altos, isto corresponde a

duas direções principais diferentes no gradiente da imagem subjacente. Isto é calculado

rapidamente e eficientemente com uma simples equação para a resposta do canto que é

guardada para cada pixel da imagem: 2det( ) *( ( ))R C k trace C ,

onde k é um parâmetro ajustável que determina o quão “aresta-fóbica” a resposta do

algoritmo é.

O resultado da aplicação do algoritmo em uma imagem pode ser visto na Figura 10. Na

figura da direita, é possível ver algumas regiões brancas, relativas a máximas locais que

indicam que uma região é um canto. Deve-se notar que o detector de cantos de Harris é

capaz de encontrar arestas também, como pode ser visto nas regiões cinza escuro da Figura

10.

Page 15: Reconhecimento de Padrões em Tempo Real Utilizando a

Reconhecimento de padrões em tempo real utilizando a biblioteca OpenCV

RITA Volume XXXX Número X 20XX 15

Figura 10. Imagens em tons de cinza (esquerda), o resultado da aplicação do detector de cantos de

Harris (direita).

A assinatura da função é mostrada abaixo:

void cvCornerHarris( const CvArr* image,

CvArr* harris_response,

int block_size,

int aperture_size, double k );

O argumento image é a imagem de entrada, harris_response é a imagem que

guardará o resultado do detector de Harris. O parâmetro block_size é responsável pelo

tamanho da vizinhança, como discutido para autovetores e autovalores. O

aperture_size é o mesmo do operador de Sobel. Finalmente, k é o parâmetro ajustável.

Good Features to Track. O trabalho de Shi e Tomasi [1] em rastreamento de

características é implementado no OpenCV através da função

cvGoodFeaturesToTrack. Ele é fortemente baseado no operador de detecção de cantos

de Harris. A idéia básica do algoritmo é monitorar a qualidade das características da imagem

durante o rastreamento usando uma medida de dissimilaridade da característica que

quantifica a mudança de aparência de uma determinada característica entre o primeiro

quadro e o quadro atual. Abaixo, na Figura 11, as características encontradas na imagem da

esquerda são realçadas e mostradas na imagem de direita.

Page 16: Reconhecimento de Padrões em Tempo Real Utilizando a

Reconhecimento de padrões em tempo real utilizando a biblioteca OpenCV

16 RITA Volume XXXX Número X 20XX

Figura 11. O primeiro quadro da sequência (esquerda), as características selecionadas de acordo com o

critério estabelecido (direita).

Existem algumas precauções relativas a esta função. Uma delas é a necessidade de se ter

duas imagens temporárias de ponto flutuante de 32 bits do mesmo tamanho da imagem de

entrada. Em aplicações onde a memória é um recurso escasso, alguns problemas podem

aparecer quando essa função é usada.

A assinatura da função é mostrada abaixo:

void cvGoodFeaturesToTrack( const CvArr* image,

CvArr* eig_image,

CvArr* temp_image,

CvPoint2D32f* corners,

int* corner_count,

double quality_level,

double min_distance,

const CvArr* mask,

int block_size,

int use_harris,

double k );

O argumento image é a imagem mono-canal de entrada, eig_image e temp_image

são imagens temporárias de ponto flutuante de 32 bits do mesmo tamanho da imagem de

entrada. O parâmetro corners é uma estrutura previamente alocada para comportar os

cantos detectados, corner_count é simplesmente o número de cantos detectados. O

parâmetro quality_level é um número indicando a qualidade mínima aceitável dos

cantos da imagem, min_distance é a distância euclidiana mínima entre os cantos. O

parâmetro mask é a região de interesse, se um ponteiro para NULL é passado, a imagem

inteira é usada. O parâmetro block_size é o mesmo da função do detector de cantos de

Harris. Ao usar esta função, é possível decidir por usar o detector de cantos de Harris setando

use_harris para qualquer valor diferente de zero. Por fim, k é o parâmetro livre do

operador de Harris.

Page 17: Reconhecimento de Padrões em Tempo Real Utilizando a

Reconhecimento de padrões em tempo real utilizando a biblioteca OpenCV

RITA Volume XXXX Número X 20XX 17

2.2 Segmentação

A tarefa de analisar uma imagem de forma a distinguir elementos específicos é chamada

segmentação. Os sub-capítulos a seguir explicam algumas técnicas usadas para atingir esse

objetivo.

Limiarização. Esta técnica consiste em separar os objetos de interesse do fundo da

imagem. Isto é comumente feito com imagens em tons de cinza, mas pode também ser

aplicado a outros formatos, como imagens coloridas. Uma prática comum quando se quer

limiarizar imagens coloridas é considerar a soma das componentes de cor para cada pixel.

A limiarização é feita estimando intervalos de nível que determinam os pixels que

pertencem ao fundo da imagem e a objetos de interesse. Como pode ser visto na Figura 12

(esquerda), quando existe apenas um objeto para segmentar em uma imagem ),( yxf , um

limiar T é especificado e dois intervalos de nível são definidos: Tyxf ),( e

Tyxf ),( . Esta operação é chamada limiarização mono-nível e o resultado é uma

imagem binária que distingue os pixels que pertencem a cada intervalo de nível. Na

limiarização multi-nível, existem n objetos para segmentar, requerendo o uso de diferentes

limiares 1T , …, nT , como mostrado na Figura 12 (direita). O resultado desta operação é uma

imagem em tons de cinza com n níveis distintos.

Figura 12. Limiarização mono-nível (esquerda) e multi-nível (direita)

A operação de limiarização pode também ser classificada como global ou local. Na

limiarização global, os mesmos limiares kT são usados para todos os pixels da imagem. Na

limiarização local, os limiares kT dependem de propriedades locais dos pixels, tais como o

nível médio de sua vizinhança. A limiarização global é mais adequada a imagens onde os

objetos possuem uma iluminação constante. A Figura 13 mostra um exemplo onde um objeto

com iluminação constante é corretamente segmentado usando limiarização global, enquanto

que os resultados obtidos com a limiarização local não são satisfatórios. A limiarização local

Page 18: Reconhecimento de Padrões em Tempo Real Utilizando a

Reconhecimento de padrões em tempo real utilizando a biblioteca OpenCV

18 RITA Volume XXXX Número X 20XX

é mais indicada para casos onde a iluminação dos objetos é variável, visto que ela leva em

consideração características locais da imagem. Na Figura 14, a limiarização local segmenta

mais pixels dos objetos do que a limiarização global, devido à natureza variável da

iluminação dos objetos.

Figura 13. Imagem de entrada onde o objeto possui uma iluminação constante (esquerda), resultado da

limiarização global (centro) e resultado da limiarização local (direita).

Figura 14. Imagem de entrada onde os objetos possuem uma iluminação variável (esquerda), resultado

da limiarização global (centro) e resultado da limiarização local (direita).

Muitos algoritmos de processamento de imagens usados em aplicações de tempo real não

manipulam imagens coloridas. Como resultado, a imagem original tem de ser convertida

para um formato mais adequado, tal como o binário. É aí que a limiarização entra. Um

exemplo de uso da limiarização no reconhecimento de padrões em tempo real aparece no

rastreamento de marcadores feito pela biblioteca de realidade aumentada ARToolKit [6]. As

imagens coloridas capturadas pela câmera são analisadas de forma a segmentar os pixels

escuros relativos a marcadores do fundo da imagem. Uma limiarização mono-nível global é

aplicada à imagem de entrada, com o limiar T sendo especificado pelo usuário. Um valor

comum para T é 150. Considerando um pixel colorido ),,( ppp bgr da imagem de entrada,

se Tbgr ppp 3 , então o pixel é classificado como um pixel de marcador, caso

contrário é classificado como pixel de fundo. A Figura 15 mostra os resultados obtidos pelo

ARToolKit ao limiarizar um quadro de entrada.

Page 19: Reconhecimento de Padrões em Tempo Real Utilizando a

Reconhecimento de padrões em tempo real utilizando a biblioteca OpenCV

RITA Volume XXXX Número X 20XX 19

Figura 15. Limiarização global usada no ARToolKit: imagem colorida de origem (esquerda) e

resultado da limiarização global (direita).

O OpenCV implementa uma limiarização mono-nível e oferece tanto uma limiarização

global como uma local para imagens em tons de cinza. A limiarização global é implementada

pela função cvThreshold, que possui a seguinte assinatura:

void cvThreshold ( const CvArr* src, CvArr* dst,

double threshold, double max_value,

int threshold_type );

O argumento src é a imagem em tons de cinza a ser limiarizada. O argumento dst é

onde a imagem binária resultante será guardada. O limiar global T é especificado pelo

argumento threshold. O argumento max_value é o nível que será usado para distinguir

os pixels do objeto dos pixels do background. O argumento threshold_type determina

qual função será usada na operação de limiarização. Os cinco tipos de limiarização

disponíveis e suas respectivas funções são apresentados na Tabela 3, e sua representação

visual é ilustrada na Figura 16.

Tabela 3. Tipos de limiarização do OpenCV e suas funções.

Tipo de limiarização Função

CV_THRESH_BINARY contrário caso ,0

),( se,max_value),(

thresholdyxsrcyxdst

CV_THRESH_BINARY_INV contrário caso ,max_value

),( se,0),(

thresholdyxsrcyxdst

CV_THRESH_TRUNC contrário caso ),,(

),( se,),(

yxsrc

thresholdyxsrcthresholdyxdst

CV_THRESH_TOZERO contrário caso ,0

),( se),,(),(

thresholdyxsrcyxsrcyxdst

Page 20: Reconhecimento de Padrões em Tempo Real Utilizando a

Reconhecimento de padrões em tempo real utilizando a biblioteca OpenCV

20 RITA Volume XXXX Número X 20XX

CV_THRESH_TOZERO_INV contrário caso ),,(

),( se,0),(

yxsrc

thresholdyxsrcyxdst

Figura 16. Representação visual dos tipos de limiarização do OpenCV.

A limiarização local é implementada pela função cvAdaptiveThreshold, que tem a

seguinte assinatura:

void cvAdaptiveThreshold( const CvArr* src, CvArr* dst,

double max_value,

int adaptive_method,

int threshold_type, int block_size,

double param1 );

Page 21: Reconhecimento de Padrões em Tempo Real Utilizando a

Reconhecimento de padrões em tempo real utilizando a biblioteca OpenCV

RITA Volume XXXX Número X 20XX 21

Os argumentos src, dst, max_value e threshold_type são os mesmos de

cvThreshold. Os únicos tipos de limiarização local disponíveis são

CV_THRESH_BINARY e CV_THRESH_BINARY_INV. O limiar T é computado para cada

pixel da imagem de entrada. O argumento adaptive_method determina como T é

calculado. Se ele é CV_ADAPTIVE_THRESH_MEAN_C, então T é a media da vizinhança

de pixels block_size x block_size subtraída por param1. Se ele é

CV_ADAPTIVE_THRESH_GAUSSIAN_C, então T é a soma ponderada Gaussiana da

vizinhança de pixels block_size x block_size subtraída por param1. Isso significa

que pixels mais próximos terão uma influência maior no resultado do que os mais distantes.

Detecção de linhas. Para detectar linhas retas em uma imagem, o primeiro passo é

realizar uma operação de realce de arestas na imagem de entrada. Daí, um limiar é aplicado

ao resultado. A saída binária desta operação pode ser usada para a detecção de linhas.

Algumas técnicas de rastreamento 3D sem marcadores se baseiam na detecção de

segmentos de linha na imagem Erro! Fonte de referência não encontrada.. Um modelo

aramado do objeto a ser rastreado é projetado na imagem usando uma estimativa de pose da

câmera. A projeção e as linhas da imagem são comparadas para calcular a pose atual da

câmera. A Figura 17 ilustra o processo.

Figura 17. Linhas detectadas na imagem (esquerda) e pose estimada do carro (direita).

O operador usado para realizar detecção de linhas é a transformada de Hough. A idéia por

trás da transformada de Hough é diminuir a complexidade computacional da detecção de

linhas usando uma representação de linhas no espaço de parâmetro ao invés de no plano xy .

Considerando um ponto ),( ii yx no plano xy , existe uma infinidade de linhas que passam

por ele. Essas linhas têm a forma baxy ii . Rearranjando a equação em termos dos

parâmetros a e b , a equação resultante é ii yaxb . Isto é equivalente a uma linha no

espaço de parâmetros. Considerando outro ponto ),( jj yx , o conjunto de linhas que passa

por ele é representado no espaço de parâmetros por jj yaxb . A intersecção das linhas

no espaço de parâmetro no ponto )','( ba determina os parâmetros da linha que passa por

Page 22: Reconhecimento de Padrões em Tempo Real Utilizando a

Reconhecimento de padrões em tempo real utilizando a biblioteca OpenCV

22 RITA Volume XXXX Número X 20XX

ambos os pontos no ),( ii yx e ),( jj yx no plano xy . A Figura 18 mostra gráficos que

ilustram esta idéia.

Figura 18. Representação da linha no plano xy (esquerda) e no espaço de parâmetros (direita).

Na representação usada pelo algoritmo, cada eixo do espaço de parâmetros é subdividido

em intervalos de tamanho igual, como mostra a Figura 19, gerando células chamadas

acumuladores. Cada acumulador ),( ba no espaço de parâmetros representa uma linha no

plano xy .

O primeiro passo do algoritmo é atribuir zero a todos os acumuladores. Depois, a imagem

de entrada é escaneada à procura de pontos de aresta. Para cada ponto ),( ii yx , os

parâmetros ),( ba de todas as linhas que passam por ele são avaliados usando todos os

valores permitidos pela subdivisão da equação yxab . O acumulador correspondente

para cada par de parâmetros é incrementado. Depois que todos os pontos de aresta são

tratados, os valores nos acumuladores serão o número de pontos de aresta contidos na linha

correspondente. Um limiar pode então ser aplicado para selecionar as linhas com o maior

número de pontos.

Page 23: Reconhecimento de Padrões em Tempo Real Utilizando a

Reconhecimento de padrões em tempo real utilizando a biblioteca OpenCV

RITA Volume XXXX Número X 20XX 23

Figura 19. Acumuladores no espaço de parâmetros.

O tempo de execução da transformada de Hough pode ser reduzido sem perda

significativa na qualidade dos resultados usando uma abordagem probabilística [8]. Ao invés

de se utilizar todos os pontos de aresta, apenas uma fração aleatória desses pontos é

considerada.

A detecção de linhas é feita pela função do OpenCV cvHoughLines2:

CvSeq* cvHoughLines2( CvArr* image, void* line_storage,

int method, double rho, double theta,

int threshold, double param1,

double param2 );

O argumento image é a imagem binária de onde as linhas serão adquiridas. O argumento

line_storage é um recipiente para os dados das linhas detectadas. A variante da

transformada de Hough a ser utilizada é especificada pelo argumento method. A Tabela 4

apresenta os métodos da transformada de Hough disponíveis. Os argumentos rho e theta

são a resolução da distância e do ângulo, respectivamente. O argumento threshold

determina o número mínimo de pontos necessários para uma linha. Os argumentos param1

e param2 são apenas usados se method é CV_HOUGH_PROBABILISTIC ou

CV_HOUGH_MULTI_SCALE. Na transformada de Hough probabilística, param1 é o

tamanho mínimo da linha e param2 é a distância máxima entre segmentos pertencentes a

uma mesma linha que não causa sua união. Na transformada de Hough multi-escala,

param1 é o divisor para rho e param2 é o divisor para theta.

Tabela 4. Métodos da transformada de Hough do OpenCV.

Método da transformada de Hough Descrição

CV_HOUGH_STANDARD Transformada de Hough clássica. Retorna

todas as linhas detectadas. Cada linha é

Page 24: Reconhecimento de Padrões em Tempo Real Utilizando a

Reconhecimento de padrões em tempo real utilizando a biblioteca OpenCV

24 RITA Volume XXXX Número X 20XX

representada pela distância para a origem

( ) e pelo ângulo entre o eixo x e a

normal da linha ( )

CV_HOUGH_PROBABILISTIC

Transformada de Hough probabilística.

Retorna todos os segmentos de linha

detectados. Cada segmento é representado

pelos seus pontos de início e fim

CV_HOUGH_MULTI_SCALE

Variante multi-escala da transformada de

Hough clássica. Retorna todas as linhas

detectadas da mesma maneira que CV_HOUGH_STANDARD

Detecção de contornos. Após aplicar um operador de realce de imagens para detecção de

arestas e limiarizar a imagem resultante, os contornos podem ser extraídos a partir da

imagem. Para realizar esta tarefa, dois passos precisam ser contemplados: traçado de

contornos e representação de contornos. No traçado de contornos, os contornos existentes

são seguidos na imagem. Na representação de contornos, os contornos são descritos de uma

forma significativa.

A detecção de contornos é largamente utilizada em soluções de reconhecimento de

padrões em tempo real. No ARToolKit, os contornos relativos aos marcadores presentes no

quadro de entrada precisam ser segmentados para possibilitar o reconhecimento e estimativa

de pose [6]. A Figura 20 ilustra a operação.

Figura 20. Detecção de contornos usada no ARToolKit: imagem colorida de entrada (esquerda), arestas

realçadas (centro) e contornos detectados destacados na imagem (direita).

O OpenCV usa o algoritmo de Suzuki para realizar o traçada de contornos [9]. Nesse

algoritmo, inicialmente o pixel de contorno mais acima e à esquerda é encontrado. Daí, a

vizinhança do primeiro pixel é verificada no sentido horário para encontrar o próximo pixel

do contorno. A partir daí, a busca por outros pixels é feita no sentido anti-horário e termina

quando os primeiros dois pixels do contorno são encontrados novamente.

O OpenCV realiza representação de contornos usando dois tipos diferentes de descrição:

códigos de cadeia e representação poligonal.

Page 25: Reconhecimento de Padrões em Tempo Real Utilizando a

Reconhecimento de padrões em tempo real utilizando a biblioteca OpenCV

RITA Volume XXXX Número X 20XX 25

Códigos de cadeia consistem numa seqüência de números que determinam a vizinhança

de um pixel de contorno onde o próximo pixel de contorno se encontra. A Figura 21 mostra

os códigos para cada vizinhança (esquerda) e um exemplo de um contorno representado por

um código de cadeia (direita). Pode-se notar que escolher um ponto inicial diferente para o

contorno pode gerar diferentes representações de código de cadeia. Isso pode ser evitado

deslocando os números do código de cadeia de forma que resulte no inteiro de magnitude

mínima.

Figura 21. Códigos de cadeia para cada direção de vizinhança (esquerda) e uma representação de

código de cadeia de um contorno (direita).

A representação poligonal é uma seqüência de vértices que quando ligados simbolizam a

essência do contorno. A Figura 22 exemplifica esse tipo de representação, na qual existe um

compromisso entre a fidelidade do contorno e o overhead de codificação.

Figura 22. Representação poligonal.

O OpenCV provê várias maneiras de organizar os contornos obtidos a partir de uma

imagem. Por exemplo, os contornos podem ser guardados em uma árvore, onde um contorno

1C é pai de um contorno 2C se e somente se 1C contém 2C . A Figura 23 mostra como

contornos aninhados podem ser descritos por uma árvore.

Page 26: Reconhecimento de Padrões em Tempo Real Utilizando a

Reconhecimento de padrões em tempo real utilizando a biblioteca OpenCV

26 RITA Volume XXXX Número X 20XX

Figura 23. Representação hierárquica de contornos do OpenCV.

A função usada para extrair contornos de uma imagem binária é chamada

cvFindContours e é definida da seguinte forma:

int cvFindContours( CvArr* image, CvMemStorage* storage,

CvSeq** first_contour, int header_size,

int mode, int method, CvPoint offset);

O argumento image é a imagem binária de onde os contornos serão retornados. O

argumento storage é um recipiente de dados dos contornos. O argumento

first_countour é onde um ponteiro para o primeiro contorno detectado estará

disponível após a chamada da função. O argumento header_size é relativo ao tamanho

da estrutura do contorno. O argumento mode determina como os contornos devem ser

organizados. A Tabela 5 apresenta os modos de retorno dos contornos disponíveis e suas

descrições. O argumento method especifica a representação de contorno a ser usada. A

Tabela 6 descreve os métodos de representação disponíveis. O argumento offset é usado

para deslocar os pontos retornados de uma quantidade explícita de pixels. A função retorna o

número de contornos encontrados na imagem.

Tabela 5. Modos de retorno dos contornos do OpenCV.

Modo de retorno Descrição

CV_RETR_EXTERNAL Retorna apenas os contornos externos

extremos

CV_RETR_LIST Retorna todos os contornos numa lista

CV_RETR_CCOMP

Retorna os componentes conexos de uma

imagem (ver Rotulação de componentes

conexos)

CV_RETR_TREE Retorna todos os contornos

hierarquicamente em uma árvore

Page 27: Reconhecimento de Padrões em Tempo Real Utilizando a

Reconhecimento de padrões em tempo real utilizando a biblioteca OpenCV

RITA Volume XXXX Número X 20XX 27

Tabela 6. Métodos de representação de contornos do OpenCV.

Método de representação Descrição

CV_CHAIN_CODE Representação de código de cadeia

CV_CHAIN_APPROX_NONE

Representação poligonal onde todos os

pixels de contorno são retornados como

vértices

CV_CHAIN_APPROX_SIMPLE

Representação poligonal onde apenas os

pontos extremos de segmentos

horizontais, verticais e diagonais do

contorno são retornados como vértices

CV_CHAIN_APPROX_TC89_L1 e

CV_CHAIN_APPROX_TC89_KCOS

Duas variantes da representação

poligonal de Teh-Chin [10]. Apenas os

pixels de contorno com curvatura alta

são retornados como vértices

CV_LINK_RUNS

Representação poligonal onde apenas os

pontos extremos de segmentos

horizontais de um contorno são

retornados como vértices

Após extrair os contornos de uma imagem, eles podem ser manipulados de forma a obter

informações tais como área e aproximação poligonal. A área do contorno é calculada usando

a função cvContourArea, descrita a seguir:

double cvContourArea( const CvArr* contour, CvSlice slice);

A área do contorno especificado no argumento contour é retornada pela função. Se

apenas uma secção de interesse do contorno tem de ser considerada no cálculo, ela pode ser

determinada usando o argumento slice.

A aproximação poligonal de um contorno é obtida usando a função cvApproxPoly:

CvSeq* cvApproxPoly( const void* src_seq, int header_size,

CvMemStorage* storage, int method,

double parameter, int parameter2);

O argumento src_seq é o contorno a ser aproximado. Os argumentos header_size e

storage têm a mesma finalidade dos de cvFindContours. O único valor aceito

atualmente para o argumento method é CV_POLY_APPROX_DP, que corresponde ao

algoritmo de aproximação poligonal de Douglas-Peucker [11]. O argumento parameter

determina o valor de tolerância a ser usado no algoritmo. O argumento parameter2

especifica se uma organização hierárquica deve ser organizada ou se o contorno é fechado ou

não.

O algoritmo é baseado na distância entre um vértice e um segmento de aresta e em uma

tolerância . Para começar o algoritmo, dois pontos extremos do polígono são conectados.

Essa conexão define a primeira aresta a ser usada. Depois, a distância entre cada vértice

Page 28: Reconhecimento de Padrões em Tempo Real Utilizando a

Reconhecimento de padrões em tempo real utilizando a biblioteca OpenCV

28 RITA Volume XXXX Número X 20XX

remanescente e essa aresta é testada. Se existem distâncias maiores que , então o vértice

com a maior distância da aresta é adicionado à simplificação. O processo continua

recursivamente para cada aresta do passo atual até que todas as distâncias entre os vértices da

linha poligonal original e a simplificação estejam dentro da distância de tolerância. A Figura

24 ilustra o passo-a-passo do algoritmo.

Figura 24. Algoritmo de aproximação poligonal de Douglas-Peucker.

Rotulação de componentes conexos. A rotulação de uma imagem binária diz respeito ao

ato de atribuir um valor único para pixels que pertencem a uma mesma região conexa. Após

limiarizar a imagem de entrada, os pixels vizinhos que pertencem a objetos de interesse são

associados com um rótulo.

O conhecimento dos componentes conexos de uma imagem é bastante útil para o processo

de reconhecimento automatizado. Essa operação é comumente usada em aplicações de

reconhecimento de padrões, em tempo real. A rotulação está presente no pipeline da

biblioteca ARToolKit [6]. Os componentes conexos de uma imagem limiarizada são

Page 29: Reconhecimento de Padrões em Tempo Real Utilizando a

Reconhecimento de padrões em tempo real utilizando a biblioteca OpenCV

RITA Volume XXXX Número X 20XX 29

rotulados para identificar regiões relativas a bordas de marcadores e aos padrões internos,

como pode ser visto na Figura 25.

Figura 25. Rotulação de componentes conexos usada no ARToolKit: imagem limiarizada (esquerda) e

resultados da rotulação (direita).

O princípio do algoritmo de rotulação consiste no escaneamento da imagem binária a

partir do pixel localizado mais acima e à esquerda à procura de pixels de objeto. Para cada

pixel de objeto, os seus pixels vizinhos que já foram escaneados são examinados. Existem

três opções para a rotulação de um pixel:

- Se não existem pixels de objeto entre os pixels examinados, um novo rótulo é criado e

atribuído ao pixel atual;

- Se existe um e apenas um pixel de objeto entre os pixels examinados, o rótulo deste

pixel é atribuído ao pixel atual;

- Se existem mais de um pixel de objeto entre os pixels examinados, um dos rótulos é

atribuído ao pixel atual e uma equivalência entre os diferentes rótulos é criada.

Quando todos os pixels de objeto são rotulados, os rótulos equivalentes são agrupados em

classes de equivalência, cada uma com um rótulo único. A imagem é então escaneada

novamente para resolver as equivalências e definir os componentes conexos.

No OpenCV, a rotulação é realizada usando a função cvFindContours com

CV_RETR_CCOMP setado como o argumento mode. Os componentes conexos são

organizados de uma maneira hierárquica. Os contornos externos dos componentes são

colocados no primeiro nível na árvore. Os contornos dos buracos presentes em um

componente são colocados no segundo nível.

2.3 Rastreamento de objetos

A biblioteca OpenCV possui algumas funções para rastreamento de objetos. Este

tutorial abordará três técnicas possíveis de implementação usando estas funções. Casamento

de Modelos (Template Matching) usa um modelo (template) simples para examinar a

imagem, armazenando os resultados. CamShift é um algoritmo adaptativo que tenta

encontrar um objeto baseado na retroprojeção do seu histograma. Fluxo Óptico (Optical

Flow) usa o fluxo de cada pixel para rastrear o objeto. Outras combinações podem ser

realizadas de forma a alcançar resultados diferentes.

Page 30: Reconhecimento de Padrões em Tempo Real Utilizando a

Reconhecimento de padrões em tempo real utilizando a biblioteca OpenCV

30 RITA Volume XXXX Número X 20XX

Casamento de Modelos. Casamento de Modelos é uma das formas mais simples de

encontrar um objeto em uma imagem. O objetivo desta técnica é examinar todos os pixels de

uma imagem e encontrar todas as instâncias de um objeto específico descrito por um modelo.

Um cenário de uso do Casamento de Modelos para reconhecimento de padrões em

tempo real pode ser encontrado em algumas aplicações de realidade aumentada sem

marcadores, tais como a ilustrada na Figura 26 e descrita em [12]. A diferença entre uma

região da imagem e o modelo de referência é minimizada. Em seguida, os parâmetros de uma

função que mapeia o modelo na imagem alvo são calculados, de forma que o rastreamento

pode ser realizado.

Figura 26. Rastreamento 3D com casamento de modelos – linhas verdes delimitam a imagem do

modelo (esquerda) e cena aumentada (direita).

O OpenCV oferece tal funcionalidade através da função cvMatchTemplate:

void cvMatchTemplate( const CvArr* image, const CvArr* templ,

CvArr* result, int method );

Todos os resultados da comparação são armazenados na variável result, que pode

ser interpretada como uma imagem. A aparência desta imagem estará diretamente

relacionada com o resultado do casamento do modelo com a imagem original: quanto mais

próximo o modelo casado, maior o valor do pixel armazenado, que poderá ser visualizado na

imagem como um pixel claro.

O OpenCV suporta diversos métodos de comparação do modelo com a imagem,

conforme a Tabela 7:

Page 31: Reconhecimento de Padrões em Tempo Real Utilizando a

Reconhecimento de padrões em tempo real utilizando a biblioteca OpenCV

RITA Volume XXXX Número X 20XX 31

Tabela 7. Métodos para Casamento de Modelos

Método Descrição

CV_TM_SQDIFF A diferença quadrada entre o modelo e a

imagem

CV_TM_SQDIFF_NORMED A diferença quadrada normalizada

CV_TM_CCORR A correlação cruzada entre modelo e

imagem

CV_TM_CCORR_NORMED A correlação cruzada normalizada

CV_TM_CCOEFF O coeficiente de correlação

CV_TM_CCOEFF_NORMED O coeficiente de correlação normalizado

A Figura 27 mostra o exemplo de um modelo, e a Figura 28 ilustra os resultados

obtidos pelo casamento deste modelo com uma imagem de entrada.

Figura 27. Modelo utilizado pela técnica Casamento de Modelos.

Figura 28. Um exemplo de uso do Casamento de Modelos. A imagem original (cima) e o modelo

resultante (baixo).

Page 32: Reconhecimento de Padrões em Tempo Real Utilizando a

Reconhecimento de padrões em tempo real utilizando a biblioteca OpenCV

32 RITA Volume XXXX Número X 20XX

CamShift. CamShift remete a “Continuous Adaptive Mean Shift”, ou seja

“Deslocamento Médio Adaptativo Contínuo”, sendo um algoritmo iterativo [13]. Ele utiliza

o algoritmo de deslocamento médio, que iterage para encontrar o centro de um objeto dada a

imagem da distribuição de probabilidade da sua cor 2D. Então, o algoritmo calcula o

tamanho e a orientação do objeto.

O fluxo de funcionamento do algoritmo é mostrado na Figura 29.

Figura 29. Fluxo de funcionamento do CamShift.

O algoritmo CamShift é descrito, passo a passo, abaixo:

1. Configurar a região de cálculo da distribuição de probabilidade para toda a

imagem.

2. Escolher o local inicial da janela de busca do deslocamento médio 2D.

3. Calcular a distribuição de probabilidade da cor na região 2D centralizada na

janela de busca em uma Region of Interest (ROI) um pouco maior que o

tamanho da janela de deslocamento médio.

4. Executar o algoritmo de deslocamento médio [13] para encontrar o centro da

janela de busca. Armazenar o momento (área ou tamanho) e a posição do

centro.

5. Para o próximo frame de vídeo, centralizar a janela de busca na posição média

armazenada no Passo 4 e configurar o tamanho da janela para uma função do

momento anterior encontrado. Ir para o Passo 3.

A função cvCamShift do OpenCV implementa o algoritmo CamShift:

Page 33: Reconhecimento de Padrões em Tempo Real Utilizando a

Reconhecimento de padrões em tempo real utilizando a biblioteca OpenCV

RITA Volume XXXX Número X 20XX 33

int cvCamShift( const CvArr* prob_image, CvRect window,

CvTermCriteria criteria, CvConnectedComp*

comp, CvBox2D* box);

O parâmetro prob_image é a retroprojeção do histograma do objeto, que pode ser

calculada pela função cvCalcBackProject, como mostrado na Figura 30. O parâmetro

window é a janela de busca inicial que o algoritmo utilizará nas iterações. O parâmetro

criteria é usado para informar à aplicação sobre quando ela deve parar a busca. O

usuário pode especificar se o critério é o número de iterações ou um limiar épsilon que

define a similaridade das janelas. O parâmetro comp remete a “Componente Conectado”,

que contém informações sobre a convergência da janela de busca. As coordenadas da janela

podem ser recuperadas chamando comp->rect e a soma de todos os pixels dentro da

janela pode ser obtida pelo campo comp->area. O parâmetro box contém o tamanho e a

orientação do objeto no final da execução do algoritmo. A Figura 31 ilustra um exemplo de

rastreamento de face usando CamShift.

Figura 30. Exemplo da retroprojeção do histograma.

Figura 31. Exemplo de rastreamento com o CamShift.

Page 34: Reconhecimento de Padrões em Tempo Real Utilizando a

Reconhecimento de padrões em tempo real utilizando a biblioteca OpenCV

34 RITA Volume XXXX Número X 20XX

Fluxo Óptico. Fluxo Óptico é a técnica que mede a velocidade dos pixels de uma

imagem comparando os mesmos com o frame anterior. O deslocamento destes pixels ao

longo do tempo pode ser usado para estimar o movimento da câmera em aplicações como a

ilustrada na Figura 32, que rastreia faces em 3D [14].

Figura 32. Fluxo Óptico usado para rastreamento 3D.

Existem vários algoritmos que implementam Fluxo Óptico, e o OpenCV oferece

quatro deles. Estas implementações são explicadas na seqüência.

Técnica Lucas & Kanade. A tarefa de medir o fluxo óptico é reduzida a um sistema

linear aplicando a equação do fluxo óptico a um grupo de pixels adjacentes e assumindo que

todos eles têm a mesma velocidade [15]. Esta técnica é rápida o suficiente para ser usada em

tempo real porque não processa a imagem toda. A função do OpenCV que implementa esta

técnica é a cvCalcOpticalFlowLK, que é usada em um exemplo descrito na Seção 3.

void cvCalcOpticalFlowLK( const CvArr* prev, const CvArr*

curr, CvSize win_size, CvArr* velx,

CvArr* vely );

Os argumentos prev e curr são os dois frames adjacentes temporários da imagem

usados para calcular a velocidade. O parâmetro win_size é a janela média que funcionará

como base para toda a imagem. Os parâmetros velx e vely são, respectivamente, os

componentes horizontal e vertical do fluxo óptico para cada pixel. Eles têm o mesmo

tamanho das imagens de entrada.

O OpenCV também implementa uma abordagem piramidal do algoritmo Lucas &

Kanade [16]. O algoritmo de rastreamento piramidal procede da seguinte forma.

Primeiramente, o fluxo óptico é calculado em um nível de maior profundidade da pirâmide

mL . Então, o resultado deste cálculo é propagado até o nível mais alto para se obter um valor

inicial (uma tentativa) para o deslocamento dos pixels. Dado este valor inicial, o fluxo óptico

refinado é calculado no nível 0 (a imagem original). A função

cvCalcOpticalFlowPyrLK do OpenCV implementa este algoritmo.

void cvCalcOpticalFlowPyrLK( const CvArr* prev, const CvArr*

Page 35: Reconhecimento de Padrões em Tempo Real Utilizando a

Reconhecimento de padrões em tempo real utilizando a biblioteca OpenCV

RITA Volume XXXX Número X 20XX 35

curr, CvArr* prev_pyr, CvArr*

curr_pyr, const CvPoint2D32f*

prev_features, CvPoint2D32f*

curr_features, int count, CvSize

win_size, int level, char*

status, float* track_error,

CvTermCriteria criteria, int

flags );

Os argumentos prev_pyr e curr_pyr são buffers usados pelo algoritmo para

armazenar as imagens parciais. Os argumentos prev_features e curr_features são

os arrays de pontos a serem rastreados. O primeiro buffer contém os pontos e o segundo

buffer armazenará as novas posições encontradas. O argumento count define o número de

pontos a serem rastreados. O parâmetro win_size define o tamanho da janela de busca

para cada pirâmide, e level o nível piramidal máximo. O parâmetro status é um array

que contém 1 se a característica (feature) foi rastreada com sucesso e o fluxo foi calculado, e

0 em caso contrário. O argumento track_error é um parâmetro opcional que contém

diferenças entre patches ao redor dos pontos originais e deslocados. O parâmetro flags

pode ser configurado para salvar algum tempo de processamento, uma vez que é possível

assumir que um buffer de uma determinada pirâmide já foi calculado. As flags disponíveis

são listadas na Tabela 8.

Tabela 8. Flags do Fluxo Óptico Piramidal

Flag Descrição

CV_LKFLOW_PYR_A_READY A pirâmide para o primeiro frame é pré-

calculada antes da chamada

CV_LKFLOW_PYR_B_READY A pirâmide para o segundo frame é pré-

calculada antes da chamada

CV_LKFLOW_INITIAL_GUESSES

O array curr_features contém as

coordenadas iniciais das características

antes da chamada da função

Técnica Horn & Schunck. Esta função encontra o padrão do fluxo óptico, assumindo

que a velocidade aparente do padrão de brilho varia suavemente, praticamente em toda a

imagem [17].

A técnica de Fluxo Óptico Horn & Schunck é implementada no OpenCV através da

função cvCalcOpticalFlowHS:

void cvCalcOpticalFlowHS( const CvArr* prev, const CvArr*

curr, int use_previous, CvArr* velx,

CvArr* vely, double lambda,

CvTermCriteria criteria );

Page 36: Reconhecimento de Padrões em Tempo Real Utilizando a

Reconhecimento de padrões em tempo real utilizando a biblioteca OpenCV

36 RITA Volume XXXX Número X 20XX

O parâmetro use_previous denota usar ou não o cálculo do campo de velocidade

prévia. O campo lambda é chamado multiplicador Lagrangiano (Lagrangian multiplier).

Ele deve ser menor para imagens com ruído e maior para imagens limpas e precisas.

Técnica de Casamento de Blocos (Block Matching). Esta técnica não utiliza

diretamente uma equação de fluxo óptico. Ao invés disso, ela usa uma técnica que lembra

casamento de padrões. Ela usa uma caixa definida dentro da primeira imagem e tenta

encontrar outra caixa de mesmo tamanho na segunda imagem, que seja similar a primeira.

Este algoritmo apresenta um resultado aproximado quando comparado às outras técnicas.

A função cvCalcOpticalFlowBM no OpenCV implementa esta técnica:

void cvCalcOpticalFlowBM( const CvArr* prev, const CvArr*

curr, CvSize block_size, CvSize

shift_size, CvSize max_range, int

use_previous, CvArr* velx, CvArr*

vely );

Os parâmetros block_size e shift_size definem as características do bloco

utilizado. O parâmetro max_range representa o tamanho dos pixels vizinhos ao redor do

bloco que serão examinados.

2.4 Detecção de objetos

A biblioteca OpenCV fornece a funcionalidade de detecção de objetos. Ela usa um

classificador, proposto por Paul Viola [18] e Rainer Lienhart [19], que identifica vários

objetos diferentes.

O processo inicia selecionando algumas centenas de amostras de visões do objeto

desejado, em diversos ângulos e sob diversas condições de iluminação. Este conjunto de

imagens é chamado de amostras positivas. Então, outro conjunto de imagens é escolhido,

contendo imagens arbitrárias não incluindo o objeto desejado. Este conjunto é chamado de

amostras negativas.

Em seguida, ambos os conjuntos são usados para treinar uma cascata de

classificadores ditos “boosted”. A palavra “cascata” no nome do classificador significa que o

classificador resultante consiste de diversos classificadores mais simples que são aplicados

subseqüentemente a uma ROI, até que em alguma etapa o candidato é rejeitado ou todas as

etapas são superadas. A palavra “boosted” significa que os classificadores, a cada etapa da

cascata, são complexos por si só e são formados por classificadores básicos usando uma

entre quatro técnicas de boosting diferentes (voto ponderado). Atualmente, as técnicas

Discrete Adaboost, Real Adaboost, Gentle Adaboost e Logitboost são suportadas [20].

Após o classificador ser treinado, pode ser usado para detectar o objeto em uma ROI.

O classificador é projetado de forma a, redimensionando a ROI, detectar objetos de tamanhos

diferentes.

Page 37: Reconhecimento de Padrões em Tempo Real Utilizando a

Reconhecimento de padrões em tempo real utilizando a biblioteca OpenCV

RITA Volume XXXX Número X 20XX 37

O OpenCV fornece um projeto completo para detecção de faces, que será detalhado

na Seção 3, implementando o classificador em cascata descrito anteriormente. Este projeto

pode ser facilmente adaptado para qualquer objeto, uma vez que um novo conjunto de

imagens pode ser usado na etapa de treinamento sem modificar muito o código. A Figura 33

mostra uma aplicação de detecção de objetos [21].

Figura 33. Exemplo de detecção de componentes de uma placa mãe.

O OpenCV disponibiliza algumas funções importantes que merecem um

detalhamento para melhor entendimento do conteúdo. A função cvLoad do OpenCV é

usada para importar o arquivo XML gerado durante a etapa de treinamento:

void* cvLoad( const char* filename, CvMemStorage* memstorage,

const char* name, const char** real_name);

O único parâmetro que precisa ser passado para esta função quando carregando uma

cascata é o filename, que deve conter o endereço do arquivo XML.

A função cvHaarDetectObjects retorna uma seqüência de quadrados para cada

objeto detectado:

CvSeq* cvHaarDetectObjects( const CvArr* image,

CvHaarClassifierCascade* cascade,

CvMemStorage* storage,

double scale_factor,

int min_neighbors, int flags,

CvSize min_size);

Page 38: Reconhecimento de Padrões em Tempo Real Utilizando a

Reconhecimento de padrões em tempo real utilizando a biblioteca OpenCV

38 RITA Volume XXXX Número X 20XX

O parâmetro image representa a imagem onde os objetos devem ser detectados. A

saída da função cvLoad deve ser passada no parâmetro cascade. Durante a busca,

potenciais retângulos candidatos são armazenados no parâmetro storage. O

scale_factor é o fator de escala aplicado na janela de busca a cada subexame. O

parâmetro min_neighbors funciona agrupando retângulos vizinhos. A única flag

atualmente suportada pelo parâmetro flags é CV_HAAR_DO_CANNY_PRUNNING, que

usa o detector de arestas Canny para rejeitar algumas regiões da imagem que não contém o

objeto procurado. min_size define o tamanho mínimo da janela de detecção.

3 Aplicações de exemplo

A Intel também disponibiliza no pacote padrão do OpenCV alguns exemplos de

código. No subdiretório “samples”, localizado no diretório de instalação, tem códigos fonte

que podem auxiliar um usuário iniciante do OpenCV. Entre estes arquivos, alguns exemplos

merecem um detalhamento maior, levando em consideração sua relevância para detecção de

padrões e o uso de conceitos apresentados previamente neste tutorial. Estes exemplos serão

descritos na seqüência.

3.1 Detecção de quadrados

O exemplo da detecção de quadrados visa encontrar e destacar os quadrados contidos

nas imagens carregadas. Para encontrar os quadrados, o exemplo implementa uma função

que retorna uma seqüência contendo os vértices dos quadrados detectados.

Primeiramente, a seqüência que será usada para guardar o resultado é criada, tornando

possível qualquer futura adição de vértices. Em seguida, alguns filtros são aplicados para

destacar arestas, considerando vários limiares. A cada limiar, a função cvFindContours

separará cada contorno e armazenará os mesmos em um objeto de seqüência. Para cada

contorno, a função cvApproxPoly calcula um polígono aproximado baseado no resultado

de cvFindContours. Se algumas condições forem satisfeitas (tais como ter quatro

vértices e um contorno convexo), o polígono detectado é um retângulo. A Figura 34 ilustra

dois exemplos com os quadrados destacados pelo exemplo.

Page 39: Reconhecimento de Padrões em Tempo Real Utilizando a

Reconhecimento de padrões em tempo real utilizando a biblioteca OpenCV

RITA Volume XXXX Número X 20XX 39

Figura 34. Exemplo de detecção de quadrados.

3.2 Demo do CamShift

Este exemplo mostra como aplicar a cvCamShift para detectar um padrão em uma

imagem capturada por uma webcam, baseado na informação fornecida por um histograma. O

histograma contém a informação da cor de um padrão, e este demo usa o mesmo para

encontrar uma área na imagem que casa com os dados do histograma.

Para tornar o rastreamento possível, o usuário precisa fornecer como entrada para a

aplicação uma subárea do frame capturado. Esta área é tomada como base para calcular um

histograma de matizes, que servirá como padrão para vasculhar todo o frame procurando por

uma combinação correspondente. Um exemplo de histograma pode ser visto na Figura 35.

Este histograma funciona como uma identidade da cor.

Figura 35. Histograma de matizes da face detectada na Figura 36.

As funções usadas para criar e calcular o histograma são, respectivamente,

cvCreateHist e cvCalcHist.

Para encontrar o padrão em um frame deve-se calcular a retroprojeção do plano de

matizes, usando o histograma. A retroprojeção é uma imagem onde cada posição tem uma

Page 40: Reconhecimento de Padrões em Tempo Real Utilizando a

Reconhecimento de padrões em tempo real utilizando a biblioteca OpenCV

40 RITA Volume XXXX Número X 20XX

probabilidade de compor um objeto tal qual o objeto rastreado. Para calcular a imagem

equivalente à retroprojeção da imagem, baseado em um histograma, o usuário precisa

chamar cvCalcBackProjection. O resultado da retroprojeção é ilustrado na Figura 36

(direita). Dado o resultado da retroprojeção, o algoritmo CamShift é aplicado para retornar a

“caixa de rastreamento”, que conterá o retângulo orientado que envolve a área casada. O

algoritmo CamShift é implementado pela função cvCamShift. Um exemplo do CamShift

sendo aplicado a uma face pode ser visto na Figura 36 (esquerda). O algoritmo visa buscar a

maior área com vizinhos conectados, tendo uma alta probabilidade de fazer parte da solução.

Figura 36. CamShift detectando uma face (esquerda) e retroprojeção da imagem (direita).

3.3 O rastreador Kanade Lucas

O Kanade Lucas é um rastreador (tracker) de características (features) popular,

implementado utilizando uma abordagem piramidal que usa fluxo óptico para calcular as

novas posições das características selecionadas. Uma característica pode ser explicada como

um ponto em uma cena praticamente rígida que pode ser casado com outro ponto no próximo

frame, mantendo o valor semântico de estar no mesmo ponto 3D da cena real.

Para gerar algumas características para popular a aplicação e testar o comportamento

do rastreador, uma função chamada cvGoodFeaturesToTrack pode ser usada. Esta

função seleciona os cantos mais fortes na imagem para ser as características que serão

rastreadas pela aplicação. Para refinar a posição dos cantos selecionados,

cvFindCornersSubPix pode ser usada adicionalmente à função apropriada. Um

resultado desta função pode ser visto na Figura 37.

Page 41: Reconhecimento de Padrões em Tempo Real Utilizando a

Reconhecimento de padrões em tempo real utilizando a biblioteca OpenCV

RITA Volume XXXX Número X 20XX 41

Figura 37. Um frame mostrando as “boas características para rastrear”.

No laço principal, o programa testa se o usuário adicionou manualmente uma nova

característica e também refina a posição deste ponto para casar com o canto mais próximo na

imagem. Isto é necessário porque cantos são mais fáceis de rastrear e calcular o fluxo óptico.

Para calcular a próxima posição das características mostradas no último frame, a

função cvCalcOpticalFlowPyrLK é usada. Esta função implementa o rastreador

Kanade Lucas e precisa de algumas imagens temporárias para aplicar a abordagem

piramidal. Elas atuam como imagens subamostradas que ajudam o algoritmo a rastrear fluxos

ópticos, com movimentos grandes. O resultado desta função é a nova posição dos pontos

fornecidos como parâmetros.

3.4 Detecção de faces

O exemplo de detecção de faces usa o classificador Haar para reconhecer um padrão

de face. O exemplo carrega um classificador Haar pré-treinado e usa o mesmo para detectar

os objetos no frame atual. O classificador Haar usado neste exemplo é o

HaarClassifierCascade, que difere de outros classificadores por usar em cascata múltiplos

classificadores Haar.

Para carregar o classificador o exemplo usa a função cvLoad e o resultado é definido

como sendo do tipo cvHaarClassifierCascade. Este classificador será usado como parâmetro

da função cvHaarDetectObjects. Com esta função, o usuário pode encontrar todas as

regiões que casam com os objetos que a cascata foi treinada. Como valor de retorno a função

cvHaarDetectObjects fornece uma seqüência de retângulos contendo os objetos

casados. Uma instanciação em tempo de execução da detecção de faces é mostrada na Figura

38.

Page 42: Reconhecimento de Padrões em Tempo Real Utilizando a

Reconhecimento de padrões em tempo real utilizando a biblioteca OpenCV

42 RITA Volume XXXX Número X 20XX

Figura 38. Classificador Haar detectando faces.

4 Considerações finais

Este tutorial apresentou o OpenCV, composto por uma grande quantidade de funções

relacionadas com reconhecimento de padrões. Estas funções são básicas para qualquer

projeto de processamento de imagens que visa detectar um padrão específico ou genérico. As

funções básicas do OpenCV para detecção de padrões são fáceis de usar e seguem uma

estrutura padronizada, compartilhando parâmetros comuns fornecidos pela biblioteca.

Além da simplicidade do framework, o OpenCV traz uma biblioteca para

desenvolvimento de interfaces, que agiliza o período de prototipação de um teste ou

aplicação usando o OpenCV. Esta biblioteca é chamada HighGUI e um exemplo de código é

mostrado no Apêndice, em anexo.

Referências

[1]. J. Shi e C. Tomasi, “Good Features to Track,” Proceedings of the IEEE Conference on

Computer Vision and Pattern Recognition, Washington DC, EUA, 1994.

[2]. C. Tomasi e R. Manduchi. “Bilateral Filtering for Gray and Color Images”,

Proceedings of the International Conference on Computer Vision, Bombay, India, 1998.

[3]. C. Harris. “Tracking with Rigid Objects”. MIT Press, 1992.

[4]. H. Scharr. “Digitale Bildverarbeitung und Papier: Texturanalyse mittels Pyramiden und

Grauwertstatistiken am Beispiel der Papierformation”. Diplomarbeit, Fakultät für Physik

und Astronomie, Ruprecht-Karls-Universität Heidelberg, 1996.

Page 43: Reconhecimento de Padrões em Tempo Real Utilizando a

Reconhecimento de padrões em tempo real utilizando a biblioteca OpenCV

RITA Volume XXXX Número X 20XX 43

[5]. M. Uenohara e T. Kanade. “Vision-Based Object Registration for Real-Time Image

Overlay”. Journal of Cognitive Neuroscience 3, 71–86, 1991.

[6]. H. Kato e M. Billinghurst. “Marker Tracking and HMD Calibration for a Video-Based

Augmented Reality Conferencing System”, Proceedings of the Workshop on Augmented

Reality, San Francisco, EUA, 1999.

[7]. D. Koller, K. Daniilidis e H. Nagel. “Model-Based Object Tracking in Monocular

Image Sequences of Road Traffic Scenes”. International Journal of Computer Vision

10, 257–281, 1993.

[8]. J. Matas, C. Galambos e J. Kittler. “Progressive Probabilistic Hough Transform”,

Proceedings of the British Machine Vision Conference, Southampton, UK, 1998.

[9]. S. Suzuki e K. Abe. “Topological Structural Analysis of Digital Binary Images by

Border Following”. Graphical Model and Image Processing 30, 32-46, 1985.

[10]. C. The e R. Chin. “On the Detection of Dominant Points on Digital Curves”. IEEE

Transactions on Pattern Analysis and Machine Learning 11, 859-872, 1989.

[11]. D. Douglas e T. Peucker. "Algorithms for the Reduction of the Number of Points

Required to Represent a Digitized Line or its Caricature". The Canadian Cartographer

10, 112-122, 1973.

[12]. Lepetit, V., Lagger, P. e Fua, P. “Randomized Trees for Real-Time Keypoint

Recognition”, Conference on Computer Vision and Pattern Recognition, 2005.

[13]. Bradski, G. “Computer Vision Face Tracking as a Component of a Perceptual User

Interface”, Workshop on Applications of Computer Vision, 1998.

[14]. Basu, S., Essa, I. e Pentland, A. “Motion Regularization for Model-Based Head

Tracking”, International Conference on Pattern Recognition, 1996.

[15]. Lucas, B. e Kanade, T. “An Iterative Image Registration Technique with an Application

to Stereo Vision”, International Joint Conference on Artificial Intelligence, 1981.

[16]. Bouguet, J.-Y. “Pyramidal Implementation of the Lucas Kanade Feature Tracker”, parte

da documentação do OpenCV.

[17]. Horn, B. e Schunck, B. “Determining Optical Flow”. Artificial Intelligence, 17, 185-

203, 1981.

[18]. Viola, P. e Jones, M. “Rapid Object Detection using a Boosted Cascade of Simple

Features”, Conference on Computer Vision and Pattern Recognition, 2001.

[19]. Lienhart, R. e Maydt, J. “An Extended Set of Haar-like Features for Rapid Object

Detection”, International Conference on Image Processing, 2002.

[20]. Freund, Y. e Schapire, R. “A Short Introduction to Boosting”, Journal of Japanese

Society for Artificial Intelligence, 14, 771-780, 1999.

Page 44: Reconhecimento de Padrões em Tempo Real Utilizando a

Reconhecimento de padrões em tempo real utilizando a biblioteca OpenCV

44 RITA Volume XXXX Número X 20XX

[21]. Teixeira, J. M., Silva, D., Moura, G., Costa, L. H., Teichrieb, V. e Kelner, J. “miva:

Constructing a Wearable Platform Prototype”, Symposium on Virtual and Augmented

Reality, 2007.

Apêndice

Este apêndice descreve como construir uma interface simples para testar ou prototipar

algumas funcionalidades do OpenCV, usando o framework HighGUI.

O framework HighGUI é disponibilizado com a distribuição padrão do OpenCV e

visa simplificar tarefas básicas, tais como criar e manipular janelas, exibir imagens em

janelas, criar controles para ajustar parâmetros de aplicações e outras funções para manipular

imagens, vídeos e captura de câmera. Funcionalidades como escutar eventos de mouse

também são gerenciadas pelo framework HighGUI.

O trecho de código abaixo mostra o vídeo capturado por uma câmera e implementa

uma função básica que escuta os eventos do mouse.

#include "cv.h"

#include "highgui.h"

#ifdef _EiC

#define WIN32

#endif

//escuta os eventos do mouse

void on_mouse(int event, int x, int y, int flags, void* param)

{

//testar todos os eventos possiveis

switch(event)

{

case CV_EVENT_LBUTTONDOWN:

break;

case CV_EVENT_RBUTTONDOWN:

break;

case CV_EVENT_MBUTTONDOWN:

break;

case CV_EVENT_LBUTTONUP:

break;

case CV_EVENT_RBUTTONUP:

break;

case CV_EVENT_MBUTTONUP:

break;

case CV_EVENT_LBUTTONDBLCLK:

Page 45: Reconhecimento de Padrões em Tempo Real Utilizando a

Reconhecimento de padrões em tempo real utilizando a biblioteca OpenCV

RITA Volume XXXX Número X 20XX 45

break;

case CV_EVENT_RBUTTONDBLCLK:

break;

case CV_EVENT_MBUTTONDBLCLK:

break;

default: //CV_EVENT_MOUSEMOVE

}

}

int main( int argc, char** argv )

{

int c = 0;

//Objeto capture usado para captura de video

CvCapture* capture = 0;

//Imagens usadas como buffers na captura de video

IplImage *frame, *frame_copy = 0;

//Captura da camera padrao

capture = cvCaptureFromCAM(-1);

//Cria uma janela chamada "result"

cvNamedWindow( "result", 1 );

//Configura o callback do mouse como sendo a funcao

//descrita antes da main

cvSetMouseCallback( "result", on_mouse, 0 );

if( capture )

{

//laco de captura

for(;;)

{

if( !cvGrabFrame( capture ))

break;

frame = cvRetrieveFrame( capture );

if( !frame )

break;

if( !frame_copy )

frame_copy = cvCreateImage(

cvSize(frame->width,frame->height),

IPL_DEPTH_8U, frame->nChannels );

if( frame->origin == IPL_ORIGIN_TL )

cvCopy( frame, frame_copy, 0 );

else

Page 46: Reconhecimento de Padrões em Tempo Real Utilizando a

Reconhecimento de padrões em tempo real utilizando a biblioteca OpenCV

46 RITA Volume XXXX Número X 20XX

cvFlip( frame, frame_copy, 0 );

//Exibe o frame na janela

cvShowImage( "result", frame_copy );

//Testa se o usuario pressionou a tecla ESC

c = cvWaitKey(10);

if( (char)c == 27 )

break;

}

cvReleaseImage( &frame_copy );

cvReleaseCapture( &capture );

}

cvDestroyWindow("result");

return 0;

}