implementação de métodos e classes de - Biblioteca

Propaganda
IMPLEMENTAÇÃO DE MÉTODOS E CLASSES DE PROCESSAMENTO DE
IMAGENS PARA SISTEMA DE NAVEGAÇÃO ROBÓTICA
Rafael A. B. Barros
ITA – Divisão de Ciência da Computação
Praça Mal. Eduardo Gomes, 50
12228-900 São José dos Campos – SP
[email protected]
Carlos H. C. Ribeiro
ITA – Divisão de Ciência da Computação
Praça Mal. Eduardo Gomes, 50
12228-900 São José dos Campos – SP
[email protected]
RESUMO: O projeto consiste na implementação, em uma plataforma Java, de técnicas de detecção
de guias de calçadas para a utilização em robótica móvel A plataforma realiza filtragem de
imagens e processamento baseado em transformada de Hough, também sendo feito um controle de
erros usando o filtro de Kalman. Este artigo detalha a arquitetura de software desenvolvida para a
implementação do sistema de detecção de guias.
ABSTRACT: This project consists in the implementation, in a Java platform, of techniques for
sidewalk detection for posterior use in mobile robotics. The platform filters images and performs
processing based on the Hough Transform, and error control using the Kalman filter. This paper
details the software architecture developed for implementation of this sidewalk detection system.
1. INTRODUÇÃO
Esse projeto consiste em implementar métodos de localização e posicionamento simples
para um robô móvel que possui como sensor de visão uma câmera de baixo custo (webcam). O
algoritmo resultante deve ser pouco sensível a erros e suportar a baixa resolução das imagens
obtidas.
O projeto conta com duas fases: a implementação do algoritmo em Matlab, para a
realização de testes iniciais, e a implementação final em Java, utilizando-se de duas bibliotecas
adicionais, Java Advanced Imaging e Java Multimedia Framework [1][2] para o funcionamento
definitivo.
A plataforma deve retornar com sucesso as coordenadas em parametrização circular da reta
que melhor define a guia de calçada que o robô utilizará para se localizar.
Também é objetivo desse projeto que o algoritmo funcione em um tempo razoável, já que
uma demora excessiva na obtenção dos resultados pode retardar o movimento do robô,
prejudicando desta forma a eficiência do mesmo.
A implementação em Matlab não será discutida aqui. Maiores informações poderão ser
encontradas em [3] e [4]. Apenas conceitos básicos para o entendimento dos algoritmos utilizados
serão apresentados, e detalharemos a descrição da implementação em Java, além de uma breve
descrição dos resultados.
2. CONCEITOS
2.1 Imagens e sua Obtenção
A plataforma em Java obtém a imagem como uma matriz de pixels, definida por três
valores correspondentes às componentes vermelho, azul e verde da imagem. A imagem é
armazenada em um objeto Java chamado bufferedImage, que por sua vez é composto de um Raster
(referente à matriz de pixels) e um modelo de cores (ColorModel), que registra a forma como as três
componentes de cor distribuem-se pela imagem.
Como uma bufferedImage é na verdade uma matriz de pixels, os algoritmos utilizados para
manipular a imagem e a partir dela obter quaisquer informações necessárias são algoritmos que
basicamente manipulam matrizes fazendo a análise direta dos valores nelas contidos e da forma
como esses valores relacionam-se entre si.
2.2 Transformadas e Filtros
Os filtros são modos de se manipular as matrizes de pixels de modo a obterem-se
informações desejadas ou eliminar aquelas que prejudicariam o correto funcionamento da aplicação.
Os filtros se baseiam em uma matriz de convolução, que é uma matriz responsável por
definir, para cada elemento, como este se relaciona com os seus vizinhos. O valor de cada pixel da
imagem obtida após a filtragem será determinado, então, como resultado das operações definidas
pela matriz de convolução para os elementos correspondentes da matriz original.
A transformada de Hough [5] foi um algoritmo desenvolvido por Paul Hough em 1962 e
patenteado pela IBM. É um algoritmo de ordem O(n4) que transforma uma imagem
convenientemente filtrada numa curva paramétrica, e obtém desta curva pontos que representam
linhas retas na imagem original.
A transformada de Hough é um algoritmo adequado para a detecção de retas, porém em
imagens muito ruidosas pode cometer erros. Desse modo, é interessante a determinação de alguma
forma de eliminar eventuais erros de modo a fornecer um funcionamento consistente para o robô, e
nestas ocasiões pode ser conveniente estabelecer o posicionamento das retas na imagem com base
em uma estimação baseada no filtro de Kalman [6].
3. ARQUITETURA DE SOFTWARE: METODOLOGIA
A plataforma Java é constituída por um conjunto de classes, cada uma definindo operações
ou objetos que são de evidência na aplicação do algoritmo. Um esquema geral de classes definidas e
relações existentes entre elas é mostrado na Figura 1. As setas indicam o relacionamento entre os
diversos objetos, no que tange ao fluxo de informações.
Figura 1 – Esquema geral de classes
As classes estão divididas da seguinte forma: quatro delas definem a construção da interface
gráfica (Direita, Principal, Origem e Resultados). Duas delas referem-se à captação de imagens da
câmera (FrameGrabber e FrameGrabberException). Três contém métodos para as operações a
serem realizadas nas Imagens (Kalman_2D, Hough e Filtros). Finalmente, a última, Comando e
Matriz são classes de armazenamento de dados, utilizadas como auxiliares.
3.1 Interface Gráfica
Embora a interface gráfica definida não seja utilizada no funcionamento do robô em si, ela é
interessante na fase de testes. Por isso, foi incluída na especificação do projeto de modo a permitir
manejar com facilidade os parâmetros dos filtros e algoritmos utilizados na plataforma.
O modelo de interface gráfica escolhido foi de um frame onde podem ser anexados um ou
mais painéis (Figura 2). Esses painéis também podem ser arrastados de modo a ajustar-se à
visualização de acordo com o objetivo pretendido. Eles também possuem cada um uma caixa de
texto, onde os comandos inseridos são interpretados e encaminhados para execução, sendo
atualizados na próxima iteração do algoritmo.
Figura 2 – Janela Principal
São descritos a seguir cada classe constituinte da interface gráfica.
3.1.1 Principal
A Classe principal é constituída de um JFrame que define uma barra de menu e no mínimo
duas janelas que servem para controle de testes da interface gráfica. Seu funcionamento consiste em
dois threads que fazem o controle geral do programa e sincronizam a amostragem de imagens na
tela.
A grande funcionalidade dessa interface é a possibilidade de se anexar várias janelas
Resultados, obtendo dessa forma resultados de diferentes testes simultaneamente.
3.1.2 Original
A Classe Original é um JPanel que conterá a imagem diretamente obtida da câmera. Ela
também possui um pequeno espaço onde o usuário pode inserir os comandos referentes aos filtros
que ele quer visualizar aplicados à imagem. Um detalhe importante: os filtros inseridos aqui farão o
processamento em uma outra janela resultados, de modo que se a primeira não for fechada, ambos
os processos ocorrerão paralelamente.
A maior funcionalidade desse fato é que podemos observar a detecção de quantos filtros a
resolução do monitor permitir ocorrendo simultaneamente, o que pode ser útil para determinar se tal
filtro fornece ou não um resultado mais preciso do que outro. Ela difere da classe Resultados, a ser
descrita em seguida, pelo fato de alterações nos comandos necessitarem de uma outra janela para a
exibição dos resultados em si, enquanto que na classe Resultados todas as alterações são
processadas automaticamente.
3.1.3 Resultados
A Classe Resultados é um container que conterá dois JPanels. O primeiro contém a mesma caixa
de inserção de comandos existente na janela Original, porém qualquer modificação nessa caixa,
além de fazer com que o efeito seja imediato, apareça na mesma janela Resultados onde o texto está
sendo digitado. O Segundo JPanel define uma área onde será anexado o objeto referente à classe
Direita, a ser explicada adiante.
3.1.4 Direita
A Classe Direita estende JPanel, sendo um painel onde serão exibidas as imagens referentes
ao vetor construído baseado nos filtros, colocados na caixa de texto tanto na classe Resultados como
na Original.
3.2 Comando
A Classe comando é uma classe auxiliar para armazenamento de informações. Ela guarda
os resultados de uma tokenização dos Strings pertencentes à JTextArea presentes nas janelas
Original e Resultados.
Após esse processo, os diversos objetos instanciados desta classe podem ser utilizados para
a chamada dos comandos respectivos.
3.3 Matriz
A classe Matriz é também uma classe de Armazenamento, utilizada pela classe
Kalman_2D, e determina operações usuais de matrizes, como por exemplo, o cálculo da inversa.
Essa classe foi definida pelo fato da Transformada de Kalman ter a necessidade do cálculo
de muitas operações envolvendo matrizes, fazendo com que a definição de uma matriz como objeto
tornasse o projeto da classe responsável pela transformada de Kalman bem mais simples.
3.4 FrameGrabber
FrameGrabber é um pacote de classes fornecido pela Sun Microsystems que permite a
obtenção de imagens diretamente de uma câmera. Ela é constituída de duas classes: FrameGrabber
e FrameGrabberException.
A classe faz a conexão com dispositivo de captura com o mesmo nome fornecido em um
arquivo vídeo.properties, podendo disparar uma FrameGrabberException. A partir daí o programa
tenta determinar o formato com que as informações obtidas pela câmera serão repassadas ao
programa, e então determina um processador de dispositivo, que ficará responsável por fazer a
coleta de dados. Finalmente, as informações obtidas são guardadas em um buffer. A Classe possui
então um método getImage, que acessa esse buffer e recupera a imagem que está instantaneamente
armazenada, retornando-a para o método que acessou esta classe.
3.5 Filtros
A classe filtros possui os métodos de operação dos principais filtros utilizados que foram
julgados de interesse para o projeto.
A maioria dos filtros inseridos nessa classe possui uma matriz de convolução padrão.
Alguns poucos, porém, possuem um método mais arrojado de processamento. Para inserir novos
filtros nessa classe, basta então definir a matriz de convolução do filtro em questão, e inserir o filtro
usando o método filtros.put().
A descrição resumida de cada filtro atualmente definido na classe segue abaixo:
ƒ edge: ressalta os cantos e pontos com grande diferença dos pontos vizinhos na imagem.
ƒ edge5: ressalta os cantos e pontos com grande diferença dos pontos vizinhos na imagem,
agora vizinhos mais distantes.
ƒ sobel0: obtém a aproximação de Sobel para a derivada, tomando a direção de 0º.
ƒ sobel90: obtém a aproximação de Sobel para a derivada, tomando a direção de 90º.
ƒ sobel180: obtém a aproximação de Sobel para a derivada, tomando a direção de 180º.
ƒ sobel270: obtém a aproximação de Sobel para a derivada, tomando a direção de 270º.
ƒ gaussiana3: aplicada o filtro gaussiano na imagem, tornando-a menos acidentada. Esse
filtro melhora bastante o resultado do filtro sobel se utilizado antes do mesmo.
ƒ gaussiana5: aplicada o filtro gaussiano na imagem, tornando-a menos acidentada. Esse
filtro melhora bastante o resultado do filtro sobel se utilizado antes do mesmo. Nesse caso a
gaussiana é uma matriz 5x5 ao invés de 3x3.
ƒ blur: torna a imagem embaçada.
ƒ
ƒ
Bisobel: Sobel em duas direções perpendiculares
Quadsobel: Sobel em quatro direções perpendiculares.
3.6 Hough
A Classe Hough, como o próprio nome diz, é a responsável direta por realizar a
transformada de Hough na imagem filtrada, além de retornar as coordenadas da reta encontrada na
imagem.
A Classe Hough contém, além disso, uma série de operações para determinar o modelo de
cores (ColorModel) da imagem de destino, de modo que se possa construir uma imagem que mostre
o resultado da transformada.
Segue uma descrição das operações realizadas:
Primeiro, a classe calcula o raio máximo que a reta terá, ou seja, a diagonal da imagem. O
raio mínimo é definido como zero. Já os valores do ângulo mínimo e máximo são definidos como –
PI e +PI, diretamente no construtor da classe.
O programa que acessar a classe Hough deverá fazê-lo também enviando os valores de
pTheta (quantas divisões terá o intervalo de –PI a PI). pRo (número de divisões no Raio), Threshold
e RenderingHints. É importante notar que pequenos valores para pTheta e pRo tornam o processo
mais rápido, porém podem conduzir a erros.
Gera-se então uma matriz com os valores de co-seno e seno para cada theta entre os valores
mínimos e máximos, cujo número é definido por pTheta. Essa matriz serve para diminuir a
quantidade de processamento da máquina, visto que é muito mais fácil conseguir os valores dos
ângulos através do acesso à matriz de senos e co-senos do que recalcular esses valores toda vez que
eles forem necessários.
Varre-se então a imagem filtrada, checando-se para cada ponto se o valor dele é maior que
o limiar (threshold) fornecido ao construtor. Caso o seja, as coordenadas do conjunto de retas que
passam por aquele ponto são obtidas e o elemento do acumulador respectivo a cada uma é
incrementado, caso o valor do raio para a reta em questão seja menor que o valor do raio máximo
definido anteriormente, de modo a evitar exceções relativas ao tamanho do array definido.
Feito isso, varre-se o array em busca daquele elemento que foi incrementado mais vezes,
que logicamente guardará o maior valor. Depois de obtido, temos a coordenada da reta.
A matriz de acumuladores ainda é normalizada de modo que se possa construir o gráfico do
espaço ro x theta, além de ser construída a imagem com a reta detectada (que é impressa acima da
imagem do último filtro que é passado na imagem antes da transformada de Hough).
3.7 Kalman_2D
Filtro de Kalman é invocado da classe Hough, caso sejam fornecidos para o construtor
desta classe um parâmetro adicional, que será utilizado na determinação do erro mostrado na curva
parametrizada (o interior do círculo verde). Ele está especificado dentro da classe FiltroKalman2D.
O modelo de movimento utilizado é estático, porque é intuitivo que na maioria do tempo de
seu movimento o robô estará seguindo em linha reta, e portanto a calçada deverá permanecer na
mesma posição em relação deste e, portanto, parada na imagem.
A reta verde na tela principal mostra o resultado da transformada de Hough depois da
filtragem de Kalman. O modelo de crença do filtro de Kalman foi definido de forma bem simples:
se o ponto ficar dentro do erro considerado pelo filtro de Kalman, este funcionará normalmente.
Porém, no caso de o ponto encontrado pela câmera em conjunto com a transformada de Hough for
fora da região de erro, o filtro de Kalman não se atualizará e tratará o caso como uma exceção,
mantendo o ponto como o ponto anterior. Logicamente, se passarem um dado número de iterações e
o resultado continuar fora da região de erro, o filtro de Kalman considerará que a situação mudou, e
adequar-se-á a nova situação.
4. TESTES
Os testes foram realizados com uma plataforma com suporte para o notebook e uma câmera
corretamente posicionada, de acordo com as especificações recebidas para o robô utilizado.
Os testes foram feitos em três períodos do dia, separados de acordo com o grau de
iluminação existente: meio-dia, fim de tarde e noite. Também foram feitos testes em curvas.
O algoritmo também foi submetido a alguns testes em ambiente interno, de modo a testar-se
a sua aplicabilidade.
Maiores detalhes sobre a plataforma e testes realizados podem ser encontrados em [3] e [4].
5. CONCLUSÃO
A arquitetura de software desenvolvida se mostro plenamente adequada, especialmente em
seus aspectos facilitadores de análise e calibração dos parâmetros dos algoritmos utilizados. Embora
não tenhamos calculado formalmente o tempo de execução, a rapidez de processamento (em um
notebook Toshiva Sattelite Pentium IV) foi suficiente para a aplicação, já que as velocidades a
serem desenvolvidas pelo robô de vigilância são compatíveis com um mecanismo de controle
servovisual baseado na arquitetura implementada. naturalmente, uma análise mais profunda
dependeria da efetiva implementação da arquitetura em um robô móvel.
Obtivemos um resultado bastante bom com a utilização da transformada de Hough e filtro
de Kalman para detecção de guia de calçadas. Os algoritmos funcionam com exatidão e se
mostraram robustos no que se refere ao tratamento da maioria das situações adversas [3][4].
Referências Bibliográficas
1. “Java Advanced Imaging (JAI) API Specification”, http://java.sun.com/products/javamedia/jai/forDevelopers/jai-apidocs/index.html. Acessado em 17/08/2005.
2. Deitel, H.M e Deitel P.J., JavaTM Como Programar. 6a Edição, Editora Prentice Hall, 2005.
3. Ferriani, V. M. P., “Detecção de Guias de Calçada usando variações da transformada de
Hough”, Relatório Final PIBIC/CNPq, Instituto Tecnológico de Aeronáutica, 2005.
4. Reineri, S., “Implementação e análise de algoritmos de tempo real para detecção de bordas
em navegação utilizando robô móvel de vigilância”, Relatório Final PIBIC/CNPq, Instituto
Tecnológico de Aeronáutica, 2005.
5. Dudek, G. e Jenkin, M. “Computational principles of Mobile Robotics”, Cambridge
University Press, 2000.
6. Russel, S. e Norvig, P., Inteligência Artificial. Tradução da Segunda Edição. Editora
Campos, 2004.
Download