86
Universidade do Minho Licenciatura e Mestrado em Engenharia Electrónica e Computadores Dissertação Ano Lectivo de 2007/2008 Módulo de visão para o robô AIBO da Sony José Afonso Machado Pires Nº27384 Guimarães, 2008

Módulo de visão para o robô AIBO da Sonyintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/27384.pdf · Índice de Tabelas x 1 Introdução 1 1.1 Objectivos 2 1.2 Motivação 3 1.3

Embed Size (px)

Citation preview

Universidade do Minho

Licenciatura e Mestrado em Engenharia

Electrónica e Computadores

Dissertação

Ano Lectivo de 2007/2008

Módulo de visão para o robô AIBO da Sony

José Afonso Machado Pires Nº27384

Guimarães, 2008

José Afonso Machado Pires

Módulo de visão para o robô AIBO da Sony

Dissertação apresentada à

Universidade do Minho para a obtenção do titulo de Mestre em

Engenharia Electrónica Industrial e Computadores.

Guimarães, 2008

Orientador: Prof. Manuel João Ferreira

"É fazendo que se aprende a fazer aquilo que se deve

aprender a fazer."

(Aristóteles)

i

Resumo

Este trabalho surge no âmbito da criação de um módulo de software que permita o uso

de técnicas de visão por computador no robô AIBO da Sony, recorrendo a utilização

de funções de processamento e análise de imagem.

Uma das estratégias gerais do desenvolvimento prende-se com o facto de o módulo

de visão ter que funcionar nos seguintes modos de utilização: simulação recorrendo ao

programa webots; robô como unidade autónoma, robô em comunicação com o PC

recorrendo a TCP/IP. Prendia-se também que o código usado para gerar o programa

para o simulador webots fosse o mesmo para gerar o programa OPEN-R para o AIBO.

Para cumprir estes objectivos foi necessário ter em consideração a especificação da

arquitectura a desenvolver, bem como estender o módulo RCServer e o cross-

compiler (controller) desenvolvidos pela Cyberbotics.

O Módulo de Visão que vai ser apresentado, apesar de ter sido testado e desenvolvido

para o modelo Aibo da Sony, devido a sua arquitectura, permite que facilmente se

integre como módulo de visão de um outro qualquer modelo robótico. Apenas sendo

necessário que o modelo robótico permita a compilação de módulos de software

desenvolvidos em C e C++.

Este Módulo é constituído por diversas classes e funções, que ao contrário de outros

Módulos de Visão, é simples, pouco complexo e permite cumprir vários objectivos

recorrendo ao uso de técnicas de processamento de imagem, tais como a conversão

para diferentes espaços de cor, Operações Morfológicas, Operações para Detecção

de Contornos e Binarizações.

Os resultados do projecto são três pacotes de software. Um é o módulo de visão

constituído por 3 classes, sendo elas respectivamente a classe para definição de

regiões de interesse, a classe para operar com imagens a tons de cinza ou com

apenas um “Frame” de cor de uma Imagem a cores e a classe para trabalhar com

imagens a cores. Os outros são o módulo RCServer e o módulo de cross-compiler

cujas versões iniciais foram estendidas para suportar as funções de processamento e

análise de imagem.

ii

Abstract

This work comes as part of creating a software module, which allows the use of

techniques of computer vision in the Sony AIBO robot, using functions of image

processing and image analysis.

One of the general strategies of development is based in the fact that the module of

vision has to work in the following modes of use: simulation using the program webots;

robot as autonomous unit, robot in communication with the PC using TCP / IP. Was

necessary also that the code used to generate the program for the simulator webots

would be the same program to generate the OPEN-R to the AIBO.

To meet these objectives was necessary to take into account the specification of

architecture to develop and extend the module RCServer and cross-compiler

(controller) developed by Cyberbotics.

The module of Vision that is going to be shown, despite having been tested and

developed for the model Aibo from Sony, due to its architecture, which allows easily to

be integrated as a module of vision of some other robotic model. Only is necessary that

the robotic model allows the compilation of modules of software developed in C and C

+ +.

This module consists of various classes and functions, unlike that of other modules of

Vision, is simple, and allows meet several objectives through the use of techniques of

image processing, such as conversion for different areas of color, Morphologic

Operations, Edge detection Operations and threshold.

The results of the project are three software packages. One is the module of visions

that consists in 3 classes, which are respectively the class that define the regions of

interest; other is the class to operate with the gray images or with only a "Frame" of

color of the color picture and the class to work with images in color. The others are the

modules are the RCServer module and the cross-compiler whose original versions

were extended to support the functions of image processing and analysis.

iii

Agradecimentos

A viabilidade e execução deste projecto dependeu muito da contribuição com

conhecimentos e ajuda de várias pessoas, sem elas não seria possível a conclusão do

mesmo e a consequente escrita desta dissertação, pelo que não posso deixar de lhes

expressar desta forma o meu profundo agradecimento:

– Ao meu orientador Doutor Manuel João Oliveira Ferreira agradeço a orientação

dada, as sugestões e esclarecimentos, o incentivo e a confiança que sempre em mim

depositou. Tenho ainda a agradecer a orientação e sugestões fornecidas no decorrer

da escrita desta dissertação e também pela valiosa ajuda na revisão final.

– À Doutora Cristina Manuela Peixoto Santos pela sua disponibilidade, ajuda e

esclarecimentos fornecidos ao longo deste projecto.

– Ao Pedro José da Silva Ferreira Arade de Macedo, colega do Grupo ASBG da

Universidade do Minho pela sua ajuda e colaboração na realização do software para o

projecto.

– Ao Miguel Alexandre Campos Oliveira, colega do Grupo ASBG da Universidade do

Minho pela sua ajuda e colaboração na realização do projecto e testes no Robot AIBO.

– Aos restantes colegas do Grupo ASBG da Universidade do Minho pelo seu grande

apoio durante toda a execução do projecto e também pela sua amizade e

companheirismo

– Aos meus colegas e amigos do Núcleo Estudantil IEEE da Universidade do Minho

pelo seu grande apoio durante toda a execução do projecto e também pela sua forte

amizade.

– Por último, mas não menos importante, quero demonstrar um profundo

agradecimento à minha mãe, ao meu pai, à minha irmã e amigos mais chegados pelo

apoio e confiança incondicionais que me deram, grande alento quando mais precisei,

não só durante a execução deste projecto mas durante todo o meu percurso até hoje.

iv

Índice

Resumo i

Abstract ii

Agradecimentos iii

Índice iv

Índice de Figuras vi

Índice de Equações viii

Índice de Tabelas x

1 Introdução 1

1.1 Objectivos 2

1.2 Motivação 3

1.3 Metodologia de Pesquisa 3

1.4 Estrutura do Documento 4

2 Ferramentas de Desenvolvimento 5

2.1 Modelo AIBO ERS-7 5

2.1.1 Características 6

2.1.2 Programação do AIBO 8

2.2 Webots 10

2.2.1 RCServer 12

2.2.2 Cross-compiler 14

3 Desenvolvimento 15

3.1 Módulo de Visão 15

3.2 Webots 17

3.3 RCServer 23

3.4 Cross-Compiler 33

4 Fundamentos e implementação do módulo de visão 38

4.1 Binarização 38

4.1.1 Método adaptativo de Russ 39

4.1.2 Método adaptativo de Ostu 40

4.1.3 Implementação 42

4.2 Detecção de Contornos 44

v

4.2.1 Gradiente 45

4.2.2 Laplaciano 46

4.2.3 Implementação 46

4.3 Operações Morfológicas 48

4.3.1 Erosão 48

4.3.2 Dilatação 50

4.3.3 Abertura e Fecho (Open e Close) 51

4.3.4 Implementação 51

4.4 Conversão dos Espaços de Cor 53

4.4.1 RGB 53

4.4.2 YCrCb 54

4.4.3 HSV 55

4.4.4 𝐂𝐈𝐄𝐱𝐲𝐳 56

4.4.5 𝐂𝐈𝐄𝐥𝐚𝐛 57

4.4.6 HCL 58

4.4.7 Implementação 59

5 Caso de aplicação – Coreografia sincronizada por visão 62

5.1 Oscilloscope 62

5.2 Sistema de visão 66

6 Conclusão 71

7 Bibliografia 72

vi

Índice de Figuras

Figura 2.1 – Modelo AIBO ERS-7 ................................................................................. 6

Figura 2.2 – Localização da Câmara do AIBO ERS-7 ................................................... 8

Figura 2.3 – Modo de Comunicação entre Objectos ..................................................... 9

Figura 2.4 – Modo de Funcionamento Webots-RCServer ........................................... 11

Figura 2.5 – Controle Remoto do Webot's AIBO ERS-7, separador de controlo ......... 11

Figura 2.6 – Características de Observer do RCServer .............................................. 12

Figura 2.7 – Características de Subject do RCServer ................................................. 12

Figura 2.8 – Esquema de Funcionamento .................................................................. 13

Figura 3.1 – Esquema de Classes ............................................................................. 16

Figura 3.2 – Esquema de Ligação entre Classes ........................................................ 17

Figura 3.3 – Diagrama de Classes Webots ................................................................. 17

Figura 3.4 – Painel de controlo do AIBO no simulador Webots .................................. 18

Figura 3.5 – Controle Remoto do Webot's AIBO ERS-7, separador de configuração .. 19

Figura 3.6 - Controle Remoto do Webot's AIBO ERS-7, separador de processamento

de imagem .................................................................................................................. 21

Figura 3.7 - Formato de dados OFbkImageVectorData .............................................. 25

Figura 3.8 – Protocolo de comunicação para parâmetros da câmara.......................... 26

Figura 3.9 – Protocolo de Comunicação para as Principais Funções de Processamento

................................................................................................................................... 28

Figura 3.10 – Protocolo de Comunicação da operação Base de Selecção de Canais 29

Figura 3.11 – Protocolo de Comunicação da operação Base de Binarização ............. 29

Figura 4.1 – Representação matemática de uma imagem .......................................... 38

Figura 4.2 – Representação Matemática de uma Binarização ................................... 39

Figura 4.3 – Exemplo da aplicação de filtros de detecção de contornos .................... 44

Figura 4.4 – Resultado da aplicação do gradiente e laplaciano a uma linha de uma

imagem ....................................................................................................................... 45

Figura 4.5 – Esquema representativo das diferentes operações morfológicas ............ 48

Figura 4.6 – Imagem de 6x7 com elemento estruturante em estrela .......................... 49

Figura 4.7 – Exemplo da Erosão ................................................................................. 50

vii

Figura 4.8 – Exemplo da Dilatação ............................................................................ 51

Figura 4.9 - Esquema representativo da conversão em Espaços de Cor .................... 53

Figura 4.10 – Espaço de cores RGB .......................................................................... 54

Figura 4.11 – Distribuição espacial das cores no espaço de cor YCrCb .................... 55

Figura 4.12 – Distribuição espacial das cores no espaço de cores HSV .................... 56

Figura 4.13 – Distribuição espacial das cores no espaço de cor CIExyz ...................... 57

Figura 4.14 – Distribuição espacial das cores no espaço de cor CIElab ...................... 58

Figura 4.15 – Distribuição espacial das cores no espaço de cores HCL .................... 59

Figura 5.1 – Esquema de Funcionamento do Oscilloscope ......................................... 62

Figura 5.2 – Disposição dos círculos no monitor ......................................................... 63

Figura 5.3 – Caixa de diálogo onde é feita a apresentação do som analisado. ........... 63

Figura 5.4 – Imagem do Exemplo Dado ..................................................................... 65

Figura 5.5 – Arquitectura do sistema de visão ........................................................... 66

Figura 5.6 – Círculos de teste de cor .......................................................................... 67

Figura 5.7 – Detecção de Cor ..................................................................................... 67

Figura 5.8 – Detecção de Círculos .............................................................................. 67

Figura 5.9 – Representação do modelo pinhole .......................................................... 69

Figura 6.1 – Folheto de divulgação do Webots de Junho de 2007 .............................. 71

viii

Índice de Equações

Equação 1 .................................................................................................................. 39

Equação 2 .................................................................................................................. 40

Equação 3 .................................................................................................................. 40

Equação 4 .................................................................................................................. 40

Equação 5 .................................................................................................................. 41

Equação 6 .................................................................................................................. 41

Equação 7 .................................................................................................................. 41

Equação 8 .................................................................................................................. 41

Equação 9 .................................................................................................................. 41

Equação 10 ................................................................................................................ 41

Equação 11 ................................................................................................................ 41

Equação 12 ................................................................................................................ 41

Equação 13 ................................................................................................................ 41

Equação 14 ................................................................................................................ 42

Equação 15 ................................................................................................................ 42

Equação 16 ................................................................................................................ 42

Equação 17 ................................................................................................................ 42

Equação 18 ................................................................................................................ 42

Equação 19 ................................................................................................................ 42

Equação 20 ................................................................................................................ 45

Equação 21 ................................................................................................................ 45

Equação 22 ................................................................................................................ 45

Equação 23 ................................................................................................................ 45

Equação 24 ................................................................................................................ 46

Equação 25 ................................................................................................................ 46

Equação 26 ................................................................................................................ 46

Equação 27 ................................................................................................................ 48

Equação 28 ................................................................................................................ 50

Equação 29 ................................................................................................................ 51

ix

Equação 30 ................................................................................................................ 51

Equação 31 ................................................................................................................ 54

Equação 32 ................................................................................................................ 54

Equação 33 ................................................................................................................ 56

Equação 34 ................................................................................................................ 56

Equação 35 ................................................................................................................ 56

Equação 36 ................................................................................................................ 57

Equação 37 ................................................................................................................ 57

Equação 38 ................................................................................................................ 57

Equação 39 ................................................................................................................ 57

Equação 40 ................................................................................................................ 57

Equação 41 ................................................................................................................ 57

Equação 42 ................................................................................................................ 58

Equação 43 ................................................................................................................ 58

Equação 44 ................................................................................................................ 58

Equação 45 ................................................................................................................ 59

Equação 46 ................................................................................................................ 68

Equação 47 ................................................................................................................ 68

Equação 48 ................................................................................................................ 68

Equação 49 ................................................................................................................ 68

Equação 50 ................................................................................................................ 68

Equação 51 ................................................................................................................ 69

Equação 52 ................................................................................................................ 69

Equação 53 ................................................................................................................ 69

Equação 54 ................................................................................................................ 69

Equação 55 ................................................................................................................ 69

Equação 56 ................................................................................................................ 69

Equação 57 ................................................................................................................ 70

x

Índice de Tabelas

Tabela 2.1 – Protocolos de Comunicação RCServer - Webots ................................... 13

Tabela 3.1 – Valores de Identificação das Juntas ....................................................... 31

Tabela 4.1 – Operadores Gradiente ........................................................................... 46

Tabela 5.1 – Referencias de Transformação ............................................................. 70

Tabela 5.2 – Coeficientes de Distorção ...................................................................... 70

1

1 Introdução

No domínio da robótica, apesar de existirem inúmeros e cada vez mais sofisticados

sensores, os de natureza óptica ou seja, os dispositivos de visão ou câmaras,

associados a sofisticados algoritmos de processamento e análise de imagem, têm

cada vez mais um papel predominante.

A informação adquirida por sistemas de visão cobre um volume espacial muito

superior ao dos restantes sensores, permitindo desta forma tornar os sistemas mais

compactos. Ou seja para obter toda a informação igual à proveniente de uma imagem

seria necessário recorrer a um vasto e complexo conjunto de sensores, que mesmo

compactados nunca ocupariam apenas o espaço do sensor óptico. Alterando apenas o

tipo de processamento que é aplicado à imagem é possível extrair, com uma única

aquisição, informação diversificada. Resulta deste modo um sensor mais compacto e

versátil.

É por estes motivos que se expandiu a aplicação de sensores ópticos no domínio da

robótica, tal como aconteceu na década de 90 nos robôs didácticos e plataformas de

estudo, de que são exemplo o AIBO e o ASIMO, dotados de sensores ópticos com

elevada capacidade de processamento e análise de imagem.

A Plataforma AIBO ERS-7 que foi dos últimos modelos do AIBO lançados pela Sony

Corporations, é um robô com diversas potencialidades e diferentes tipos de sensores,

tais como, acelerómetros, sensores de proximidade e de contacto. Possui também um

sensor óptico, cuja imagem fica disponível para aplicação de técnicas de

processamento e análise de imagem, tipicamente para a identificação e

reconhecimento de objectos.

O trabalho que se apresenta nesta tese foca o desenvolvimento dos diferentes

módulos de software que permitem controlar o processo de aquisição de imagens

recorrendo à câmara do AIBO, bem como efectuar processamento e extrair

informação da imagem. Depois de desenvolvidos, estes módulos foram usados noutro

projecto de investigação em curso com o objectivo de auxiliar o robô a efectuar tarefas

específicas. Esta integração fez-se no âmbito do projecto “Online choreography

generation for aquadruped robot using dynamical systems”. A integração do módulo de

visão permite que a plataforma reconheça cores e diâmetros de círculos, que surgem

desenhadas num monitor em conformidade com o som, para posteriormente fornecer

essa informação a um sistema dinâmico que efectua uma coreografia.

Dado o carácter genérico deste módulo de visão ele fica disponível para posterior

integração noutros sistemas, actualmente em desenvolvimento, designadamente o

2

projecto “Locomotion of AIBO Sony based on Non-Linear Dynamic Sistems” em que a

plataforma tem que se locomover evitando e desviando-se de obstáculos, colocando

as patas em marcas identificadas com cores no chão.

1.1 Objectivos

O objectivo geral do trabalho é o desenvolvimento de um módulo de visão, para o robô

AIBO da Sony, que permita controlar o processo de aquisição de imagens e efectuar

processamento e análise sobre as imagens adquiridas com o intuito final de detecção

e seguimento de objectos.

A detecção e seguimento de objectos recorrerão a técnicas de “token matching” [1].

Estas estabelecem correspondências entre características extraídas de imagens

adjacentes numa cena. Genericamente estas características resultam da aplicação de

técnicas de análise de regiões, cor ou textura. Neste trabalho em particular, apenas se

consideram dois tipos de objectos: obstáculos (objectos presentes no ambiente) e

marcadores (objectos utilizados para guiar o posicionamento das patas). Estes

marcadores, por sua vez, apresentarão uma característica geométrica ou cromática

conhecida à priori.

Tendo como ponto de partido as características dos objectos e do ambiente, foram

alvo de estudo e de implementação técnicas nos seguintes domínios:

Calibração da câmara;

Remoção de ruído;

Segmentação baseada em cor;

Extracção de contornos.

Pretende-se também que os algoritmos sejam implementados duma forma flexível de

modo a poderem ser utilizados no robô real, para além da simulação no programa

Webots. Deste modo, foi proposta a criação de um módulo de software independente

do software Webots, independente do sistema de desenvolvimento específico do AIBO

- OPEN-R (linguagem desenvolvida pela Sony) e independente do módulo de

comunicação entre o Webots e o robô real - RCServer desenvolvido por Olivier Michel

(Responsável pelos avanços tecnológicos da Cyberbotics). A flexibilização do módulo

passará também pelo desenvolvimento de novas funcionalidades ao nível do cross-

compiler (controller), desenvolvido por Olivier Michel, permitindo que o mesmo código

fonte possa ser compilado quer para o simulador quer para o robô real.

3

Em específico, a evolução do software RCServer e do controller deve centrar-se nos

seguintes aspectos:

Aquisição da imagem do AIBO e transferência para o Webots via TCP/IP;

Controle dos parâmetros da câmara do AIBO;

Criação de rotinas para processamento e análise de imagem.

1.2 Motivação

A utilização da visão no âmbito da robótica tem-se demonstrado uma área em

expansão. A visão nos robôs permite-lhes localizarem-se, no meio e no espaço em

que estão inseridos, e fornece-lhes dados relevantes quanto à forma de interacção

com esse meio.

Apesar de ser um projecto que envolve visão, que foi a principal motivação para a

execução do mesmo, o presente trabalho demonstrava outros aspectos aliciantes, tais

como:

A plataforma, que apesar de descontinuada, ainda é utilizada para desenvolver

inúmeros estudos científicos;

O carácter genérico que se pretende para o módulo, o qual pode ser integrado

em diversos projectos de estudo, tal como se verificou a quando dos testes do

mesmo;

A implementação de técnicas de processamento de imagem em C/C++;

A possibilidade de desenvolver software para a Cyberbotics Ltd, mais

propriamente para o simulador Webots.

Foi um projecto muito satisfatório e motivante pois forneceu os vários contributos

espectáveis.

1.3 Metodologia de Pesquisa

Este projecto foi alvo de uma fase prévia de estudo ao nível das ferramentas de

desenvolvimento para aplicações para o AIBO, pois apesar de o OPEN-R ter por base

a linguagem C++, contém inúmeras funções próprias e inúmeros métodos de acesso

ao hardware. A metodologia adoptada para a pesquisa bibliográfica contemplou as

seguintes etapas de busca e análise:

Referências acerca do funcionamento do OPEN-R;

4

Referências específicas acerca do acesso ao hardware;

Referências relacionadas com os exemplos fornecidos pelo OPEN-R SDK;

Referências relacionadas com o uso de módulos de visão no AIBO;

Referências acerca dos algoritmos de visão a implementar.

1.4 Estrutura do Documento

Ao longo deste documento vão ser apresentados os aspectos considerados na

implementação do projecto. Para o facto, foi ponderado quais os métodos a serem

utilizados e escolhida a melhor abordagem, tendo em conta as funcionalidades e

capacidades do modelo robótico em causa e o que já existiria para ser usado como

base do projecto.

No ponto Ferramentas de Desenvolvimento são apresentados as diferentes

ferramentas e suas respectivas características. Características essas que vão

condicionar e estipular as abordagens feitas e descritas ao longo do capítulo

Desenvolvimento.

As funções implementadas no módulo de visão e suas respectivas características são

apresentadas no capítulo Fundamentos e implementação do módulo de visão.

Neste capítulo são descritas funções tais como a função de binarização, detecção de

contornos, operações morfológicas e conversão de espaços de cor.

Como este projecto visava o facto que o que fosse desenvolvido poder ser aplicado

em outros projectos é apresentado no capítulo Caso de aplicação – Coreografia

sincronizada por visão um dos casos onde o projecto foi aplicado e que serviu para

realizar os testes pretendidos.

Por fim são apresentadas as Conclusões, tendo estas sido obtidas durante o

desenvolvimento do projecto.

5

2 Ferramentas de Desenvolvimento

Para a execução deste projecto houve a necessidade de recorrer a um conjunto de

ferramentas disponibilizadas pelo laboratório A.S.B.G. (Adaptive System Behaviour

Group) do DEI, em específico:

O robô Modelo AIBO ERS-7 [2];

O software de simulação Webots [3][4];

A aplicação RCServer que permite a comunicação via TCP/IP entre o

simulador e o robô,

O cross-compiler controller que permite a compilação do código fonte do

controlador em Webots em OPEN-R;

O ambiente Cygwin necessário para a compilação dos programas para o robô;

trata-se de um pacote que instala alguns utilitários do Linux no Windows, em

específico o compilador gcc;

OPEN-R SDK, ambiente de desenvolvimento da Sony para o robô AIBO;

Compilador Mingw32, necessário para compilar o software Webots.

De seguida faz-se uma descrição sumária das ferramentas especificamente dedicadas

a este trabalho, pelo que não serão focados as de utilização genérica, nomeadamente

o ambiente Cygwin e Mingw32.

2.1 Modelo AIBO ERS-7

Em 1999 a Sony lançou o AIBO como cão robô de companhia. Esta designação é

obtida a partir de AI (Artificial Inteligence) em combinação com roBOt e que por sua

vez em Japonês significa companheiro. Com o decorrer dos anos o modelo foi

sofrendo alterações quer no âmbito da aparência quer a nível do hardware. Em 2002 a

Sony disponibilizou a ferramenta de desenvolvimento de software para o AIBO,

obtendo-se deste modo acesso a todas as funcionalidades do robô. O sistema de

desenvolvimento é composto por 3 partes: R-CODE; AIBO Remote Framework;

OPEN-R SDK. Desde então, esta plataforma tem sido usada em diversos projectos em

inúmeras áreas [5] [6] [7] [8] [9] [14] [15] [2]. Várias equipas de investigação têm

desenvolvido diversas ferramentas, inclusive no domínio da visão - URBI[16],

Tekkotsu[17], Pyro[18], Cognitive Vision[19] e Carnegie Mellon[20].

Em 26 de Janeiro de 2006 a Sony anunciou a descontinuidade de vários

equipamentos produzidos pela Sony Robotics e em Março desse mesmo ano terminou

6

a produção do modelo tal como o anunciado, apesar de garantir assistência técnica

até 2013.[13] [2].

O modelo utilizado no desenvolvimento deste trabalho é a versão mais recente (ERS-

7-M3) cujas características morfológicas se apresentam na Figura 2.1.

Figura 2.1 – Modelo AIBO ERS-7

2.1.1 Características

O modelo escolhido tem a capacidade de ver, ouvir, sentir e caminhar, e é capaz de se

ligar a uma rede sem fios para comunicar com outros dispositivos electrónicos, através

das seguintes características:

CPU:

Processador RISC 64-bit

Frequência do CPU:

576 MHz

RAM:

64 MB

7

Sistema Operativo:

Dedicado AIBO robot "Memory Stick™" sistema (Aperios)

Partes Móveis: 20 graus de liberdade (DOF - degrees of freedom)

Cabeça - 3 DOF

Boca - 1 DOF

Patas - 3 DOF x 4 (Patas)

Orelhas - 1 DOF x 2 (Orelhas)

Cauda - 2 DOF

Conectores de entrada:

Contacto para carregamento de baterias

Interruptores:

Controlo de volume

Activação da placa wireless LAN

Imagem de entrada:

350.000-pixel sensor de Imagem CMOS

Entrada Áudio:

2 Microfones estéreo

Saída Áudio:

Coluna 20.8mm, 500mW

Sensores:

2 Sensores infravermelhos de distância

Acelerómetro

Sensor de vibração

Sensor de toque na cabeça

Sensor de toque nas costas

Sensor de toque no queixo

4 Sensor de toque ON/OFF das patas

Placa Wireless LAN:

Compatibilidade com protocolos: IEEE 802.11b/IEEE 802.11

8

Banda de Frequência: 2,4 GHz

Canais Wireless: 1 – 11

Modelação: DS-SS (IEEE 802.11 – compliant)

Encriptação: WEP 64 (40 bits), WEP 128 (104 bits)

A câmara, posicionada na cabeça do robô (Figura 2.2), tem uma distância focal de

3.27mm e permite adquirir imagens com dimensões máximas de 208x160 pixel. A

aquisição é feita no espaço de cor YCrCb com uma taxa de aquisição da ordem dos

30 a 40 milissegundos.

Figura 2.2 – Localização da Câmara do AIBO ERS-7

2.1.2 Programação do AIBO

A programação do AIBO tem por base o OPEN-R SDK que faz uso da linguagem

OPEN-R. Esta linguagem caracteriza-se pela programação por objectos e pela

comunicação (transferência de informação) entre objectos. Cada objecto é

considerado como um módulo específico neste tipo de programação e apesar de usar

classes em C++ tem comportamentos similares a um ficheiro executável de um outro

qualquer sistema operativo. A comunicação existente entre eles e as respectivas

dependências são definidas, externamente a cada objecto, no ficheiro stub.cfg. Este é

lido quando o robô é iniciado e desta forma o sistema operativo sabe quais os objectos

que vai ter que executar. A implementação da comunicação entre objectos é realizada

de tal forma que cada módulo é criado de forma independente e existe a possibilidade

de colocar um ou mais módulos em funcionamento.

Quando se pretende colocar objectos em comunicação entre si tem que existir um

objecto definido como Observer e um outro como Subject. O Observer mantém-se em

espera até que o Subject envie um NotifyEvent. Este evento indica ao Observer que o

Subject contém dados para lhe serem enviados. Em resposta, o Observer envia um

sinal de Ready ao Subject, que assim sabe que deve enviar os dados; caso não

receba esse sinal de Ready, o Subject descarta os dados e quando tiver novos dados

envia um novo NotifyEvent (Ver Figura 2.3) [3] [4].

9

Figura 2.3 – Modo de Comunicação entre Objectos

Existem objectos fundamentais que necessitam de ser executados, pelo sistema

operativo, quando se pretende cumprir certas tarefas. Esses objectos são:

OVirtualRobotComm que serve de interface entre o hardware das juntas, dos

sensores, dos LED‟s e da câmara do modelo;

OVirtualRobotAudioComm que serve de interface entre os dispositivos de

áudio do modelo;

JointMover que realiza os acessos ao OVirtualRobotComm para enviar a

informação das juntas;

PowerMonitor que controla a alimentação do modelo.

A ferramenta de desenvolvimento OPEN-R SDK baseada em gcc permite criar

aplicações que funcionem para os diversos modelos do AIBO (ERS-7, ERS-210, ERS-

220, ERS-210A e ERS-220A). Através do recurso a objectos e funções de interface

com o hardware, permite que a aplicação aceda a funcionalidades tais como [6] [7] [8]

[9] [10]:

Mover as juntas;

Ler informação dos sensores;

Receber imagens da câmara;

Usar a conexão wireless (TCP/IP).

A título de exemplo refira-se o pacote de software Tekkotsu [17], que consiste num

conjunto de objectos OPEN-R desenvolvidos recorrendo ao OPEN-R SDK. Tem como

objectivo elevar a abstracção relativa aos comandos e parâmetros a serem passados

às funções de baixo nível e assim permitir que o desenvolvimento de uma aplicação se

faça em termos de comportamentos do robô.

10

De forma a garantir a comunicação via TCP/IP, entre o simulador Webots e o modelo

real, o Instituto Federal Suíço de Tecnologia de Lausanne desenvolveu um objecto

RCServer. Este apenas permite aceder às funcionalidades de mover juntas e

estabelecer conexão wireless [8][9]. O mesmo Instituto desenvolveu um cross-compiler

(controller) com o objectivo de garantir a portabilidade do código desenvolvido no

simulador para o modelo real. O controller apresenta apenas as funcionalidades de

mover juntas.

2.2 Webots

A ferramenta Webots é um simulador tridimensional, produzido pela Cyberbotics Ltd,

que utiliza tecnologia co-desenvolvida pelo Instituto Federal Suíço de Tecnologia de

Lausanne [3] [4]. Esta ferramenta é usada por mais de 450 instituições de

investigação, sendo o grupo A.S.B.G. da Universidade do Minho um desses

utilizadores e colaborador no desenvolvimento de módulos para o simulador.

Este simulador inclui funcionalidades que permitem ao utilizador simular e controlar

diversos mecanismos robóticos, com diferentes formas de locomoção em diferentes

meios. Para isso recorre à tecnologia gráfica OpenGL, à possibilidade de leitura de

modelos 3D compatíveis com VRML97 standard e à Open Dynamics Engine library

(ODE) que permite a introdução de características físicas na simulação [3] [4] [8] [9].

O controlador do mecanismo robótico pode ser desenvolvido em linguagem C, C++ ou

Java. Para alguns modelos de robôs é possível transferir o controlador ou enviar

comandos via TCP/IP para o robô real, para que este realize as mesmas tarefas do

modelo simulado [3] [4]. Isto já é possível para os modelos reais da e-puck™, LEGO™

Mindstorms™, Khepera™, Hemisson™, Sony™ AIBO ERS-210 e Sony™ AIBO ERS-

7.

Para que seja estabelecida uma ligação de envio de comandos entre o simulador

Webots e o modelo real do AIBO, é necessário que o objecto RCServer seja

executado dentro do modelo real. Só desta forma se consegue estabelecer uma

ligação do tipo cliente-servidor via TCP/IP entre o computador que contém o simulador

Webots (cliente) e o modelo real (servidor), tal como se ilustra na Figura 2.4.

11

Figura 2.4 – Modo de Funcionamento Webots-RCServer

Antes do início deste trabalho só era possível enviar do Webots via TCP/IP os

comandos para cada uma das juntas e LEDS, receber os estados das juntas e

efectuar o reboot ou shutdown do modelo real. Na Figura 2.5 apresenta-se o painel de

controlo do Webots que permitia efectuar as operações referidas. O Webots também

já continha o código para a funcionalidade de aquisição de imagem, no entanto este

estava operacional.

Figura 2.5 – Controle Remoto do Webot's AIBO ERS-7, separador de controlo

12

2.2.1 RCServer

Este módulo é um objecto OPEN-R que serve para estabelecer, do lado do modelo

real, a comunicação servidor-cliente com o programa Webots; é também responsável

pela implementação do protocolo de troca de informação. O módulo RCServer

funciona como Observer e como Subject sendo as comunicações estabelecidas como

se ilustra nas Figuras 2.6 e 2.7.

Figura 2.6 – Características de Observer do RCServer

Figura 2.7 – Características de Subject do RCServe

A Figura 2.8 apresenta o esquema de funcionamento e os objectos OPEN-R

necessários para estabelecer a ligação cliente-servidor entre o Webots e o modelo real

do robô.

13

Figura 2.8 – Esquema de Funcionamento

Uma vez estabelecida a ligação, o objecto RCServer fica à espera de comandos do

Webots. Estes comandos dividem-se em dois grupos: envio de ordens (SetCommand),

por exemplo para o posicionamento das juntas e pedido de leitura (GetCommand), por

exemplo leitura da posição das juntas. Para a correcta interpretação destes pedidos a

comunicação RCServer – Webots faz uso do protocolo da Tabela 2.1.

Comando Trama

SetCommand „X‟,B2,B3B4

Reboot 'R',0,0

Shutdown 'Q',0,0

Global Acceleration 'V', 0, AngleValue

Global Velocity 'A', 0, Value

Joint Velocity 'V', JointID, Value

Joint Acceleration 'A', JointID, Value

Joint Position 'J', JointID, Value

Plunger 'K', PlungerID, Value

LED 'L', LEDID, Value

GetCommand „X‟,B2

Joint Velocity 'V',JointID

Joint Acceleration 'A',JointID

Joint Value 'J',JointID

Tabela 2.1 – Protocolos de Comunicação RCServer - Webots

A trama do comando SetCommand do AIBO é constituída por 4 bytes („X‟,B2,B3B4). O

primeiro byte („X‟) identifica o comando; o segundo byte (B2) transporta o identificador

do elemento a controlar (por exemplo identificador da junta); o terceiro e quarto bytes

14

(B3B4) contêm o valor a aplicar ao elemento. A trama do comando GetCommand é

constituída por dois bytes. O primeiro („X‟) identifica o comando e o segundo (B2) é o

identificador do elemento sobre o qual se pretende obter informação.

Cada um destes comandos é interpretado pelo RCServer, gerando a respectiva acção.

Em resposta, se o comando foi bem interpretado, o RCServer devolve uma trama com

o byte do comando („X‟) alterado para o respectivo carácter minúsculo („x‟). Em caso

de erro de interpretação o RCServer devolve a trama com o byte do comando com o

carácter „e‟.

2.2.2 Cross-compiler

O módulo cross-compiler (controller) permite a portabilidade do código desenvolvido

para o simulador Webots para o modelo real Aibo. Para tal consiste num conjunto de

funções globais com a mesma sintaxe que as funções do Webots e que fazem o

encapsulamento ao acesso no modelo real. Este acesso é efectuado através de um

objecto OPEN-R – controller. A título de exemplo apresenta-se o acesso à informação

do estado da bateria.

//Objecto OPEN-R

Controller* mySelf;

// função global para encapsulamento

float robot_battery_sensor_get_value(void)

{

return mySelf->robot_battery_sensor_get_value();

}

// função do objecto controller que acede ao hardware

float

Controller::robot_battery_sensor_get_value(void)

{

// OSYSPRINT(("Controller::robot_battery_sensor_get_value()\n"));

OPowerStatus currentStatus;

OPENR::GetPowerStatus(&currentStatus);

OSYSPRINT(("Controller::robot_battery_sensor_get_value()

%f\n",(float)(currentStatus.remainingCapacity)));

// unit = 1%

return (float)(currentStatus.remainingCapacity);

}

A função global robot_battery_sensor_get_value apresenta a mesma sintaxe que a

função da biblioteca do Webots. Quando em modo de cross-compiler é compilada esta

versão da função que evoca a função, com o mesmo nome, do objecto mySelf. A

variável mySelf aponta para uma instância do objecto OPEN-R Controller, acedendo-

se assim às funcionalidades do modelo real.

15

3 Desenvolvimento

Como foi referido no ponto 2.1.1 o AIBO contém um módulo programável baseado no

sistema operativo aperios, capaz de executar e interpretar programas criados em

OPEN-R. Esta linguagem tem como suporte o C++, pelo que o ambiente de

desenvolvimento (OPEN-R SDK) permite a integração de classes desenvolvidas em

C++ e funções C. Desta forma o módulo de visão foi desenvolvido em C++, e de tal

forma que fosse portável para diferentes ambientes de desenvolvimento e sistemas

operativos.

3.1 Módulo de Visão

O módulo de visão é constituído por três classes (Figura 3.1): a classe ROI, a classe

CGrayImage e a classe CColorImage.

A classe ROI permite a definição de regiões de processamento e analise na imagem,

evitando assim a perca de tempo a processar áreas que não contêm informação

relevante.

A classe CGrayImage tem os argumentos referentes às operações passíveis de ser

executadas em imagens de níveis de cinzento ou em imagens de cada um dos 3

componentes de cor, tais como a binarização, as operações morfológicas e a detecção

de contornos.

A classe CColorImage integra os argumentos referentes a operações em imagens a

cores, tais como a mudança de espaços de cores e a selecção da componente de cor

a processar.

Conforme se pode observar na Figura 3.1, a classe ROI está ligada por agregação a

cada uma das restantes classes. A classe CColorImage contém três objectos da

classe CGrayImage. Desta forma cada componente de cor pode ser processada

individualmente através da classe CGrayImage. As ligações entre classes foram

estipuladas desta forma para assegurar versatilidade e portabilidade do módulo para

outros programas.

16

+m_Xint : int

+m_Yinit : int

+m_Width : int

+m_Height : int

Classe ROI

-m_Roi : Classe ROI

-* m_pOImage : unsigned char

-* m_pTImage : unsigned char

-m_Width : int

-m_Height : int

+m_BlobXmi : int

+m_BlobXmax : int

+m_BlobYmin : int

+m_BlobYmax : int

+* GetRoi() : Classe ROI

+SetRoi(int x, int y, int w, int h) : void

+SetRoi(ROI r) : void

+clearblob(int Xmin, int Ymin, int Xmax, int Ymax, unsigned char CL, unsigned char OL, unsigned char BKL ) : void

+SetImage(unsigned char* imagedata) : void

+* GetImage(){ return m_pOImage;} : unsigned char

+Convolution(int N, int * OffsetX, int * OffsetY, double * Weight, double Denoninator) : void

+Histogram(double *pValues) : void

+enum { RankOperationDilatation, RankOperationErosion, RankOperationMean}

+enum { GradientOperatorRoberts, GradientOperatorPrewitt, GradientOperatorSobel }

+enum { MorphologicalGradientErosion, MorphologicalGradientDilatation, MorphologicalGradientDilatationErosion }

+enum { BinarizationLevelOtsu, BinarizationLevelRuss }

+EdgeDetectionMorphologicalGradient(int Operation, int N, int *OffsetX, int *OffsetY, int *Weight) : void

+EdgeDetectionGradientOperator(int Type) : void

+MorphologicalRankOperation(int Operation, int N, int *OffsetX, int *OffsetY, int *Weight) : void

+ComputeBinarizationLevel(int Type) : unsigned char

+Binarization(unsigned char Level, bool Invert=false) : void

+Binarization(unsigned char MinLevel,unsigned char MaxLevel, bool Invert=false) : void

+Inside(int X, int Y) : bool

+SetLevel(int X, int Y, unsigned char Level) : void

+GetLevel(int X, int Y) : unsigned char

+SetDimensions(int Width, int Height) : void

+GetWidth() { return m_Width; } : int

+GetHeight() { return m_Height; } : int

+Flood(int X, int Y, unsigned char OLevel, unsigned char NLevel) : void

+calcblob(int GL)

+ CGrayImage()

+CGrayImage(int Width, int Height, unsigned char *pData=NULL, unsigned char Level=0)

+CGrayImage::CGrayImage(CGrayImage *pImage)

+~CGrayImage() : virtual

+ConvertCImgGray2WebotsImg(unsigned char *imgData) : void

Class CGrayImage

-*m_pTrueColorImage[3] : Class CGrayImage

-m_Width : int

-m_Height : int

-m_Roi : Classe ROI

+m_Channel2Proc : int

+* GetRoi() : Classe ROI

+SetRoi(int x, int y, int w, int h) : void

+SetRoi(ROI r) : void

+ColorSegmentation(unsigned char rmin, unsigned char rmax, unsigned char gmin, unsigned char gmax, unsigned char bmin, unsigned char bmax, int mode) : void

+ConvertRGB2HSL() : void

+ConvertRGB2HSV() : void

+RGB2HSV(double r, double g, double b, double *h,double *s,double *v) : void

+RGB2HSL(double r, double g, double b, double *h,double *s,double *l) : void

+HSL2RGB(double *r, double *g, double *b, double H,double S,double L) : void

+RGB2Lab(double R, double G, double B, double *L,double *a,double *b) : void

+ConvertRGB2Lab() : void

+RGB2Gray(double R, double G, double B) : double

+ConvertRGB2Gray() : void

+ConvertRGB() : void

+HuetoRGB(double m1, double m2, double h) : double

+m_DPIY : long

+m_DPIX : long

+SetFrame(CGrayImage * pImage, int Frame) : void

+* GetFrame(int Frame) : Class CGrayImage

+GetLevel(int x, int y, int Frame=0) : unsigned char

+m_Image_Type : int

+GetWidth() : int

+GetHeight() : int

+CColorImage()

+CColorImage(int Width, int Height,unsigned char *pData0=NULL,unsigned char *pData1=NULL,unsigned char *pData2=NULL, unsigned char Level=0,int IMAGE_TYPE=YCrCb_IMAGE)

+CColorImage(CColorImage *pImgTrueColor)

+CColorImage(int Width, int Height,CGrayImage* pRFrame,CGrayImage* pGFrame,CGrayImage* pBFrame,int IMAGE_TYPE)

+ConvertCImgTrueColor2WebotsImg(unsigned char *imgData) : void

+ConvertWebotsImg2CImgTrueColor(unsigned char *imgData) : void

+SaveRawImg(char * filename) : void

+LoadRawImg(char * filename) : void

+~CColorImage() : virtual

Class CColorImage

(a)

(b)

(c)

Figura 3.1 – Esquema de Classes

O controlador do AIBO acede ao módulo de visão através dos objectos RCServer ou

Controller. Cada um destes objectos, por agregação, ganha acesso aos diferentes

argumentos e métodos das classes que constituem o módulo de visão. A Figura 3.2

mostra esquematicamente a ligação entre as diversas classes.

17

Figura 3.2 – Esquema de Ligação entre Classes

3.2 Webots

A Figura 3.3 apresenta em esquema o diagrama de classes do Webots que controlam

as funcionalidades de comunicação com o AIBO através do painel de controlo.

Figura 3.3 – Diagrama de Classes Webots

A classe A_Aibo implementa a interface com o painel de controlo recorrendo a

objectos da biblioteca wxWidgets [21]. Quando alguma acção é executada na interface

é evocada a respectiva função da classe Remote, que por sua vez evoca o método da

classe A_AiboClient. A título de exemplo apresenta-se o código fonte que implementa

o comando reboot do painel de controlo (Figura 3.4), através da função

OnButtonNetReboot da classe A_Aibo.

Classe A_Aibo:

void A_Aibo::OnButtonNetReboot(wxCommandEvent &event) {

_DEBUG("Net: Reboot requested\n");

if( !remote.isConnected() ) return;

A_Aibo

Remote

wxWindow

1

+1

A_AiboClient

1

P_WinSock

Controller +1

18

ErrorID error = remote.reboot();

if( !error ) {

Disconnect();

SetStatusText(_T("Aibo rebooting... Please reconnect"));

} else ShowAiboErrorAndDisconnect(error);

}

Classe Remote:

ErrorID Remote::reboot() {

return client.sendCommand('R',0,0);

}

Classe A_AiboClient:

ErrorID A_AiboClient::sendCommand(const char command,

const unsigned char identifier,

const short value ) {

if (!isConnected()) return NOT_CONNECTED_ERROR;

BasicSetCommand cmd;

cmd.command = command;

cmd.identifier = identifier;

cmd.value = wxINT16_SWAP_ON_BE(value);

int cmd_length = sizeof(BasicSetCommand);

char* cmd_string = (char*)&cmd;

if (!send(cmd_string,cmd_length))

return NetworkFailure(SENDING_COMMAND_ERROR);

// confirm

BasicAnswer* answer = recvBasicAnswer();

return answer==NULL ? RECEIVING_ANSWER_ERROR

: answer->command == 'e' ? UNKNOWN_COMMAND_ERROR

: SUCCESS;

}

Figura 3.4 – Painel de controlo do AIBO no simulador Webots.

Estas três classes (A_Aibo; Remote, A_AiboClient) foram estendidas de forma a

suportar as funcionalidades acrescidas ao simulador Webots.

A primeira alteração realizada no programa Webots foi tornar funcional a captação de

imagens e a alteração dos parâmetros da câmara. Na Figura 3.5 apresenta-se a

interface gráfica desenvolvida.

19

Figura 3.5 – Controle Remoto do Webot's AIBO ERS-7, separador de configuração

As funções acrescidas à classe A_Aibo, relativas ao controlo da câmara, são as que

se apresentam de seguida:

virtual void OnButtonCameraGetGain(wxCommandEvent &event);

virtual void OnButtonCameraGetShutter(wxCommandEvent &event);

virtual void OnButtonCameraGetWB(wxCommandEvent &event);

virtual void OnRadioGain( wxCommandEvent &event );

virtual void OnRadioShutter( wxCommandEvent &event );

virtual void OnRadioWB( wxCommandEvent &event );

A título de exemplo apresenta-se a implementação da funcionalidade associada ao

botão de interface Get Gain.

Classe A_Aibo:

void A_Aibo::OnButtonCameraGetGain(wxCommandEvent &event) {

short v=1;

_DEBUG("Get Camera Gain requested\n");

if( !remote.isConnected() )

{

A_Util::message("GET GAIN: AIBO not connected");

return;

}

ErrorID error = remote.GetCameraGain(v);

if( error )

ShowAiboErrorAndDisconnect(error);

else

cameraRadioGain->SetStringSelection(cameraRadioGainChoices[v-1] );

}

Classe Remote:

ErrorID Remote::GetCameraGain(short &value) {

return client.sendGetCommand('I','G',value);

}

Classe A_AiboClient:

ErrorID A_AiboClient::sendGetCommand(const char command,

const unsigned char identifier,

short& value) {

if (!isConnected()) return NOT_CONNECTED_ERROR;

20

BasicGetCommand cmd;

cmd.command = command;

cmd.identifier = identifier;

// send command

int cmd_length = sizeof(BasicGetCommand);

char *cmd_string = (char *)&cmd;

if (!send(cmd_string, cmd_length))

return NetworkFailure(SENDING_COMMAND_ERROR);

// receive answer

BasicAnswer* answer = recvBasicAnswer();

if (answer==NULL) return NetworkFailure(RECEIVING_ANSWER_ERROR);

if (answer->command=='e') return UNKNOWN_COMMAND_ERROR;

// assign payload value

value = wxINT16_SWAP_ON_BE(answer->value);

return SUCCESS;

}

A aquisição da imagem é efectuada através da funcionalidade associada ao botão

Snapshot (OnButtonCameraSnapShot).

Classe A_Aibo:

void A_Aibo::OnButtonCameraSnapShot(wxCommandEvent &event) {

_DEBUG("Camera Frame requested\n");

if( !remote.isConnected() )

{

A_Util::message("AIBO not connected");

return;

}

ErrorID error = remote.GetCameraFrame(ImgJpeg);

if( error )

ShowAiboErrorAndDisconnect(error);

ShowImageOnCanvas(0,ImgJpeg);

imageacquired=true;

}

Classe Remote:

ErrorID Remote::GetCameraFrame(char *ImgJpeg) {

return client.sendGetFrameCommand('F',0x64,ImgJpeg);

}

Classe A_AiboClient:

ErrorID A_AiboClient::sendGetFrameCommand(const char command,

const unsigned char identifier,

char *ImgJpeg) {

if (!isConnected()) return NOT_CONNECTED_ERROR;

BasicGetCommand cmd;

cmd.command = command;

cmd.identifier = identifier;

// send command

int cmd_length = sizeof(BasicGetCommand);

char *cmd_string = (char *)&cmd;

if (!send(cmd_string, cmd_length))

return NetworkFailure(SENDING_COMMAND_ERROR);

if(recvImage(ImgJpeg))

return SUCCESS;

else

return NetworkFailure(RECEIVING_ANSWER_ERROR);

}

int A_AiboClient::recvImage(char* buffer) {

int nrecv=SOCKET_ERROR;

clock_t c0=clock(); float delay=0;

do {

21

nrecv = ::recv(commSocket,buffer,5,MSG_PEEK);

delay = (clock()-c0)/(float)CLOCKS_PER_SEC;

} while( nrecv<5 && delay<WINSOCK_RECV_TIMEOUT );

if(delay<WINSOCK_RECV_TIMEOUT )

{

int IS=0;

int ImageSize=((unsigned char)buffer[4]<<24) + ((unsigned

char)buffer[3]<<16) + ((unsigned char)buffer[2]<<8) + (unsigned

char)buffer[1];

nrecv = ::recv(commSocket,buffer,ImageSize+5,0);

IS+=nrecv-5;

while(IS<ImageSize)

{

nrecv = ::recv(commSocket,buffer +IS+5,ImageSize+5,0);

IS+=nrecv ;

}

return 1;

}

else

return 0;

}

Numa segunda fase, ao Simulador Webots foi acrescentado um novo separador no

controle remoto do Webot's AIBO ERS-7 com o nome “Image Processing” e criados os

comandos que permitissem o processamento da imagem adquirida pela câmara do

AIBO (Figura 3.6).

Figura 3.6 - Controle Remoto do Webot's AIBO ERS-7, separador de processamento

de imagem

No separador “Image Processing” pode observar-se quais os algoritmos de

processamento que são passíveis de serem aplicados à imagem através de comandos

remotos, designadamente: conversão entre espaços de cor (Color conversion),

operações morfológicas (Morphology), filtros espaciais (Spatial filter) e binarização

22

(Segmentation). Para além destas operações é possível seleccionar a componente de

cor a processar (Select Channel) bem como enviar uma sequência de operações para

processamento sequencial. As funções que se apresentam de seguida foram

implementadas na classe A_Aibo:

virtual void OnRadioImageProcessingColor( wxCommandEvent &event );

virtual void OnRadioImageProcessingMorph( wxCommandEvent &event );

virtual void OnRadioImageProcessingSegmentation( wxCommandEvent &event );

virtual void OnRadioImageProcessingSpatialFilters( wxCommandEvent &event );

virtual void OnRadioImageProcessingSelectChannel( wxCommandEvent &event );

virtual void OnListBoxImageProcessingRunFunction( wxCommandEvent &event );

virtual void OnListBoxAppendImageProcessingFunction( wxCommandEvent &event );

virtual void OnListBoxRemoveImageProcessingFunction( wxCommandEvent &event );

virtual void OnListBoxSend2Aibo( wxCommandEvent &event );

virtual void OnSpinCtrlMinThrValue( wxSpinEvent &event );

virtual void OnSpinCtrlUpMinThrValue( wxSpinEvent &event );

virtual void OnSpinCtrlDownMinThrValue( wxSpinEvent &event );

virtual void OnSpinCtrlTextMinThrValue( wxCommandEvent &event );

virtual void OnSpinCtrlMaxThrValue( wxSpinEvent &event );

virtual void OnSpinCtrlUpMaxThrValue( wxSpinEvent &event );

virtual void OnSpinCtrlDownMaxThrValue( wxSpinEvent &event );

virtual void OnSpinCtrlTextMaxThrValue( wxCommandEvent &event );

A título de exemplo mostra-se a implementação nas três classes da operação

RGB2HSV recorrendo a OnRadioImageProcessingColor.

Classe A_Aibo:

void A_Aibo::OnRadioImageProcessingColor( wxCommandEvent &event )

{

imageprocessed=false;

if (event.GetString()==imageProcessingColorRadioChoices[0])

{

_DEBUG("DO none Color conversion \n");

if( !remote.isConnected() )

{

A_Util::message("Do none Color conversion: AIBO not

connected");

return;

}

ErrorID error = remote.SetNoColorConv(ImgProcJpeg);

if( error )

ShowAiboErrorAndDisconnect(error);

}

if (event.GetString()==imageProcessingColorRadioChoices[1])

{

_DEBUG("Do RGB2HSV color conversion \n");

if( !remote.isConnected() )

{

A_Util::message("Do RGB2HSV color conversion: AIBO not

connected");

return;

}

ErrorID error = remote.SetColorConv2HSV(ImgProcJpeg);

if( error )

ShowAiboErrorAndDisconnect(error);

else

imageprocessed=true;

}

if (event.GetString()==imageProcessingColorRadioChoices[2])

{

_DEBUG("Do RGB2CIELab color conversion \n");

if( !remote.isConnected() )

{

A_Util::message("Do RGB2CIELab color conversion : AIBO not

connected");

return;

23

}

ErrorID error = remote.SetColorConv2CIELab(ImgProcJpeg);

if( error )

ShowAiboErrorAndDisconnect(error);

else

imageprocessed=true;

}

if (event.GetString()==imageProcessingColorRadioChoices[3])

{

_DEBUG("Do RGB2HSL color conversion \n");

if( !remote.isConnected() )

{

A_Util::message("Do RGB2HSL color conversion : AIBO not

connected");

return;

}

ErrorID error = remote.SetColorConv2HSL(ImgProcJpeg);

if( error )

ShowAiboErrorAndDisconnect(error);

else

imageprocessed=true;

}

if(imageprocessed)

selectedoperation=event.GetString();

ShowImageOnCanvas(2,ImgProcJpeg);

}

Classe Remote:

ErrorID Remote::SetColorConv2HSV(char *ImgJpeg) {

return client.sendSetImageProcessingCommand('M',0x64,'C',1,ImgJpeg);//2HSV

}

Classe A_AiboClient:

ErrorID A_AiboClient::sendSetImageProcessingCommand(const char command, const

unsigned char imageresolution,

const unsigned char processingclass, const unsigned char processingtype,

char *ImgJpeg) {

if (!isConnected()) return NOT_CONNECTED_ERROR;

BasicSetCommand cmd;

cmd.command = command;

cmd.identifier = imageresolution;

cmd.value=(processingclass<<8)+processingtype;

// send command

int cmd_length = sizeof(BasicSetCommand);

char *cmd_string = (char *)&cmd;

if (!send(cmd_string, cmd_length))

return NetworkFailure(SENDING_COMMAND_ERROR);

if(recvImage(ImgJpeg))

return SUCCESS;

else

return NetworkFailure(RECEIVING_ANSWER_ERROR);

}

3.3 RCServer

Tal como efectuado ao simulador Webots o objecto OPEN-R RCServer foi estendido

para contemplar as novas funcionalidades: captação de imagem; controlo dos

parâmetros da câmara; processamento e análise de imagem.

24

3.3.1 Aquisição e controlo dos parâmetros da câmara

Através do OPEN-R SDK, é possível aceder a todas as funcionalidades do modelo

AIBO mediante a função OPENR::ControlPrimitive() [12]. A parametrização da câmara

é efectuada recorrendo aos seguintes parâmetros dessa função.

Balanço de Brancos:

o ocamparamWB_INDOOR_MODE

o ocamparamWB_OUTDOOR_MODE

o ocamparamWB_FL_MODE (para lâmpadas fluorescentes)

Exemplo de parametrização:

OPrimitiveControl_CameraParam wb(ocamparamWB_OUTDOOR_MODE);

OPENR::ControlPrimitive(cameraID, oprmreqCAM_SET_WHITE_BALANCE, &wb, sizeof(wb), 0, 0);

Ganho:

o ocamparamGAIN_LOW

o ocamparamGAIN_MID

o ocamparamGAIN_HIGH

Exemplo de parametrização:

OPrimitiveControl_CameraParam gain(ocamparamGAIN_MID);

OPENR::ControlPrimitive(cameraID, oprmreqCAM_SET_GAIN, &gain, sizeof(gain), 0, 0);

Velocidade de Obturador:

o ocamparamSHUTTER_SLOW

o ocamparamSHUTTER_MID

o ocamparamSHUTTER_FAST

Exemplo de parametrização:

OPrimitiveControl_CameraParam shutter(ocamparamSHUTTER_FAST) ;

OPENR::ControlPrimitive(cameraID, oprmreqCAM_SET_GAIN, &shutter, sizeof(shutter), 0, 0);

O acesso à imagem da câmara é efectuado através da classe OVirtualRobotComm,

sendo para tal necessário introduzir no ficheiro de configuração connect.cfg a seguinte

ligação [5] [6] [10] [14] [15]:

OVirtualRobotComm.FbkImageSensor.OFbkImageVectorData.S

25

Deste modo a estrutura que contém a informação do sensor (FbkImageSensor) fica

disponível para os objectos OPEN-R. O acesso à imagem é efectuado recorrendo à

estrutura OFbkImageVectorData contida em FbkImageSensor. Na Figura 3.7 é

apresentado o formato e estrutura de dados de cada OFbkImageVectorData [5] [6] [7]

[12] [14] [15].

Figura 3.7 - Formato de dados OFbkImageVectorData.

A imagem contida em cada OFbkImageVectorData pode ser de quatro tipos [12]:

ofbkimageLAYER_H - Imagem a cores de alta resolução;

ofbkimageLAYER_M - Imagem a cores de média resolução (metade da

resolução de ofbkimageLAYER_H);

ofbkimageLAYER_L - Imagem a cores de baixa resolução (metade da

resolução de ofbkimageLAYER_M);

ofbkimageLAYER_C - Imagem para detecção de cores (contém apenas as

cores que se pretende reconhecer);

Através da função GetInfo() da classe OFbkImageVectorData obtém-se toda a

informação relativa a imagem e através da função GetData() obtém-se um ponteiro

para a imagem. Por exemplo, para aceder à informação de uma imagem de média

resolução (ofbkimageLAYER_M) o código a usar é o seguinte:

OFbkImageInfo* info = fbkImageVectorData->GetInfo(ofbkimageLAYER_H);

byte* data = fbkImageVectorData->GetData(ofbkimageLAYER_H);

Para enviar a informação entre o Webots e o RCServer foi usada a mesma abordagem

protocolar implementada pela cyberbotics. Assim, o protocolo para alterar um

parâmetro da câmara foi estendido da seguinte forma:

26

O primeiro byte da trama contém o carácter „I‟;

O segundo byte diz respeito ao parâmetro a alterar:

Ganho – „G‟;

Abertura da Câmara – „S‟;

Balanço dos Brancos – „W‟.

O terceiro e quarto bytes conterão o valor de 1 a 3 referente aos três estados

(pela ordem de apresentação) que cada parâmetro admite.

A Figura 3.8 apresenta esquematicamente o protocolo referente à alteração dos

parâmetros da câmara. O RCServer, como confirmação de que o comando foi

recebido e executado, envia uma resposta com o primeiro byte com o valor „i‟.

Figura 3.8 – Protocolo de comunicação para parâmetros da câmara

A título de exemplo as linhas de código seguintes implementam a operação de

alteração do valor do ganho no objecto RCServer:

BasicAnswer

RCServer::AnalyzeCommand(int size){

……

if (commandChar == 'I')

{

longword set;

if(commandID == 'G') //GAIN

{

switch(commandValue)

{

case 1:

set=ocamparamGAIN_LOW;

OSYSPRINT(("\nGAIN LOW\n"));

break;

case 2:

set=ocamparamGAIN_MID;

OSYSPRINT(("\nGAIN MID\n"));

break;

case 3:

set=ocamparamGAIN_HIGH;

OSYSPRINT(("\nGAIN HIGH\n"));

break;

}

CameraparameGain=commandValue;

OPrimitiveControl_CameraParam gain(set);

27

OPENR::ControlPrimitive(cameraID,oprmreqCAM_SET_GAIN,

&gain, sizeof(gain),0,0);

}

……….

}

O comando para receber uma imagem tem a seguinte trama: „F‟,0x64,0,0. O valor

0x64 é a informação relativa à qualidade da imagem. 0x64 faz referência à melhor

qualidade, ou seja não é executada nenhuma alteração da imagem quando se faz a

compressão para envio.

A imagem é devolvida no formato jpeg pelo RCServer ao Webots num array de bytes

que começa com o carácter „f‟ seguido de quatro bytes com o tamanho da imagem.

Após este cabeçalho o array contém a informação da imagem. A seguir apresenta-se

as linhas de código da classe RCServer que implementam a resposta ao Webots.

void

RCServer::Notify(const ONotifyEvent& event)

{

...

imgData = new byte[JPEG_BUFSIZE]; // pointer to image

...

// take picture

OFbkImageVectorData* fbkImageVectorData =

(OFbkImageVectorData*)event.Data(0);

OSYSPRINT(("RCServer::Notify(): Picture taking OK.\n"));

// convert raw picture to JPEG

imgResult = GetJPEG(fbkImageVectorData,

ofbkimageLAYER_H,

imgQuality,

imgData,

&(imgSize));

...

// protocol convention, header has to start with the character f

imgHeader[0] = 'f';

// convert file size to big endian and put it splitted to array

imgHeader[1] = imgSize & 255;

imgHeader[2] = (imgSize >> 8) & 255;

imgHeader[3] = (imgSize >> 16) & 255;

imgHeader[4] = (imgSize >> 24) & 255;

// copy header to shared memory buffer

memcpy(connection.sendData, imgHeader, sizeof(imgHeader));

// copy picture to shared memory buffer just behind header

memcpy((connection.sendData+5), imgData, imgSize);

// prepare sending information

connection.sendSize = imgSize + 5;

Send();

...

}

28

3.3.2 Processamento e análise de imagem

De forma similar ao que se efectuou para o controlo dos parâmetros da câmara, o

protocolo foi estendido para suportar novos comandos de processamento e análise de

imagem.

As funções de conversão de cores, operações morfológicas e as operações de filtros

espaciais foram agrupadas num mesmo tipo de comando. Deste modo o primeiro byte

da trama contém o carácter „M‟. O segundo byte transporta a qualidade da imagem e

os restantes bytes a classe da operação e o índice do filtro a executar. A Figura 3.9

apresenta o protocolo para o comando „M‟.

Por exemplo, se for enviado {M, 0x64,M,1}, está-se a solicitar que seja executada uma

operação principal de processamento „M‟; pretende-se receber a imagem com

qualidade 100%; a operação desejada é uma operação morfológica „M‟ e o filtro

específico é a erosão 1.

A resposta a este comando „M‟ é idêntica ao do pedido de uma imagem, comando „F‟,

só que neste caso a imagem foi previamente processada.

(a) (b)

Figura 3.9 – Protocolo de Comunicação para as Principais Funções de Processamento

(a) Operações Morfológicas ‘M’ (b) Conversão de Cores ‘C’ e Filtros ‘F’

Para o caso da Selecção de Canais e Binarização estas operações foram agrupadas

no mesmo comando („B‟).

O protocolo para a Selecção de Canais tem um procedimento muito similar aos

apresentados anteriormente. Este comando apenas faz uma selecção do canal onde

vão ser executadas as operações futuras. Por exemplo enviando {B,0x64,A,3} é

indicado que se vai realizar um comando („B‟), sem compressão, em que a operação é

Selecção de Canais („A‟) e selecciona-se o canal 3 da imagem (3). A resposta é „f‟

seguido da imagem; neste caso nenhum processamento é efectuado (Figura 3.10).

29

Figura 3.10 – Protocolo de Comunicação da operação Base de Selecção de Canais

No caso da operação Base de Binarização („S‟) existem 2 protocolos semelhantes aos

já descritos:

- {B,0x64,S,0} quando não se pretende realizar a operação

- {B,0x64,S,1} quando se pretende que a binarização seja realizada segundo o método

de Ostu.

No caso da binarização manual o protocolo é diferente, uma vez que não se envia o

caracter „S‟, e é enviado {B,0x64,Min,Max}. No método de binarização implementado

os pixéis com valores de nível de cinzento entre o Min e Max vão ficar com o valor 255

os restantes pixéis com o valor 0. A Figura 3.11 (a) e (b) apresenta esquematicamente

o protocolo da binarização.

(a) (b)

Figura 3.11 – Protocolo de Comunicação da operação Base de Binarização (a) None e

Método de Ostu (b) Manual

Em cada um destes comandos uma imagem é adquirida da câmara do Aibo e é

enviada ao objecto da classe CColorImage para processamento.

Nas linhas de código seguintes pode observar-se o processo de aquisição da imagem

(event.Data(0)), a criação do objecto imgAibo (imgAibo=new CColorImage(w,h);), a

conversão da imagem do formato YCrCb para a classe CColorImage

30

(ConvertAibo2CImgTrueColorYCbCr) e finalmente a aplicação do filtro de média

(pImage->MorphologicalRankOperation).

void

RCServer::Notify(const ONotifyEvent& event)

{

...

int imgSize;

bool imgResult;

//Take a picture

OFbkImageVectorData* fbkImageVectorData =

(OFbkImageVectorData*)event.Data(0);

OSYSPRINT((" //Take a picture()\n"));

if(!imgAibo)

{

OFbkImageInfo* info = fbkImageVectorData->GetInfo(ofbkimageLAYER_H);

byte* data = fbkImageVectorData->GetData(ofbkimageLAYER_H);

OFbkImage yImg(info, data, ofbkimageBAND_Y);

int w = yImg.Width();

int h = yImg.Height();

imgAibo=new CColorImage(w,h);

OSYSPRINT((" imgAibo=new CColorImage (w,h);\n"));

imgAibo->m_Channel2Proc=0x7;

}

ConvertAibo2CImgTrueColorYCbCr(fbkImageVectorData, ofbkimageLAYER_H);

...

if(imgAibo->m_Channel2Proc&0x1)

if (pImage=imgAibo->GetFrame(0))

pImage->MorphologicalRankOperation(CImgGray::RankOperationMean, 9, XOffsets,

YOffsets, Weights );

3.3.3 GetAllJoint

Para um melhor aproveitamento do tamanho da trama TCP/IP foi criado um protocolo

com uma trama de 56 bytes para enviar simultaneamente a informação de todas as

juntas do AIBO.

Em específico, este protocolo permite enviar o ângulo de apenas uma junta, de um

conjunto de juntas ou de todas as 18 juntas.

Na Tabela 3.1 apresenta-se a identificação de cada junta e a respectiva

correspondência com a designação Webots.

Índice das juntas no

array:

jointValues

Novo valor de

identificação usado no

comando

Valor de

identificação no

Webots

Nome da junta

0 0x01 0x01 Inclinação do Pescoço

1 0x02 0x02 Rotação Cabeça (Pan)

2 0x03 0x03 Inclinação da Cabeça

31

3 0x04 0x04 Boca

4 0x05 0x1F Perna frontal direita Swing

5 0x06 0x20 Perna frontal direita Flap

6 0x07 0x21 Perna frontal direita Joelho

7 0x08 0x0B Perna frontal esquerda

Swing

8 0x09 0x0C Perna frontal esquerda Flap

9 0x0A 0x0D Perna frontal esquerda

Joelho

10 0x0B 0x29 Perna traseira direita Swing

11 0x0C 0x2A Perna traseira direita Flap

12 0x0D 0x2B Perna traseira direita Joelho

13 0x0E 0x15 Perna traseira esquerda

Swing

14 0x0F 0x16 Perna traseira esquerda

Flap

15 0x10 0x17 Perna traseira esquerda

Joelho

16 0x11 0x33 Rotação Cauda (Pan)

17 0x12 0x34 Inclinação Cauda

Tabela 3.1 – Valores de Identificação das Juntas

A trama contém dois bytes iniciais correspondentes ao identificador. Este pode admitir

vários valores dependendo da actualização que se pretende executar.

A trama continua com 3 bytes por junta, num total de 54 bytes. Por junta, os 2 bytes

mais significativos transportam o ângulo e o byte menos significativo a acção a

executar sobre a junta. O valor zero para este byte significa que o valor da junta não

vai ser alterado.

Deste modo o array de 56 bytes tem a seguinte estrutura:

identificador,

ângulo, tipo de acção (junta 0)

…, …, …

ângulo, tipo de acção (junta 17)

Se o identificador tiver o valor de identificação de uma junta (valor entre 0x01 e 0x12),

apenas o valor dessa junta será actualizado e o array terá de ser preenchido da

seguinte forma:

32

Junta, ângulo, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,

0, 0, 0, 0, 0, 0.

Se o identificador tiver o valor 0x13 serão actualizados os valores de todas as juntas

independentemente do valor do byte do tipo de acção.

Se o identificador tiver o valor 0x15 serão actualizadas apenas os valores das juntas

com tipo de acção igual a 1. Desta forma quando se pretende este tipo de acesso a

estrutura terá de ser preenchida da seguinte forma:

0x13 ou 0x15,

ângulo para 0x01, 0 ou 1,

ângulo para 0x02, 0 ou 1,

ângulo para 0x03, 0 ou 1,

ângulo para 0x04, 0 ou 1,

ângulo para 0x05, 0 ou 1,

ângulo para 0x06, 0 ou 1,

ângulo para 0x07, 0 ou 1,

ângulo para 0x08, 0 ou 1,

ângulo para 0x09, 0 ou 1,

ângulo para 0x0A, 0 ou 1,

ângulo para 0x0B, 0 ou 1,

ângulo para 0x0C, 0 ou 1,

ângulo para 0x0D, 0 ou 1,

ângulo para 0x0E, 0 ou 1,

ângulo para 0x0F, 0 ou 1,

ângulo para 0x10, 0 ou 1,

ângulo para 0x11, 0 ou 1,

ângulo para 0x12, 0 ou 1);

As funções criadas para interpretar esta trama foram, SetALLJointPositions e

GetALLJointPositions com a seguinte sintaxe:

GetALLJointPositions( &jointValues[0], &jointValues[1], &jointValues[2],

&jointValues[3], &jointValues[4], &jointValues[5], &jointValues[6], &jointValues[7],

&jointValues[8], &jointValues[9], &jointValues[10], &jointValues[11], &jointValues[12],

&jointValues[13], &jointValues[14], &jointValues[15], &jointValues[16],

&jointValues[17]);

33

SetALLJointPositions( identificador,

ângulo, tipo de acção,

…, …

ângulo, tipo de acção);

3.4 Cross-Compiler

No objecto Controller foi necessário definir um objecto do tipo CColorImage bem como

o conjunto de métodos específicos para a manipulação dos parâmetros da câmara,

aquisição e processamento da imagem.

Em simultâneo e para garantir a portabilidade com o simulador Webots foram também

definidas as respectivas funções globais.

A título de exemplo apresenta-se o código para implementação da funcionalidade

impor o ganho na câmara (camera_set_gain) e a evocação de processamento de

imagem (process_and_camera_get_image).

class Controller : public OObject { ...

short CameraparameGain;

short CameraparameShutter;

short CameraparameWB;

unsigned char minThr,maxThr;

CColorImage *imgAibo;

enum ImageProcessingFunction {

IPC_NOOPER, // NO operations

IPC_ALLCHANNEL, // Select ALL channel operations

IPC_CH1,

IPC_CH2,

IPC_CH3,

IPC_RGB2HSV,

IPC_RGB2CIELAB,

IPC_RGB2HSL,

IPC_ERODE,

IPC_DILATE,

IPC_OPEN,

IPC_CLOSE,

IPC_MEAN,

IPC_GRADIENT,

IPC_LAPLACIAN,

IPC_BINARIZATION

};

ImageProcessingFunction imageProcessingfunction;

unsigned char *process_and_camera_get_image(DeviceTag t, int iPf);

void DoImageProcessingFunctions();

unsigned char *camera_get_image(DeviceTag t);

void YCrCb2RGB(byte y, byte cr, byte cb, byte* r, byte* g, byte* b);

void RGB2YCrCb(byte r, byte g, byte b, byte* y, byte* cr, byte* cb);

unsigned short camera_get_width(DeviceTag t);

unsigned short camera_get_height(DeviceTag t);

void camera_enable(DeviceTag t,unsigned short ms);

void camera_disable(DeviceTag t);

unsigned char *process_and_camera_get_image(DeviceTag t, int iPf);

unsigned short camera_get_gain(DeviceTag t);

void camera_set_gain(DeviceTag t, int v);

unsigned short camera_get_shutter(DeviceTag t);

void camera_set_shutter(DeviceTag t, int v);

unsigned short camera_get_WB(DeviceTag t);

34

void camera_set_WB(DeviceTag t, int v);

...

}

void camera_set_gain(DeviceTag t,int v)

{

return mySelf->camera_set_gain(t,v);

}

void

Controller::camera_set_gain(DeviceTag t, int v)

{

longword set;

switch(v)

{

case 1:

set=ocamparamGAIN_LOW;

OSYSPRINT(("\nGAIN LOW\n"));

break;

case 2:

set=ocamparamGAIN_MID;

OSYSPRINT(("\nGAIN MID\n"));

break;

case 3:

set=ocamparamGAIN_HIGH;

OSYSPRINT(("\nGAIN HIGH\n"));

break;

}

CameraparameGain=v;

OPrimitiveControl_CameraParam gain(set);

OPENR::ControlPrimitive(primitiveID[PrimitiveIndex(t)],oprmreqCAM_SET_GAIN,

&gain, sizeof(gain),0,0);

}

unsigned char *process_and_camera_get_image(DeviceTag t,int iPf)

{

return mySelf->process_and_camera_get_image(t,iPf);

}

unsigned char *

Controller::process_and_camera_get_image(DeviceTag t, int iPf)

{

GetImage2Webots=true;

if(imgAibo)

{

imageProcessingfunction=(ImageProcessingFunction)iPf;

DoImageProcessingFunctions();

ConvertCImgTrueColor2WebotsImg();

}

memcpy( img2Webots,imgData,3*208*160);

GetImage2Webots=false;

return img2Webots;

}

void

Controller::DoImageProcessingFunctions()

{

//DO IMAGE PROCESSING

CImgGray* pImage;

static int XOffsets[]={-1, 0, 1, -1, 0, 1, -1, 0, 1};

static int YOffsets[]={-1, -1, -1, 0, 0, 0, 1, 1, 1};

static int Weights[]={0, 0, 0, 0, 0, 0, 0, 0, 0};

static int WeightsMean[]={1, 1, 1, 1, 1, 1, 1, 1, 1};

static double WeightsLap[]={-1, -1, -1, -1, 8, -1, -1, -1, -1};

switch(imageProcessingfunction)

{

case IPC_ALLCHANNEL:

imgAibo->m_Channel2Proc=0x7;

OSYSPRINT((" Channel ALL - DONE\n"));

break;

case IPC_CH1:

imgAibo->m_Channel2Proc=0x1;

OSYSPRINT((" Channel CH1 - DONE\n"));

break;

35

case IPC_CH2:

imgAibo->m_Channel2Proc=0x2;

OSYSPRINT((" Channel CH2 - DONE\n"));

break;

case IPC_CH3:

imgAibo->m_Channel2Proc=0x4;

OSYSPRINT((" Channel CH3 - DONE\n"));

break;

case IPC_RGB2HSV:

imgAibo->ConvertRGB2HSV();

OSYSPRINT((" Conv RGB2HSV - DONE\n"));

break;

case IPC_RGB2CIELAB:

imgAibo->ConvertRGB2Lab();

OSYSPRINT((" Conv RGB2CIELab - DONE\n"));

break;

case IPC_RGB2HSL:

imgAibo->ConvertRGB2HSL();

OSYSPRINT((" Conv RGB2HSL - DONE\n"));

break;

case IPC_ERODE:

if(imgAibo->m_Channel2Proc&0x1)

if (pImage=imgAibo->GetFrame(0))

pImage-

>MorphologicalRankOperation(CImgGray::RankOperationErosion, 9, XOffsets, YOffsets,

Weights );

if(imgAibo->m_Channel2Proc&0x2)

if (pImage=imgAibo->GetFrame(1))

pImage-

>MorphologicalRankOperation(CImgGray::RankOperationErosion, 9, XOffsets, YOffsets,

Weights );

if(imgAibo->m_Channel2Proc&0x4)

if (pImage=imgAibo->GetFrame(2))

pImage-

>MorphologicalRankOperation(CImgGray::RankOperationErosion, 9, XOffsets, YOffsets,

Weights );

OSYSPRINT((" Morph Erode - DONE\n"));

break;

case IPC_DILATE:

if(imgAibo->m_Channel2Proc&0x1)

if (pImage=imgAibo->GetFrame(0))

pImage-

>MorphologicalRankOperation(CImgGray::RankOperationDilatation, 9, XOffsets, YOffsets,

Weights );

if(imgAibo->m_Channel2Proc&0x2)

if (pImage=imgAibo->GetFrame(1))

pImage-

>MorphologicalRankOperation(CImgGray::RankOperationDilatation, 9, XOffsets, YOffsets,

Weights );

if(imgAibo->m_Channel2Proc&0x4)

if (pImage=imgAibo->GetFrame(2))

pImage-

>MorphologicalRankOperation(CImgGray::RankOperationDilatation, 9, XOffsets, YOffsets,

Weights );

OSYSPRINT((" Morph Dilate - DONE\n"));

break;

case IPC_OPEN:

if(imgAibo->m_Channel2Proc&0x1)

if (pImage=imgAibo->GetFrame(0))

pImage-

>MorphologicalRankOperation(CImgGray::RankOperationErosion, 9, XOffsets, YOffsets,

Weights );

if(imgAibo->m_Channel2Proc&0x2)

if (pImage=imgAibo->GetFrame(1))

pImage-

>MorphologicalRankOperation(CImgGray::RankOperationErosion, 9, XOffsets, YOffsets,

Weights );

if(imgAibo->m_Channel2Proc&0x4)

36

if (pImage=imgAibo->GetFrame(2))

pImage-

>MorphologicalRankOperation(CImgGray::RankOperationErosion, 9, XOffsets, YOffsets,

Weights );

if(imgAibo->m_Channel2Proc&0x1)

if (pImage=imgAibo->GetFrame(0))

pImage-

>MorphologicalRankOperation(CImgGray::RankOperationDilatation, 9, XOffsets, YOffsets,

Weights );

if(imgAibo->m_Channel2Proc&0x2)

if (pImage=imgAibo->GetFrame(1))

pImage-

>MorphologicalRankOperation(CImgGray::RankOperationDilatation, 9, XOffsets, YOffsets,

Weights );

if(imgAibo->m_Channel2Proc&0x4)

if (pImage=imgAibo->GetFrame(2))

pImage-

>MorphologicalRankOperation(CImgGray::RankOperationDilatation, 9, XOffsets, YOffsets,

Weights );

OSYSPRINT((" Morph Open - DONE\n"));

break;

case IPC_CLOSE:

if(imgAibo->m_Channel2Proc&0x1)

if (pImage=imgAibo->GetFrame(0))

pImage-

>MorphologicalRankOperation(CImgGray::RankOperationDilatation, 9, XOffsets, YOffsets,

Weights );

if(imgAibo->m_Channel2Proc&0x2)

if (pImage=imgAibo->GetFrame(1))

pImage-

>MorphologicalRankOperation(CImgGray::RankOperationDilatation, 9, XOffsets, YOffsets,

Weights );

if(imgAibo->m_Channel2Proc&0x4)

if (pImage=imgAibo->GetFrame(2))

pImage-

>MorphologicalRankOperation(CImgGray::RankOperationDilatation, 9, XOffsets, YOffsets,

Weights );

if(imgAibo->m_Channel2Proc&0x1)

if (pImage=imgAibo->GetFrame(0))

pImage-

>MorphologicalRankOperation(CImgGray::RankOperationErosion, 9, XOffsets, YOffsets,

Weights );

if(imgAibo->m_Channel2Proc&0x2)

if (pImage=imgAibo->GetFrame(1))

pImage-

>MorphologicalRankOperation(CImgGray::RankOperationErosion, 9, XOffsets, YOffsets,

Weights );

if(imgAibo->m_Channel2Proc&0x4)

if (pImage=imgAibo->GetFrame(2))

pImage-

>MorphologicalRankOperation(CImgGray::RankOperationErosion, 9, XOffsets, YOffsets,

Weights );

OSYSPRINT((" Morph Close - DONE\n"));

break;

case IPC_MEAN:

if(imgAibo->m_Channel2Proc&0x1)

if (pImage=imgAibo->GetFrame(0))

pImage-

>MorphologicalRankOperation(CImgGray::RankOperationMean, 9, XOffsets, YOffsets,

WeightsMean );

if(imgAibo->m_Channel2Proc&0x2)

if (pImage=imgAibo->GetFrame(1))

37

pImage-

>MorphologicalRankOperation(CImgGray::RankOperationMean, 9, XOffsets, YOffsets,

WeightsMean );

if(imgAibo->m_Channel2Proc&0x4)

if (pImage=imgAibo->GetFrame(2))

pImage-

>MorphologicalRankOperation(CImgGray::RankOperationMean, 9, XOffsets, YOffsets,

WeightsMean );

OSYSPRINT((" Filter Mean - DONE\n"));

break;

case IPC_GRADIENT:

if(imgAibo->m_Channel2Proc&0x1)

if (pImage=imgAibo->GetFrame(0))

pImage-

>EdgeDetectionGradientOperator(CImgGray::GradientOperatorPrewitt);

if(imgAibo->m_Channel2Proc&0x2)

if (pImage=imgAibo->GetFrame(1))

pImage-

>EdgeDetectionGradientOperator(CImgGray::GradientOperatorPrewitt);

if(imgAibo->m_Channel2Proc&0x4)

if (pImage=imgAibo->GetFrame(2))

pImage-

>EdgeDetectionGradientOperator(CImgGray::GradientOperatorPrewitt);

OSYSPRINT((" Filter Gradient - DONE\n"));

break;

case IPC_LAPLACIAN:

if(imgAibo->m_Channel2Proc&0x1)

if (pImage=imgAibo->GetFrame(0))

pImage->Convolution(9, XOffsets, YOffsets, WeightsLap, 1);

if(imgAibo->m_Channel2Proc&0x2)

if (pImage=imgAibo->GetFrame(1))

pImage->Convolution(9, XOffsets, YOffsets, WeightsLap, 1);

if(imgAibo->m_Channel2Proc&0x4)

if (pImage=imgAibo->GetFrame(2))

pImage->Convolution(9, XOffsets, YOffsets, WeightsLap, 1);

OSYSPRINT((" Filter Laplacian - DONE\n"));

break;

case IPC_BINARIZATION:

if(imgAibo->m_Channel2Proc&0x1)

if (pImage=imgAibo->GetFrame(0))

{

unsigned char Level=pImage-

>ComputeBinarizationLevel(CImgGray::BinarizationLevelOstu);

pImage->Binarization(Level, false);

}

if(imgAibo->m_Channel2Proc&0x2)

if (pImage=imgAibo->GetFrame(1))

{

unsigned char Level=pImage-

>ComputeBinarizationLevel(CImgGray::BinarizationLevelOstu);

pImage->Binarization(Level, false);

}

if(imgAibo->m_Channel2Proc&0x4)

if (pImage=imgAibo->GetFrame(2))

{

unsigned char Level=pImage-

>ComputeBinarizationLevel(CImgGray::BinarizationLevelOstu);

pImage->Binarization(Level, false);

}

OSYSPRINT((" Segmentation Bin - DONE\n"));

break;

}

}

38

4 Fundamentos e implementação do módulo de

visão

Este módulo de visão consiste num conjunto de funções agrupadas, divididas em

classes, que implementam técnicas de processamento e análise de imagem.

Neste capítulo apresenta-se uma breve descrição teórica dos métodos e técnicas que

suportaram o desenvolvimento deste módulo, bem como a sua implementação.

4.1 Binarização

A binarização é um dos métodos mais simples de segmentação de imagens e é

frequentemente designada pelo seu termo anglo-saxónico: thresholding [27] [28].

Consiste na conversão de uma imagem em níveis de cinzento para uma imagem

binária (dois níveis), o que pode ser útil para separar a região correspondente ao

objecto de interesse da região que corresponde ao fundo, ou para apresentar uma

imagem num dispositivo de saída com um bit de resolução, ou seja, por exemplo, um

dispositivo de dois níveis, como uma impressora.

O processo de binarização baseia-se na separação de diferentes intensidades, sendo

atribuído tipicamente o valor “0” às intensidades não pretendidas e o valor “1” às

intensidades pretendidas.

Sendo uma imagem representada pelo sinal f(x,y), a binarização é a aplicação da

função: s = T(r), em que o operador T é aplicado a cada uma das coordenadas (x,y) da

imagem. r é o nível de intensidade de entrada e s o nível de intensidade de saída, tal

como se pode observar nas figuras 4.1 e 4.2 [22] [23] [24] [25] [26] [27] [28].

Figura 4.1 – Representação matemática de uma imagem

39

Figura 4.2 – Representação Matemática de uma Binarização [27]

A função T(r) compara o sinal de entrada com um valor de Limiar ou threshold (T),

escolhido como referência para a separação dos níveis de cinzento. O sinal de saída,

apresentado é obtido pela relação [22] [23] [24] [25] [26] [27] [28]:

𝑠 = 1 𝑝𝑎𝑟𝑎 𝑟 > 𝑇 0 𝑝𝑎𝑟𝑎 𝑟 < 𝑇

(1)

O valor do Limiar (T) pode ser obtido de através de dois métodos:

Adaptativo – Em que é executada uma análise da imagem, por exemplo através dos

métodos de Russ ou Ostu e é automaticamente determinado o limiar.

Manual - Assim como o nome indica o valor é indicado de forma manual pelo

utilizador.

Em aplicações mais complexas podem definir-se múltiplos limiares, de modo a que a

função T(r) seja aplicada a um intervalo de valores de intensidade da imagem original,

desta forma T = [ 𝑇1 𝑇2], [22] [23] [24] [25] [26] [27] [28].

4.1.1 Método adaptativo de Russ

Este método de binarização recorre a parâmetros estatísticos da imagem para

determinação do limiar. De uma forma resumida e através de uma representação

matemática tem-se:

L – número de níveis de cinzento

40

𝑔0 ,… ,𝑔𝑖 ,… ,𝑔𝐿−1 - Representação dos pixéis para um dado nível de cinzento

𝑛𝑖 - número de ocorrências de cada nível de cinzento, 𝑔𝑖

N - número total de pixéis

𝑝𝑖 - probabilidade de ocorrência de cada nível de cinzento, 𝑔𝑖

Seja :

𝜇 = gipi (2)

L−1

𝑖=0

a média dos níveis de cinzento da imagem e:

𝜎2 = (𝑔𝑖 − 𝜇)2𝑝𝑖𝑁

𝐿−1

𝑖=0

(3)

a variância dos níveis de cinzento da imagem [25] [29].

O valor de limiar é definido por 𝑇 = 𝜇 + 𝛼𝜎2, com α representando um valor

dependente da probabilidade de ocorrência de objectos relativamente ao fundo da

imagem. Este método recorre a uma estimativa do tipo de imagens a binarizar, de

forma a quantificar o valor de α [25] [29].

4.1.2 Método adaptativo de Ostu

Este método, tal como o método anterior, recorre a estatísticas extraídas da imagem.

Supondo que os pixéis da imagem se dividem por duas classes 𝐶0 e 𝐶1 , sendo o

limiar para a divisão 𝑔𝑘−1, isto é:

(𝑔0,…𝑔𝑘−1) Pertencem a 𝐶0

(𝑔𝑘 ,…𝑔𝐿−1) Pertencem a 𝐶1

a probabilidade de ocorrência das classes é dada por [29] [30]:

𝑝 𝐶0 = pi

K−1

𝑖=0

(4)

e

41

𝑝 𝐶1 = pi

L−1

𝑖=𝐾

= 1 − p C0 (5)

As médias de 𝐶0 e 𝐶1 são dadas por [29] [30]:

−𝜇0 = 𝜇(𝐾)

𝑤(𝐾) (6)

Com:

𝜇 𝐾 = gipi

K−1

𝑖=0

(7)

e:

𝑤(𝐾) = pi (8)

K−1

𝑖=0

−𝜇1 = 𝜇𝑇 − 𝜇(𝐾)

1 −𝑤(𝐾) (9)

Com:

𝜇𝑇 𝐾 = gipi

L−1

𝑖=0

(10)

w(K) e µ(K) são os momentos cumulativos de ordens zero e um do histograma até ao

nível 𝑔𝑘 , 𝜇𝑇 é a média global podendo ser expressa por [29] [30]:

𝜇𝑇 = 𝑤 𝐾 𝜇0 + 1 − 𝑤 𝐾 𝜇1 (11)

As variâncias por classe são expressas por [29] [30]:

𝜎02 =

(𝑔𝑖 − 𝜇0)2𝑝𝑖𝑤(𝐾)

𝐾−1

𝑖=0

(12)

𝜎12 =

(𝑔𝑖 − 𝜇1)2𝑝𝑖1 −𝑤(𝐾)

𝐾−1

𝑖=0

(13)

O limiar a utilizar, 𝑔𝑘 ;é tal que maximize uma das medidas λ, k e η, definidas como [30]

[24]:

42

𝜆 =𝜎0

2

𝜎𝑤2

(14)

𝑘 =𝜎𝑇

2

𝜎𝑤2 (15)

𝜂 =𝜎𝛽

2

𝜎𝑇2 (16)

Com:

𝜎𝑤2 = 𝑤 𝐾 𝜎0

2 + 1 −𝑤 𝐾 𝜎12 (17)

definindo a variância intra-classe,

𝜎𝛽2 = 𝑤 𝐾 𝜇0 − 𝜇𝑇

2 + 1 −𝑤 𝐾 𝜇1 − 𝜇𝑇 2 (18)

definindo a variância inter-classe e

𝜎𝑇2 = (

𝐿−1

𝑖=0

𝑔𝑖 − 𝜇𝑇 2𝑝𝑖) (19)

definindo a variância global.

O limiar de decisão é geralmente estabelecido pelo critério η, uma vez que é o que

apresenta o calculo mais simplificado, já que para o determinar basta determinar o

nível de cinzento 𝑔𝑘 , que maximize a expressão 𝜎𝛽2(𝐾) (𝜎𝑇

2 é definido para a imagem

como um todo) [29] [30].

4.1.3 Implementação

A implementação da binarização apresenta-se de seguida (método Binarization), bem

como o método ComputeBinarizationLevel que calcula o limiar de acordo com as

abordagens descritas atrás. Conforme se verifica pela análise da função é possível

inverter a imagem binária resultante, actuando para isso no argumento Invert da

função Binarization.

void CImgGray::Binarization(unsigned char MinLevel,unsigned char MaxLevel, bool Invert)

{

register int i;

unsigned char LowLevel, HighLevel;

43

LowLevel=(Invert) ? 255 : 0;

HighLevel=(Invert) ? 0 : 255;

for (i=m_Roi.ymin;i<m_Roi.ymax; i++)

for (int j=m_Roi.xmin;j<m_Roi.xmax;j++)

OIMG(j,i) = ( ((OIMG(j,i) > MinLevel) && (OIMG(j,i) < MaxLevel)) )

? LowLevel : HighLevel;

}

#define RUSSALPHA -1.0

unsigned char CImgGray::ComputeBinarizationLevel(int Type) // Russ, Ostu

{

double p[256];

register int i;

double m;

double v;

double N=m_Width*m_Height;

for (i=0; i<256; p[i++]=0);

for (i=m_Roi.ymin;i<m_Roi.ymax; i++)

for (int j=m_Roi.xmin;j<m_Roi.xmax;j++)

p[OIMG(j,i)] +=1.0;

for (i=0; i<256; i++)

p[i]/=N;

for (m=0,i=1; i<256; i++)

m+=(double)i*p[i];

for (v=0,i=0; i<256; i++)

v+=((double)i-m)*((double)i-m)*p[i]/N;

switch(Type) {

case BinarizationLevelRuss:

return (unsigned char)(m+v*RUSSALPHA);

case BinarizationLevelOstu:

// mt=m, vt=v

double mk, wk, m1, m0, vb, vbmax;

int vbmaxi, k;

wk=p[0];

if (wk==1.0)

vbmax=wk*(m*m);

else {

m1=m/(1.0-wk);

vbmax=wk*(m*m)+(1-wk)*(m1-m)*(m1-m);

}

for (i=1; i<256; i++) {

for (k=0,mk=wk=0.0; k<i; k++) {

mk+=(double)k*p[k];

wk+=p[k];

}

if (wk==1.0) {

m0=mk/wk;

vb=wk*(m0-m)*(m0-m);

}

else if (wk==0) {

m1=m-mk;

vb=(m1-m)*(m1-m);

}

else {

m1=(m-mk)/(1.0-wk);

m0=mk/wk;

vb=wk*(m0-m)*(m0-m)+(1-wk)*(m1-m)*(m1-m);

}

if (vb>vbmax) {

vbmax=vb;

vbmaxi=i;

}

}

return vbmaxi;

default:

return 0;

}

}

44

4.2 Detecção de Contornos

Este tipo de operação está normalmente associado a filtros passa-alto, pois removem

as baixas frequências evidenciando as transições de luminosidade e assim permitindo

a detecção dos contornos dos objectos. Desta forma é possível distinguir os objectos

do fundo dentro da imagem [24].

As operações de detecção de contornos implementadas neste trabalho são de dois

tipos: derivadas de primeira ordem, como é o caso do Gradiente e derivadas de

segunda ordem, como é o caso do Laplaciano.

A Figura 4.3 exemplifica a aplicação destes filtros a uma imagem.

Figura 4.3 – Exemplo da aplicação de filtros de detecção de contornos.

A figura 4.4 representa a aplicação dos operadores gradiente e laplaciano ao perfil de

uma linha da imagem. De acordo com esta figura verifica-se que o contorno é

detectado através do valor máximo do gradiente ou através dos zeros do laplaciano

[23] [24] [25] [26].

45

Figura 4.4 – Resultado da aplicação do gradiente e laplaciano a uma linha

de uma imagem [24].

4.2.1 Gradiente

Sendo uma imagem representada pelo sinal 𝑓 𝑥, 𝑦 (Figura 4.1.1.1), o gradiente é a

primeira derivada desse sinal, logo o gradiente (∇𝑓) de uma região 𝑓 é um vector com

módulo e direcção da maior variação em 𝑓 [22] [23] [24] [25] [26].

O cálculo do gradiente é feito segundo as duas direcções perpendiculares da imagem,

x e y. As componentes do gradiente são obtidas através da convolução da imagem

com os operadores de cada uma das direcções x e y: [24] [26]:

𝑔𝑥 = 𝑕𝑥 ∗ 𝑓 (20)

𝑔𝑦 = 𝑕𝑦 ∗ 𝑓 (21)

O módulo do gradiente é dado por [24] [26]:

𝐺 = 𝑔𝑥2 + 𝑔𝑦

2 (22),

e a direcção é dada por [24] [26]:

𝜃 = arctan 𝑔𝑦

𝑔𝑥 (23)

Existem várias aproximações aos operadores hy e hx [24] [26], apresentando-se na

Tabela 4.1 os mais frequentemente utilizados.

46

𝑔𝑦 𝑔𝑥

Geral −101 −1 0 1

Sobel −1 −2 −10 0 01 2 1

−1 0 1−2 0 2−1 0 1

Prewitt −1 −1 −10 0 01 1 1

−1 0 1−1 0 1−1 0 1

Roberts 0 1−1 0

1 00 −1

Tabela 4.1 – Operadores Gradiente [24] [26]

4.2.2 Laplaciano

O Laplaciano (∇2𝑓) é a segunda derivada do sinal 𝑓 𝑥,𝑦 [22] [23] [25], dado por:

𝛻2𝑓 =𝜕2𝑓

𝜕𝑥2+𝜕2𝑓

𝜕𝑦2 (24)

Os operadores mais frequentes usados para o cálculo do laplaciano são [23] [24] [25]

[26]:

−1

−1 4 −1−1

(25) −1 −1 −1−1 8 −1−1 −1 −1

(26)

Uma importante desvantagem do filtro laplaciano é a sua elevada sensibilidade ao

ruído existente nas imagens.

4.2.3 Implementação

A implementação do algoritmo de gradiente corresponde ao método

EdgeDetectionGradientOperator, no qual o argumento indica qual o tipo de operador a

usar. O Laplaciano recorre a uma implementação genérica do filtro de convolução

entre uma imagem e um operador matricial.

Filtro Gradiente:

#define SQRT2 1.414213562373

47

void CImgGray::EdgeDetectionGradientOperator

(

int Type // Sobel, Prewitt, Roberts

)

{

int x, y;

double gx, gy;

memcpy(m_pTImage, m_pOImage, m_Height*m_Width);

for (y=m_Roi.ymin+1; y<m_Roi.ymax-1; y++)

for (x=m_Roi.xmin+1; x<m_Roi.xmax-1; x++) {

switch(Type) {

case GradientOperatorRoberts:

gx=(double)TIMG(x+1,y-1)+

(double)TIMG(x+1,y)+(double)TIMG(x+1,y+1)-

(double)TIMG(x-1,y-1)-

(double)TIMG(x-1,y)-(double)TIMG(x-1,y+1);

gy=(double)TIMG(x-1,y-1)

+(double)TIMG(x,y-1)+(double)TIMG(x+1,y-1)-

(double)TIMG(x-1,y+1)-

(double)TIMG(x,y+1)-(double)TIMG(x+1,y+1);

break;

case GradientOperatorPrewitt:

gx=(double)TIMG(x+1,y-1)+

2.0*(double)TIMG(x+1,y)+(double)TIMG(x+1,y+1)-

(double)TIMG(x-1,y-1)-

2.0*(double)TIMG(x-1,y)-(double)TIMG(x-1,y+1);

gy=(double)TIMG(x-1,y-1)+

2.0*(double)TIMG(x,y-1)+(double)TIMG(x+1,y-1)-

(double)TIMG(x-1,y+1)-

2.0*(double)TIMG(x,y+1)-(double)TIMG(x+1,y+1);

break;

case GradientOperatorSobel:

gx=(double)TIMG(x+1,y-1)+

SQRT2*(double)TIMG(x+1,y)+(double)TIMG(x+1,y+1)-

(double)TIMG(x-1,y-1)-

SQRT2*(double)TIMG(x-1,y)-(double)TIMG(x-1,y+1);

gy=(double)TIMG(x-1,y-1)+

SQRT2*(double)TIMG(x,y-1)+(double)TIMG(x+1,y-1)-

(double)TIMG(x-1,y+1)-

SQRT2*(double)TIMG(x,y+1)-(double)TIMG(x+1,y+1);

break;

}

OIMG(x, y)=ADJUST((long)(sqrt(gx*gx+gy*gy)+0.5));

}

}

Filtro Laplaciano:

void CImgGray::Convolution

(

int N,

int * OffsetX,

int * OffsetY,

double * Weight,

double Denominator

)

{

double Value;

int x, y, i;

memcpy(m_pTImage, m_pOImage, m_Height*m_Width);

for (y=m_Roi.ymin; y<m_Roi.ymax; y++)

for (x=m_Roi.xmin; x<m_Roi.xmax; x++)

{

for (i=0; i<N && !Inside(x+OffsetX[i], y+OffsetY[i]); i++);

Value=(double)TIMG(x+OffsetX[i], y+OffsetY[i])*Weight[i];

for (; i<N; i++) {

if (Inside(x+OffsetX[i], y+OffsetY[i]))

Value+=(double)TIMG(x+OffsetX[i],

y+OffsetY[i])*Weight[i];

}

Value/=Denominator;

OIMG(x, y)=ADJUST(Value);

}

}

48

Exemplo de evocação dos métodos apresentados:

static double WeightsLap[]={-1, -1, -1, -1, 8, -1, -1, -1, -1};

pImage->Convolution(9, XOffsets, YOffsets, WeightsLap, 1);

pImage->EdgeDetectionGradientOperator(CImgGray::GradientOperatorPrewitt);

4.3 Operações Morfológicas

As operações morfológicas são operações que vão manipular a morfologia dos

objectos existentes numa imagem. A sua aplicação é particularmente relevante em

imagens binárias quando se quer eliminar ruídos resultantes da binarização ou

evidenciar pormenores do objecto [22] [23] [25].

Neste trabalho consideram-se duas operações base, a dilatação e a erosão, e duas

operações compostas, a abertura (Open) e o fecho (Close). A Figura 4.5 ilustra a

aplicação destas quatro operações a uma imagem.

Figura 4.5 – Esquema representativo das diferentes operações morfológicas

4.3.1 Erosão

Admitindo que A e B são conjuntos em Z2, a erosão de A por B define-se como [22]

[23] [24] [25] [26] [31]:

A B = {x | (B)x A } (27)

Isto significa que a erosão de A por B é o conjunto de todos os pontos x em que B

deslocado em x está contido em A [31].

Sendo B o elemento estruturante, o conjunto dos pontos onde B está sobreposto na

imagem define a vizinhança a ter em consideração [22] [23] [24] [25] [26] [31].

49

Considere-se o exemplo da Figura 4.6, em que o elemento estruturante está

representado a azul e o pixel central do elemento estruturante se encontra ilustrado

pela letra X. Quando se sobrepõe o elemento estruturante à imagem no ponto 23, a

vizinhança a ter em consideração é composta pelos pontos 17, 22, 23, 24 e 29.

Figura 4.6 – Imagem de 6x7 com elemento estruturante em estrela [31]

No cálculo da erosão duma imagem binária percorre-se o ponto central do elemento

estruturante (B) por todos os pontos da imagem pertencentes ao objecto (A = 1 lógico)

e desde que nenhum dos pontos pertença ao fundo (0 lógico) o ponto central é

considerado objecto (1 lógico) [31]. Recorrendo novamente ao exemplo anterior, ao

ponto 23, sobre o qual está sobreposto o ponto central do elemento estruturante, vai

ser atribuído o valor lógico:

1 - se o pixel 23 e todos os seus vizinhos também tiverem valor lógico 1, ou

0 - se pelo menos um dos pontos da vizinhança não tiver valor lógico 1, ou seja

pertencer ao fundo (0 lógico).

A aplicação da erosão resulta na redução do número de pontos do objecto e no

aumento do fundo, tal como ilustra na Figura 4.7. Nesta Figura o objecto A vai sofrer a

erosão pelo elemento estruturante B, que tem o ponto central assinalado com uma

textura diferente. O resultado é o objecto C, que tem sobreposto a uma cor clara o

objecto A para que melhor se entenda o efeito [22] [23] [24] [25] [26] [31].

50

Figura 4.7 – Exemplo da Erosão, A (Objecto), B (Elemento estruturante), C (Resultado

sobreposto ao original) [31].

Em linguagem informal pode descrever-se a erosão em 4 etapas:

1 - Posiciona-se a origem do elemento estruturante sobre o primeiro pixel da imagem

que vai sofrer a erosão.

2 - Calcula-se a diferença de cada par correspondente de valores de pixel do elemento

estruturante e da imagem.

3 - Acha-se o valor mínimo de todas essas diferenças, e armazena-se o pixel

correspondente na imagem de saída para este valor.

4 - Repete-se este processo para cada pixel da imagem que sofre erosão.

4.3.2 Dilatação

Admitindo que A e B são dois conjuntos em Z2, a dilatação de A por B define-se como

[22] [23] [24] [25] [26] [31]:

A B = {x | (Br)x A } (28)

Isto significa que a dilatação de A por B é o conjunto de todos os pontos x em que B,

reflectido e depois deslocado de x, é reunido com A, admitindo que A não é nulo [31].

A dilatação do objecto A por pelo elemento estruturante B é dada pelo conjunto dos

pontos em que pelo menos exista um ponto de A, com valor lógico 1, na vizinhança

definida por Br [22] [23] [24] [25] [26] [31].

A aplicação da dilatação resulta no aumento das dimensões dos objectos tal como se

pode ver na figura 4.8. Nesta figura o objecto A vai ser dilatado segundo o elemento

estruturante B, que tem o ponto central assinalado com uma textura diferente, sendo o

resultado o objecto C, que tem sobreposto a uma cor diferente o objecto A para que

melhor se entenda o efeito.

51

Figura 4.8 – Exemplo da Dilatação, A (Objecto), B (Elemento estruturante), C

(Resultado sobreposto ao original) [31]

Em linguagem informal pode descrever-se a dilatação em 4 etapas:

1 - Posiciona-se a origem do elemento estrutural sobre o primeiro pixel da imagem a

ser dilatada.

2 - Calcula-se a soma de cada par correspondente de valores de pixéis do elemento

estruturante e da imagem.

3 - Acha-se o valor máximo de todas essas somas, e armazena-se o pixel

correspondente na imagem de saída para este valor.

4 - Repete-se este processo para cada pixel da imagem a ser dilatada.

4.3.3 Abertura e Fecho (Open e Close)

A Abertura e o Fecho são consideradas operações compostas, uma vez que usam a

combinação das operações básicas erosão e dilatação, diferenciando-se pela

sequência das operações [22] [23] [24] [25] [26] [31]:

Abertura (Open)

Erosão + Dilatação

A B = (A B) B (29)

Fecho (Close)

Dilatação + Erosão

A B = (A B) B (30)

4.3.4 Implementação

O método MorphologicalRankOperation implementa as operações morfológicas de

dilatação e erosão, no qual o argumento Operation indica qual o tipo de operador a

usar.

52

void CImgGray::MorphologicalRankOperation

(

int Operation, // Minimum=Erosion, Maximum=Dilatation

int N,

int * OffsetX,

int * OffsetY,

int * Weight

)

{

long Value;

long Level;

long WeightSum;

int x, y, i;

memcpy(m_pTImage, m_pOImage, m_Height*m_Width);

for (y=m_Roi.ymin; y<m_Roi.ymax; y++)

for (x=m_Roi.xmin; x<m_Roi.xmax; x++)

{

for (i=0; i<N && !Inside(x+OffsetX[i], y+OffsetY[i]); i++);

Value=(long)TIMG(x+OffsetX[i],

y+OffsetY[i])+(long)Weight[i];

WeightSum=Weight[i];

for (; i<N; i++) {

if (Inside(x+OffsetX[i], y+OffsetY[i])) {

Level=(long)TIMG(x+OffsetX[i],

y+OffsetY[i])+(long)Weight[i];

switch(Operation) {

case RankOperationErosion :

if (Value>Level)

Value=Level;

break;

case RankOperationDilatation:

if (Value<Level)

Value=Level;

break;

default:

Value=Level;

}

}

}

OIMG(x, y)= ADJUST(Value);

}

}

Exemplo de evocação dos métodos apresentados:

static int XOffsets[]={-1, 0, 1, -1, 0, 1, -1, 0, 1};

static int YOffsets[]={-1, -1, -1, 0, 0, 0, 1, 1, 1};

static int Weights[]={0, 0, 0, 0, 0, 0, 0, 0, 0};

Erosão:

pImage->MorphologicalRankOperation(CImgGray::RankOperationErosion, 9, XOffsets,

YOffsets, Weights );

Dilatação:

pImage->MorphologicalRankOperation(CImgGray::RankOperationDilatation, 9, XOffsets,

YOffsets, Weights );

Abertura:

pImage->MorphologicalRankOperation(CImgGray::RankOperationErosion, 9, XOffsets,

YOffsets, Weights );

pImage->MorphologicalRankOperation(CImgGray::RankOperationDilatation, 9, XOffsets,

YOffsets, Weights );

Fecho:

pImage->MorphologicalRankOperation(CImgGray::RankOperationDilatation, 9, XOffsets,

YOffsets, Weights );

pImage->MorphologicalRankOperation(CImgGray::RankOperationErosion, 9, XOffsets,

YOffsets, Weights );

53

4.4 Conversão dos Espaços de Cor

Cada espaço de cor está tradicionalmente associo para um componente electrónico

específico. São disso exemplo o RGB que está associado a ecrãs CRT para a

transmissão da imagem; o YCrCb que está associado à transmissão de imagem; e o

CMY que está associado a impressoras. Outros espaços de cor foram criados para

estabelecer o paralelismo com o sistema de visão humano, são disso exemplos o

CIELab e o HCL.

Neste projecto a informação a tratar é proveniente de um sensor CMOS (YCrCb) ou de

ficheiros de imagem pré-adquiridas (RGB) pelo que estes espaços de cor foram a

base para a maior parte das conversões a realizar [25] [32] [33] [34].

A Figura 4.9 ilustra as componentes de cor para os espaços de cor RGB, HSI, YCrCb

e CIELab.

Figura 4.9 - Esquema representativo da conversão em Espaços de Cor

4.4.1 RGB

Os fundamentos que dão origem a este espaço de cor baseiam-se na teoria dos três

estímulos, em que cada um dos 3 tipos de cones presentes no olho humano, reage a

um diferente estímulo da luz em gamas de comprimento de onda distintos: Red, Green

54

e Blue [32]. A distribuição das cores neste espaço pode ser representada como um

cubo assente na origem dos eixos (Figura 4.10).

Figura 4.10 – Espaço de cores RGB [34]

4.4.2 YCrCb

Neste espaço de cor o Y está associado a luminosidade, enquanto que o Cr e o Cb

estão associados às componentes de cromaticidade, mais especificamente ao

vermelho e azul.

A forma de conversão deste espaço de cor depende da norma usada. Neste trabalho

recorreu-se à norma REC 601-1 que estipula um valor 0,2989 para o vermelho, 0,5866

para o verde e 0,1145 para o azul [25] [32] [34] [35] [36]. Donde resulta o seguinte

sistema de equações [25] [32] [34] [35] [36] [37]:

𝑌 = 0,2989 ∗ 𝑅 + 0,5866 ∗ 𝐺 + 0,1145 ∗ 𝐵𝐶𝑟 = 0,5 ∗ 𝑅 − 0,4184 ∗ 𝐺 − 0,0816 ∗ 𝐵 𝐶𝑏 = −0,1688 ∗ 𝑅 − 0,3312 ∗ 𝐺 + 0,5 ∗ 𝐵

(31)

Aplicando algumas simplificações obtem-se:

𝑌 = 0,299 ∗ 𝑅 + 0,587 ∗ 𝐺 + 0,114 ∗ 𝐵𝐶𝑟 = 𝑅 − 𝑌 . 0,713 + ∆ 𝐶𝑏 = 𝐵 − 𝑌 . 0,564 + ∆ ∆ = 128

(32)

A Figura 4.11 mostra a distribuição espacial da palete de cor.

55

Figura 4.11 – Distribuição espacial das cores no espaço de cor YCrCb [34]

4.4.3 HSV

O HSV foi criado para que o ser humano tivesse uma forma mais intuitiva de obter as

cores e melhor poder observar a sua distribuição.

Os três parâmetros constituintes do HSV são [25] [32] [34] [35] [36] [37]:

Tonalidade (H-Hue): Abrangendo todas as cores do espectro. Admite

valores entre 0 e 360, mas em algumas aplicações é usada uma

normalização entre 0 e 100%.

Saturação (S-Saturation): Está relacionado com a pureza das cores da

imagem, ou seja quanto menor esse valor, mais cinza aparecerá a imagem.

Admite valores entre 0 e 100%.

Valor ou brilho(V - Value): Define a intensidade do estimulo visual. Admite

valores entre 0 e 100%.

Na figura 4.12 pode observar-se a distribuição espacial das cores para o espaço HSV.

56

Figura 4.12 – Distribuição espacial das cores no espaço de cores HSV [34]

Considerando os valores de R, G e B normalizados entre 0.0 e 1.0, a conversão para

HSV é feita de acordo com as expressões 35 a 37. MAX e MIN são os valores

máximos e mínimo, respectivamente, dos valores (R, G, B) [25] [32] [34] [35] [36] [37]:

𝐻 =

60 ∗

𝐺 − 𝐵

𝑀𝐴𝑋 −𝑀𝐼𝑁+ 0, 𝑀𝐴𝑋 = 𝑅 𝑒 𝐺 ≥ 𝐵

60 ∗𝐺 − 𝐵

𝑀𝐴𝑋 −𝑀𝐼𝑁+ 360, 𝑀𝐴𝑋 = 𝑅 𝑒 𝐺 < 𝐵

60 ∗𝐵 − 𝑅

𝑀𝐴𝑋 −𝑀𝐼𝑁+ 120, 𝑀𝐴𝑋 = 𝐺

60 ∗𝐺 − 𝐵

𝑀𝐴𝑋 −𝑀𝐼𝑁+ 240, 𝑀𝐴𝑋 = 𝐵

(33)

𝑆 =𝑀𝐴𝑋 −𝑀𝐼𝑁

𝑀𝐴𝑋 (34)

𝑉 = 𝑀𝐴𝑋 (35)

No resultado, os valores de tonalidade (H) estão compreendidos entre 0 e 360 e a

saturação (H) e o valor/brilho (V) compreendidos entre 0.0 e 1.0.

4.4.4 𝐂𝐈𝐄𝐱𝐲𝐳

O standard de cores CIE está baseado num sistema de cor XYZ que não existe

fisicamente. Este sistema imaginário baseia-se na curva de resposta dos três

receptores dos olhos humanos. Permite passar de um sistema de cor dependente do

57

mecanismo de aquisição para um sistema adaptado ao “observador humano

standard”. A Figura 4.13 mostra a distribuição espacial deste espaço de cor.

Figura 4.13 – Distribuição espacial das cores no espaço de cor 𝐶𝐼𝐸𝑥𝑦𝑧 [34]

Após a normalização dos valores RGB para o intervalo entre 0.0 e 1.0, a conversão

para CIExyz é feita de acordo com as expressões 39 a 44, admitindo o “observador

standard” de 2º e o iluminante D65:

R = R ∗ 100 (36)

G = G ∗ 100 (37)

B = B ∗ 100 (38)

X = R ∗ 0.412453 + G ∗ 0.357580 + B ∗ 0.180423 (39)

Y = R ∗ 0.212671 + G ∗ 0.715160 + B ∗ 0.072169 (40)

Z = R ∗ 0.019334 + G ∗ 0.119293 + B ∗ 0.950227 (41)

4.4.5 𝐂𝐈𝐄𝐥𝐚𝐛

O CIElab tem como base o CIExyz (1931). O gráfico da Figura 4.14 apresenta a

distribuição das cores segundo o espaço de cor CIElab .

58

Figura 4.14 – Distribuição espacial das cores no espaço de cor 𝐶𝐼𝐸𝑙𝑎𝑏 [34]

A conversão de CIExyz (1931) para CIElab é efectuado da seguinte forma:

𝑈 =

𝑋

95,0456𝑌

100𝑍

108,8756

(42)

𝑓 𝑈 = 𝑈

13 𝑝𝑎𝑟𝑎 𝑈 > 0,008856

7,787.𝑈 +16

116 𝑝𝑎𝑟𝑎 𝑈 ≤ 0,008856

(43)

𝑙∗ = 116.𝑓

𝑌

100 − 16

𝑎∗ = 500. 𝑓 𝑋

95,0456 − 𝑓

𝑌

100

𝑏∗ = 200 𝑓 𝑌

100 − 𝑓

𝑍

108,8756

(44)

4.4.6 HCL

Criado por razões muito similares ao HSV, este espaço de cor é proveniente do CIElab .

Os seus constituintes são:

Tonalidade (H-Hue): Abrangendo todas as cores do espectro. Admite

valores entre 0 e 360, mas em algumas aplicações é usado o valor

normalizado que admite valores entre 0 e 100%.

59

Cromaticidade (C-Chroma): Está relacionado com quantidade de branco da

imagem, ou seja quanto maior esse valor, mais “pura” será a imagem.

Admite valores entre 0 e 100%.

Luminosidade (L-Luminosity): Define a Luminosidade. Admite valores entre

0 e 100%.

A Figura 4.15 ilustra a distribuição espacial das diferentes cores para o espaço de cor

HCL.

Figura 4.15 – Distribuição espacial das cores no espaço de cores HCL [34]

A conversão a partir do CIElab é feita da seguinte forma:

H = 0 para a∗ = 0

H = 180o

π∗ π+ arctan

b∗

a∗

C = a∗2 + b∗2 L = l∗

(45)

4.4.7 Implementação

A título de exemplo apresenta-se alguns métodos de transformação de espaço de cor

implementados no módulo de visão, bem como a forma da sua evocação.

void CColorImage::ConvertRGB2HSL()

{

double H, S, L;

double r,g,b;

for(int i=m_Roi.xmin; i<m_Roi.xmax;i++)

for(int j=m_Roi.ymin;j<m_Roi.ymax;j++)

{

r=(double)m_pTrueColorImage[0]->GetLevel(i,j)/255.0;

g=(double)m_pTrueColorImage[1]->GetLevel(i,j)/255.0;

60

b=(double)m_pTrueColorImage[2]->GetLevel(i,j)/255.0;

RGB2HSL(r, g, b, &H,&S,&L);

m_pTrueColorImage[0]->SetLevel(i,j,(unsigned char)(H*255.0));

m_pTrueColorImage[1]->SetLevel(i,j,(unsigned char)(S*255.0));

m_pTrueColorImage[2]->SetLevel(i,j,(unsigned char)(L*255.0));

}

}

void CColorImage::RGB2HSL(double r, double g, double b, double *h,double *s,double *l)

{

double H,S,L, delta;

double cmax = max(r,max(g,b));

double cmin = min(r,min(g,b));

L=(cmax+cmin)/2.0;

if(cmax==cmin)

{

S = 0;

H = 0; // it's really undefined

}

else

{

if(L < 0.5)

S = (cmax-cmin)/(cmax+cmin);

else

S = (cmax-cmin)/(2.0-cmax-cmin);

delta = cmax - cmin;

if(r==cmax)

H = (g-b)/delta;

else if(g==cmax)

H = 2.0 +(b-r)/delta;

else

H=4.0+(r-g)/delta;

H /= 6.0;

if(H < 0.0)

H += 1;

}

(*h)=H;

(*s)=S;

(*l)=L;

}

void CColorImage::ConvertRGB2HSV()

{

double H, S, V;

double r,g,b;

for(int i=m_Roi.xmin; i<m_Roi.xmax;i++)

for(int j=m_Roi.ymin;j<m_Roi.ymax;j++)

{

r=(double)m_pTrueColorImage[0]->GetLevel(i,j)/255.0;

g=(double)m_pTrueColorImage[1]->GetLevel(i,j)/255.0;

b=(double)m_pTrueColorImage[2]->GetLevel(i,j)/255.0;

RGB2HSV(r, g, b, &H,&S,&V);

m_pTrueColorImage[0]->SetLevel(i,j,(unsigned char)(H*255.0));

m_pTrueColorImage[1]->SetLevel(i,j,(unsigned char)(S*255.0));

m_pTrueColorImage[2]->SetLevel(i,j,(unsigned char)(V*255.0));

}

}

void CColorImage::RGB2HSV(double r, double g, double b, double *h,double *s,double *v)

{

double H,S,V;

double cmax = max(r,max(g,b));

double cmin = min(r,min(g,b));

V=max(r,max(g,b));

61

if(V!=0.0)

S=(V-min(r,min(g,b)))/V;

if (V==r)

H=(g-b)*60.0/S;

if (V==g)

H=180.0+(b-r)*60.0/S;

if (V==b)

H=240.0+(r-g)*60.0/S;

(*h)=H/360.0;

(*s)=S;

(*v)=V;

}

void CColorImage::ConvertRGB()

{

double r,g,b;

double H,S,L;

for(int i=m_Roi.xmin;i<m_Roi.xmax;i++)

for(int j=m_Roi.ymin;j<m_Roi.ymax;j++)

{

H=(double)(m_pTrueColorImage[0]->GetLevel(i,j)/255.0);

S=(double)(m_pTrueColorImage[1]->GetLevel(i,j)/255.0);

L=(double)(m_pTrueColorImage[2]->GetLevel(i,j)/255.0);

HSL2RGB(&r, &g, &b, H,S,L);

m_pTrueColorImage[0]->SetLevel(i,j,(unsigned char)(r*255.0));

m_pTrueColorImage[1]->SetLevel(i,j,(unsigned char)(g*255.0));

m_pTrueColorImage[2]->SetLevel(i,j,(unsigned char)(b*255.0));

}

}

double CColorImage::RGB2Gray(double R, double G, double B)

{

return (0.299*R + 0.587*G + 0.114*B);

}

Exemplo de evocação dos métodos apresentados:

imgAibo->ConvertRGB2HSV();

imgAibo->ConvertRGB2Lab();

imgAibo->ConvertRGB2HSL();

62

5 Caso de aplicação – Coreografia sincronizada por

visão

A validação do módulo de visão desenvolvido foi efectuada através da sua integração

num projecto que visava a geração de movimentos das patas dianteiras do AIBO,

controlados por música, recorrendo a sistemas dinâmicos não lineares.

A integração do módulo de visão neste projecto vai permitir que o AIBO reconheça

cores e diâmetros de círculos, que surgem no monitor, para posteriormente fornecer

essa informação a um sistema dinâmico que realiza uma dança dinâmica.

Para tal foi também desenvolvido um módulo, designado por Oscilloscope, que gera

círculos com tamanhos, cores e posição no monitor dependentes da música.

5.1 Oscilloscope

Esta ferramenta tem como objectivo gerar manchas coloridas (círculos) num ecrã

controladas por uma música, para serem reconhecidas pelo robô. Ou seja, pretendeu-

se controlar o tamanho, posição e cor dos círculos através da informação do espectro

musical.

Usando como ponto de partida o programa open source desenvolvido por [38] foi

criado o analisador de som, que se designou de Oscilloscope. Este analisa as

frequências e a potência do som para criar as imagens dos círculos coloridos, as quais

podem ser apresentados num monitor ou transferidos para o simulador Webots. Na

Figura 5.1 é mostra-se o esquema de funcionamento desta ferramenta.

Figura 5.1 – Esquema de Funcionamento do Oscilloscope

A posição dos círculos no ecrã foi predefinida de acordo com a representação da

Figura 5.2. Cada círculo foi também virtualmente numerada de 1 a 8. Num som

constituída por 2 canais (estéreo), canal direito e esquerdo, é possível extrair

63

informação espectral de cada um. Deste modo, ao canal esquerdo fez-se

corresponder os círculos 1,2,3 e 4, e ao canal direito os restantes.

Figura 5.2 – Disposição dos círculos no monitor

A Figura 5.3 mostra a caixa de diálogo (Audio Scope) na qual é apresentada a

informação de cada canal.

Figura 5.3 – Caixa de diálogo onde é feita a apresentação do som analisado.

Através das barras L (canal esquerdo) e R (canal direito) é feita a representação da

potência (power meter) em que se utiliza os 10 MSB (Most Signiffcant Bits) dos 16 Bits

que fazem parte do WAVE PCM. Isto significa que cada uma das barras tem 1024

estados possíveis. Os 10 MSB definem da seguinte forma o círculo colorido que vai

ser apresentado no monitor:

Se no power meter qualquer um dos canais se encontrar entre 0 e 255 a

barra L desenha o círculo 1 e a barra R o círculo 5;

Se no power meter qualquer um dos canais se encontrar entre 256 e 511 a

barra L desenha o círculo 2 e a barra R o círculo 6;

64

Se no power meter qualquer um dos canais se encontrar entre 512 e 701 a

barra L desenha o círculo 3 e a barra R o círculo 7;

Se no power meter qualquer um dos canais se encontrar entre 702 e 1023

a barra L desenha o círculo 4 e a barra R o círculo 8;

Se no power meter qualquer um dos canais se encontrar entre 0 e 255 a

barra L desenha o círculo 1 e a barra R o círculo 5;

Na Janela Audio Scope para além das barras do power meter existe uma outra

representação da informação dos canais, em que para cada canal estão contempladas

10 barras. Estas equivalem ao espectro de frequências, que vai de 0 a 22,05KHz,

representando cada barra um intervalo com amplitude de 2,2KHz desse espectro.

Cada uma destas barras mede graficamente 3276 UM (Unidades de Medida), o que

significa que cada barra corresponde a 0,67Hz/UM. É através da análise da

distribuição da informação espectral por estes intervalos que se define a cor de cada

círculo, ou seja se a barra com valor mais alto for:

barra 2 ou 1 (frequências entre 0 e 4.4KHz) - não são tomadas em

consideração para a escolha de uma cor;

a barra 4 ou 3 (frequências entre 4.4 KHz e 8.8 KHz) - o círculo admite a

cor vermelha;

barra 6 ou 5 (frequências entre 8.8 KHz e 13.2 KHz) - o círculo admite a cor

verde;

barra 8 ou 7 (frequências entre 13.2 KHz e 17.6 KHz) - o círculo admite a

cor azul;

barra 10 ou 9 (frequências entre 17.6 KHz e 22 KHz) - o círculo admite a

cor amarela.

Os círculos não só admitem oito posições e quatro cores, como também podem ter

três diâmetros diferentes. Os diâmetros admissíveis são:

d1 = 3 cm (104 pixels)

d2 = 5 cm (184 pixels)

d3 = 6,5 cm (234 pixels)

Estes valores foram estabelecidos para um monitor de 17” com resolução de

1024x768 pixéis e para uma imagem gerado pelo programa com 1015x740 pixéis.

65

O diâmetro dos círculos é seleccionado através do valor médio das 10 barras de cada

canal, da seguinte forma:

Inferior a 395Hz o circulo admite o diâmetro d1

Entre 395Hz e 794Hz o círculo admite o diâmetro d2

Entre 794Hz e 2205Hz o círculo admite o diâmetro d3

De forma a permitir uma melhor compreensão deste módulo considere-se o seguinte

exemplo:

Os canais esquerdo e direito têm na barra de representação do power meter valores

de 854 e 901, respectivamente. Desta forma os círculos a desenhar serão o 4 por

indicação da barra associada ao canal esquerda e o 8 por indicação da barra

associada ao canal direito.

Na representação por barras, o valor mais elevado do canal esquerdo é o da barra 3

com 804,67 Hz, definindo a cor vermelha e o valor mais elevado do canal direito é o da

barra 7 com 761,76 Hz, definindo a cor azul.

O valor médio dos 10 barras do canal esquerdo é 1009 Hz, definindo o diâmetro d3 e

do canal direito é 1103,49 Hz, definindo também o diâmetro d3.

O resultado final apresenta-se na Figura 5.4 Consiste numa imagem com um círculo

de cor vermelha e diâmetro d3, na posição 4 definido pela informação do canal

esquerdo e um círculo de cor azul e diâmetro d3 na posição 8 definido pela informação

do canal direito.

Figura 5.4 – Imagem do Exemplo Dado

66

5.2 Sistema de visão

O módulo de visão é usado neste projecto para identificar a posição, a cor e o

tamanho de cada uma das manchas presente no ecrã. Com este objectivo foi

especificado um sistema de visão que recorre a diferentes métodos implementados no

módulo de visão desenvolvido. Figura 5.5 apresenta o diagrama de blocos do sistema

de visão desenvolvido. Após a aquisição da imagem e conversão para o espaço de cor

RGB é aplicado um filtro passa baixo para remoção de ruído, após o qual é aplicada a

segmentação para se obter a imagem binária. O filtro abertura remove ruído resultante

da binarização. Após a obtenção da imagem binária são determinadas a posição e

dimensão de cada círculo no referencial do AIBO. A conversão do referencial imagem

para o referencial AIBO faz-se recorrendo ao modelo pinhole da câmara e ao

conhecimento prévio da distância (valor Z) a que esta se encontra do monitor.

Figura 5.5 – Arquitectura do sistema de visão.

Para obter os limiares de binarização por canal RGB foi projectada a imagem da

Figura 5.6 no monitor. A partir desta imagem, adquirida pelo AIBO, resultou o gráfico

apresentado na Figura 5.7, que representa a dispersão de cores no espaço RGB. Da

análise desta dispersão é possível extrair os diferentes limiares de binarização para

cada uma das quatro cores envolvidas. A imagem binária apresenta valor 0 para o

fundo e 255 para a região do círculo.

Filtro Média

Analise região

Pinhole Model

Pose 3D

Imagem RGB

Imagem Binária

P1(u,v); P2(u,v)

P1(x,y); P2(x,y) Valor Z

CM (X,Y); dx, dy

Aquisição Imagem

Segmentação

Filtro Abertura

Conversão 2 RGB

Imagem YCrCb

67

Figura 5.6 – Círculos de teste de cor

Figura 5.7 – Detecção de Cor

Cada metade do monitor tem activa um único círculo pelo que a análise de regiões se

resume à identificação dos pixéis com nível de cinzento 255, calculando a posição

xmin, ymin (P1), xmax e ymax (P2) conforme se ilustra na Figura 5.8

Figura 5.8 – Detecção de Círculos

68

Após a determinação dos pontos P1 e P2, o passo seguinte foi a detecção do tamanho

e do ponto central do círculo, através de:

Dimensão em X - Dx = Umax-Umin (46)

Dimensão em Y - Dy = Vmax-Ymin (47)

Coordenada X do Ponto Central - Ox = Umin+ ((Dx)/2) (48)

Coordenada Y do Ponto Central - Oy = Vmin1+ ((Dy)/2) (49)

A conversão destes valores de pixels (referencial câmara) para mm (referencial AIBO)

é efectuada recorrendo ao modelo pinhole da câmara [39]. De acordo com a Figura

5.9, este modelo estima o raio que passa pelo centro de projecção (ponto C), pelo

ponto da imagem (m=(u,v)) e pelo ponto no referencial mundo M=(X,Y,Z).

Neste modelo, para uma imagem estática, um ponto no mundo (X,Y,Z) é projectado

num ponto da imagem (u,v), o qual pode ser obtido através da transformação

perspectiva da equação 50.

1100

0

1

y

x

cf

csf

v

u

yy

xx

(50)

x = X/Z, y = Y/Z; (cx,cy) são as coordenadas do ponto principal em pixels (C – centro

óptico); fx, fy são as distancias focais expressas em pixels calculadas através de:

fx=f/Px e fy=f/Py, com Px e Py a largura e altura do pixel; s é o factor que reflecte o

quanto rectangular é o pixel, sendo o seu valor 0.

69

Figura 5.9 – Representação do modelo pinhole

A matriz assim definida é designada por matriz dos parâmetros intrínsecos. Este

modelo, para um sistema de visão real, deve ter em consideração a distorção radial e

tangencial da lente. Uma das aproximações é estender o modelo da seguinte forma:

)2(2)1(' 22

21

6

3

4

2

2

1 xrpxyprkrkrkxx (51)

xypyrprkrkrkyy 2

22

1

6

3

4

2

2

1 2)2()1(' (52)

222 yxr (53)

xx csyxfu '' (54)

yy cyfv ' (55)

Com k1, k2 e k3 os coeficientes de distorção radial. E p1, p2 os coeficientes da

distorção tangencial. Estes parâmetros não dependem da cena pelo que são também

considerados parâmetros intrínsecos do sistema.

Nesta aplicação os parâmetros usados são os apresentados pelo Tekkotsu e Tira-

Thompson [2004], ver tabelas 5.1 e 5.2.

Após a aplicação do modelo da câmara ao centro do círculo obtêm-se os valores x,y

dos centros relativos ao referencial normalizado do sistema de visão. O cálculo dos

valores no referencial AIBO recorre às equações 56 e 57 e ao valor Z pré-definido.

X=Z*x (56)

70

Y=Z*y (57)

No simulador a abordagem seguida é idêntica mas considera-se a câmara ideal, isto é,

sem distorção radial e tangencial.

X(pixéis) Y(pixéis)

Distancias Focais 198.807 200.333

Coordenadas do centro óptico de projecção 102.689 85.0399

Tamanho da Imagem 208 160

Tabela 5.1 – Referencias de transformação

1 2 3

Coeficientes de distorção radial -0.147005 0.38485 0

Coeficientes de distorção tangencial -0.00347777

0.00012873

Tabela 5.2 – Coeficientes de distorção

71

6 Conclusão

O trabalho apresentado conduziu ao desenvolvimento de um conjunto de módulos de

software que permitem tirar partido das funcionalidades do robô AIBO da Sony e do

simulador desenvolvido pela Cyberbotics, Lda – Webots. Em especifico foi criado um

módulo de visão, constituído por um conjunto de classes C++, e foram estendidos os

seguintes módulos de software: Painel de Controlo do Webots, RCServer e o cross-

compiler. Estes desenvolvimentos representam uma contribuição relevante para a

evolução do simulador, na medida em que foram já incluídos no Webots a partir da

versão 5.3 (Figura 6.1).

Figura 6.1 – Folheto de divulgação do Webots de Junho de 2007

Através do simulador Webots recorrendo ao Painel de Controlo ou ao módulo de

cross-compiler, as novas funcionalidades acrescidas ao software já existente permitem

controlar os parâmetros da câmara, adquirir imagens da câmara do AIBO, efectuar

processamento e extrair informação da imagem.

Na criação do módulo de visão contemplaram-se algoritmos de processamento e

análise de imagem que permitem a remoção de ruídos, a segmentação baseada em

cor e a extracção de contornos. A arquitectura deste módulo foi definida de tal forma

que a sua divisão em classes assegura a independência relativamente ao sistema de

desenvolvimento e ao sistema operativo alvo. O seu carácter modular permite ainda a

integração futura de novos algoritmos de imagem tais como o chain code e

reconhecimento de padrões.

Em trabalho futuro, relativamente ao software da Cyberbotics Ltd, pode ser dada

continuidade aos melhoramentos feitos, tais como a criação de novos protocolos de

comunicação que permitirão aumentar a eficiência da comunicação entre o Webots e o

RCServer.

72

7 Bibliografia

[1] Haralick, Robert M., Shapiro, Linda G., “Computer and Robot Vision”

(Volume I e Volume II). Addison Wesley Longman, 2002

[2] http://www.eu.aibo.com – Sony AIBO página oficial europeia - último acesso feito

em Junho de 2008

[3] Cyberbotics Ltd. Webots Reference Manual

[4] Cyberbotics Ltd. Webots User Guide

[5] Raphael Haberer-Proust, “Remote control of the Aibo camera from Webots”, project

semestral, Swiss Federal Institute of Technology Lausanne, 2006

[6] Ricardo A. Téllez, “Introduction to the Aibo programming environment”,

http://www.ouroboros.org/aibo.html, 17 de Julho de 2005

[7] François Serra, Jean-Christophe Baillie, “AIBO programming using OPEN-R SDK”,

Tutorial, ENSTA, Junho 2003

[8] Lukas Hohl, “Aibo Simulation in Webots and Controller Transfer to Aibo Robot”,

Summer Semester Project, Swiss Federal Institute of Technology Lausanne, 2004

[9] Lukas Hohl, “Wireless Remote Control and Monitoring of an Aibo Robot”, Winter

Semester Project, Swiss Federal Institute of Technology Lausanne, 2003/2004

[10] Sony Corporation, “Installation Guide”, 2004

[11] Sony Corporation, “OPEN-R Internet Protocol Version4”, 2004

[12] Sony Corporation, “Level2 Reference Guide”, 2004

[13] Sony Corporation, “Model Information for ERS-7”, 2004

[14] Sony Corporation, “OPEN-R SDK Programmer's Guide”, 2004

[15] Francisco Martín Rico, “Open-R: un enfoque práctico”, Relatório Técnico,

Robotic Lab, GSyC, 2004

[16] http://www.urbiforge.com/eng/ - URBI página oficial - último acesso feito em

Outubro de 2007

[17] http://www-2.cs.cmu.edu/~tekkotsu/ - Tekkotsu página oficial - último acesso feito

em Outubro de 2007

[18] http://pyrorobotics.org/ - Pyro página oficial – último acesso feito em 2/11/2007

[19] http://aibo.sourceforge.net/aibo_resources.html - Cognitive Vision página oficial -

último acesso feito em 2 de Outubro de 2007

[20] http://www.cs.cmu.edu/~jbruce/cmvision/ - Carnegie Mellon - “The CORAL Group's

Color Machine Vision Project” - último acesso feito em 28 de Maio de 2008

[21] http://www.wxwidgets.org/ - wxWidgets – último acesso feito em Julho 2008

[22] Rafael C. Gonzalez, Richard E. Woods, “Digital Image Processing”, Second

Edition, Prentice Hall, 2002.

73

[23]William K. Pratt, “Digital Image Processing - PIKS Scientific Inside”, Fourth Edition,

Wiley-Interscience, 2007

[24] Luís Paulo Peixoto dos Santos, “Visão por Computador”, Departamento de

Informática, Universidade do Minho, 03 de Março de 1995

[25] Russ, John C., “The image processing handbook”, Second Edition, Boca Raton,

CRC Press, 1995

[26] João Luís Sobral, “Visão por Computador”,

http://gec.di.uminho.pt/lesi/vpc0607/guioes.html, Notas de estudo, 2006

[27] http://www.ic.uff.br/~aconci/curso/binari~3.htm , Aura Conci, Texto de Apoio

[28] www.cee.hw.ac.uk/hipr/html/threshld.html - Bob Fisher, Simon Perkins Ashley

Walker, Erik Wolfart, “Hyper Media Image Processing Reference – Thresholding” -

último acesso feito em Outubro de 2007

[29] Manuel João Ferreira, “Aplicação de Técnicas de Processamento de Imagem ao

Controlo da Qualidade na Linha de Produção em Indústrias Tradicionais”, Tese de

Mestrado, Universidade do Minho, 1996

[30] Shapiro L., Stockman G., “Computer Vision”, Prentice-Hall, 2001

[31] http://homepage.esoterica.pt/~rscf/apsi_e3/introducao.html - Ricardo Sérgio

Caetano Ferreira, “Aplicações de Processamento de Imagem e Sinal” - última acesso

feito em Junho de 2008

[32] ColorLock™ da Silicon Graphics ,Guia do Usuário, Número do documento 007-

3939-001PTB

[33] http://www.handprint.com/HP/WCL/color7.html#CIELUV - Bruce MacEvoy,

“modern color models” – último acesso feito Junho de 2008

[34] Philippe Colantoni and Al, “Color Space Transformations”, couleur.org, 2004

[35] http://www.cs.rit.edu/~ncs/color/t_convert.html - Eugene Vishnevsky, “Color

Conversion Algorithms” - último acesso feito em Julho de 2008

[36] http://www.easyrgb.com/index.php?X=MATH – EasyRGB, “Color conversion math

and formulas” - último acesso feito em Julho de 2008

[37] http://www.sourceforge.net/projects/opencvlibrary/ - Página Oficial do OPENCV –

último acesso feito em Junho de 2008

[38] http://www.codeproject.com/audio/oscilloscope.asp - Steven De Toni, Steven De

Toni, “Simple audio out oscilloscope and spectrum analyzer" – último acesso feito em

27 de Julho de 2006.

[39] Ballard, D.H., Brown, C.M. “Computer Vision”, Prentice-Hall – 1982