• Nenhum resultado encontrado

Visão Robótica - e detecção de movimento

N/A
N/A
Protected

Academic year: 2021

Share "Visão Robótica - e detecção de movimento"

Copied!
162
0
0

Texto

(1)

RELATÓRIO DE PROJETOS 2

(2)

INE – DEPARTAMENTO DE INFORMÁTICA E ESTATÍSTICA

Visão Robótica – Detecção de Movimento

Autor:

Carlos Eduardo Lenz

Orientador: Mauro Roisenberg

Banca Examinadora:

Jorge Muniz Barreto

Jovelino Falqueto

(3)

Sumário

Lista de Figuras ...V

Lista de Abreviaturas...VII

Resumo ... VIII

1. Introdução ...1

1.1 Objetivos ... 1

1.2 Motivação ... 2

1.3 Estrutura do Trabalho ... 2

2. Processamento Digital de Imagens ...4

2.1 Etapas... 4

2.2 Ferramentas ... 6

2.2.1 Histograma de Tons-de-Cinza ... 6

2.2.1.1 Contraste Normal ... 7

2.2.1.2 Baixo Contraste... 7

2.2.1.3 Alto Contraste ... 8

2.2.2 Operações Pontuais... 8

2.2.3 Operações Algébricas ... 10

2.2.4 Segmentação ... 10

2.2.4.1 Segmentação de Imagens por Limiarização ... 11

(4)

2.2.4.2 Estrutura da Imagem Segmentada ... 13

2.3 Medidas e Classificação... 13

2.3.1 Medidas de tamanho... 14

2.3.2 Medidas de forma ... 14

2.3.3 Classificação ... 15

2.3.3.1 Probabilidades... 15

2.3.3.2 Regra de Decisão ... 15

2.3.3.3 Treinamento ... 15

2.3.3.4 Performance ... 15

3. Robótica...17

3.1 Robô ... 18

3.2 Histórico... 18

3.3 Lego RCX ... 18

3.3.1 Hardware ... 19

3.3.3 LegOS... 21

3.3.3.1 Biblioteca de funções do LegOS ... 22

3.3.3.1.1 Motores ... 22

3.3.3.1.2 Sensor de Luz ... 22

3.3.3.1.3 Sensor de Toque ... 23

3.3.3.1.4 LCD ... 23

3.3.3.1.5 Botões ... 23

3.3.3.1.6 Processos ... 24

3.3.3.2 O Protocolo LNP ... 24

3.3.3.2.1 Integrity Messages ... 25

3.3.3.2.2 Addressing Messages ... 25

3.3.3.2.3 Funções do LegOS para comunicação ... 26

(5)

4.1 Captura e Processamento das Imagens ... 28

4.1.1 Classe Região... 28

4.1.2 Classe CBitmapEx ... 28

4.1.3 Classe CFrameGrabber ... 29

4.1.4 Classe CAboutDlg ... 29

4.1.5 Classe CFrameGrabberTestApp... 30

4.1.6 Classe CMainFrame ... 30

4.1.7 Classe CFrameGrabberTestView ... 30

4.1.7.1 Método OnTimer ... 31

4.1.8 Classe CFrameGrabberTestDoc ... 33

4.1.8.1 Método ProcessImage... 33

4.1.8.2 Método Limiarizar... 35

4.1.8.3 Método SeparaRegioes ... 36

4.1.8.4 Método Envia ... 36

4.2 Comunicação ... 37

4.2.1 Classe CComm ... 37

4.2.2 Classe CTower... 38

4.2.3 Classe CLNP... 38

4.2.4 Camada de Transporte... 38

4.3 Controle do Robô ... 42

4.3.1 Processo de Segurança para Permanência do Robô na Arena ... 43

4.3.2 Processo Tratador de Pacotes Recebidos... 44

5. Experimento ...46

5.1 Objetivo... 47

5.2 Robô ... 47

5.3 Interface do Programa ... 47

5.4 Resultados... 49

6. Conclusão ...50

6.1 Sugestões para Trabalhos Futuros ... 50

Referências Bibliográficas ...52

Anexo A – Código Fonte ...53

(6)

Lista de Figuras

Figura 2.1 – Imagem em tons de cinza ... 5

Figura 2.2 – Imagem RGB... 5

Figura 2.3 – Imagem com contraste normal ... 7

Figura 2.4 – Histograma do canal verde da imagem 2.3... 7

Figura 2.5 – Imagem com baixo contraste. ... 7

Figura 2.6 – Histograma do canal vermelho da imagem 2.5... 8

Figura 2.7 – Imagem com alto contraste... 8

Figura 2.8 – Histograma do canal azul da imagem 2.7. ... 8

Figura 2.9 – Imagem obtida através de: f(x) = 255 – x ... 9

Figura 2.10 – Imagem limiarizada com limiar “lim = 100” ... 12

Figura 3.1 – RCX... 19

Figura 3.2 – Motor ... 20

Figura 3.3 – Sensores de luz(cor) e toque. ... 20

Figura 3.4 – Torre de comunicação infra-vermelha ... 21

Figura 3.5 – Programa criado pela Lego para desenvolvimento do robô ... 21

Figura 3.6 – Formato das Integrity Messages ... 25

Figura 3.7 – Formato das Addressing Messages ... 25

Figura 4.1 – Visão Geral do sistema. ... 27

Figura 4.2 – Janela Sobre ... 29

Figura 4.3 – Janela Principal com um quadro capturado. ... 30

Figura 4.4 – Método de Suavização ... 32

Figura 4.5 – Reta usada para determinar a direção do robô ... 36

Figura 4.6 – Sucesso... 39

Figura 4.7 – Pacote perdido... 40

Figura 4.8 – ACK perdido. ... 40

Figura 4.9 – Timeout Prematuro. ... 41

Figura 4.10 – Pacote corrompido. ... 41

Figura 4.11 – ACK corrompido... 41

Figura 4.12 – Máquina de estados finitos versão Robô. ... 42

(7)

Figura 4.14 – Esquema de funcionamento do programa de controle do robô. ... 43

Figura 5.1 – Arena pronta para o experimento... 46

Figura 5.2 – Menu Controle -> Processador de Imagens. ... 48

Figura 5.3 – Menu Controle -> Cor... 48

(8)

Lista de Abreviaturas

ACK

Acknowledgment

PC

Personal

Computer

RGB

Red-Green-Blue

USB

Universal Serial Bus

MIT

Massachusetts Institute of Technology

ROM

Read Only Memory

RAM

Random Access Memory

GCC

GNU Compiler Collection

GNU

GNU's Not Unix

SO

Sistema

Operacional

IEEE

Institute of Electrical and Electronics Engineers

POSIX

Portable Operating System Interface

LCD

Liquid Crystal Display

CPU

Central Processing Unit

LNP

LegOS Networking Protocol

MFC

Microsoft Foundation Classes

OSI

Open Systems Interconnect

(9)

Resumo

Este trabalho busca estudar as técnicas de reconhecimento de padrões em

imagens que servem a sistemas de visão robótica. Para tanto as ferramentas de

processamento digital de imagens são apresentadas e implementadas em um programa.

Assim o problema de navegação de robôs autônomos é resolvido através da detecção de

movimento em imagens captadas por uma câmera digital. A comunicação entre o robô e

uma unidade controladora que é responsável pela câmera também é tratada.

A implementação consiste de um sistema completo de visão computacional que

permite o estudo de diferentes aspectos do controle de robôs, como a detecção de alvos

ou de intrusos, a navegação e comunicação com uma unidade de controle.

Palavras-chave: robótica, processamento digital de imagens, reconhecimento de

padrões, visão robótica, navegação de agentes autônomos.

(10)

1. Introdução

Nestas últimas décadas a Revolução Industrial tem atingido seu ápice. Após

séculos buscando a construção de sistemas para execução de tarefas mecânicas,

construímos os robôs. Estes não são mais controlados por complexos mecanismos

mecânicos, mas por programas em software ou diretamente em hardware (isto é,

microchips). Assim, substituindo o programa de controle, temos um robô com

capacidades completamente diferentes.

A popularização e crescente capacidade de processamento dos microchips,

aliados a um mercado de trabalho cada vez mais qualificado (principalmente nos países

desenvolvidos) e conseqüentemente avesso à possibilidade de operar máquinas pesadas

manualmente, levaram ao desenvolvimento de robôs para as mais variadas tarefas.

Eventualmente essas tarefas têm ficado cada vez mais complexas e os robôs cada vez

mais sofisticados.

Muitos robôs hoje já são controlados ou navegados com base em imagens, em

vez de usar apenas os mais tradicionais sensores. Principalmente os robôs autônomos

que precisam juntar todas essas informações para navegar pelo seu ambiente e

oferecendo as reações corretas aos estímulos. Isto é, com respostas precisas.

A Visão Computacional emprega várias técnicas, algoritmos e ferramentas

matemáticas para analisar imagens estáticas ou em movimento (isto é, quadros de um

vídeo). Seja para identificar objetos, reconhecer padrões, detectar obstáculos ou resolver

problemas de navegação, entre outros, a Visão Computacional usa os recursos

disponibilizados a partir dos avanços no Processamento Digital de Imagens.

Combinando a Visão Computacional às restrições dos robôs, que contam com

processadores limitados e operam em ambientes desconhecidos ou vastos demais, surge

a Visão Robótica. As informações fornecidas são então processadas junto de outras

vindas de vários tipos sensores para determinar o procedimento do robô, em alguns

casos também se baseando na experiência passada.

1.1 Objetivos

(11)

movimento, para isso elas são implementadas em um programa e testadas em um

experimento. Avaliar também a qualidade das respostas do robô, sua navegabilidade na

busca de um alvo quando acontece a identificação de um alvo.

Isto é, foi implementado em PC um programa para detecção de movimento

voltado para a plataforma onde o robô Lego Mindstorms © é operado. Integrando robô e

PC através de transmissão infravermelho, permitindo ao robô seguir com precisão em

direção de qualquer intruso na cena.

Aplicam-se a esse trabalho somente as técnicas de Visão Computacional para a

detecção de movimento, e possivelmente também alguma técnica básica de tratamento

de imagens para auxiliar a análise ou melhorar os resultados.

1.2 Motivação

Com base nessa realidade, a motivação para este trabalho é encontrada na

possibilidade de contribuir e fornecer um auxílio aos alunos e simpatizantes da área de

robótica e visão computacional, fornecendo em linhas gerais um estudo prático sobre o

controle e navegação de robôs usando o método de navegação baseada em visão

robótica.

1.3 Estrutura do Trabalho

O capítulo 2 consiste de relatório da pesquisa feita na área de Processamento

Digital de Imagens, detalhando as principais ferramentas que poderão ser empregadas

na implementação do programa.

A

Robótica é introduzida no capítulo 3, junto com uma descrição do robô Lego

usado na implementação deste trabalho. Outras características importantes como as

ferramentas de desenvolvimento e a câmera também descritas aqui.

Finalmente a proposta de Implementação é detalhada no capítulo 4. As técnicas

de Processamento Digital de Imagens usadas são descritas, junto com os parâmetros

utilizados. As limitações ou características do robô e do sistema de comunicação são

também analisadas e as soluções obtidas apresentadas. Topologia, número de neurônios,

função de transferência, entradas e saídas da rede neural usada no controle do robô

também são justificadas. O sistema como um todo é descrito, junto com a função de

cada módulo.

(12)

O Experimento que foi feito para validar o programa é apresentado no capítulo

5. Os resultados obtidos bem como uma avaliação do funcionamento do sistema

também faz parte deste capítulo.

As Conclusões, como resultados práticos, dificuldades encontradas e limitações

da plataforma Lego, ou dos equipamentos usados nos testes encontram-se no capítulo 6.

Sugestões de trabalhos futuros também estão neste capítulo.

(13)

2. Processamento Digital de Imagens

Na sua ânsia de registrar os acontecimentos, o homem já criou vários métodos

de capturar imagens. Todas essas técnicas e tecnologias permitiram que surgisse a

captura de imagens através da digitalização, que permitiram armazenar e manipular

imagens no computador.

O Processamento Digital de Imagens pode ser divido em várias etapas:

2.1 Etapas

A digitalização de imagens é justamente o processo de transferir as informações

de cor, forma, etc presentes na imagem para uma forma compreensível para o

computador. Nesse processo a imagem é transformada de um sinal analógico para um

digital (discreto).

A origem dessa imagem pode ser uma cena real captada por uma lente ou um

papel com um desenho (ou foto) que os sensores de um scanner reconhecem. Ou

mesmo uma câmera digital, como neste trabalho.

Exceto para uma possível análise e correção dos mecanismos de digitalização, a

origem da imagem ou método de digitalização não importam mais, a partir do momento

que as informações estão no computador.

No computador a imagem é representada como uma grade de pixels. Pode-se

considerar que os pixels são os menores elementos distinguíveis numa imagem digital,

portanto são às vezes chamados de pontos.

O tamanho dessa grade determina a dimensão da imagem. Por exemplo:

640x480 pixels. A quantidade de pontos que um dispositivo digitalizador pode

reconhecer por polegada é uma característica importante que recebe o nome de

resolução.

Existem várias formas de codificar as cores. Dois formatos muitos populares são

o grayscale, que representa tons de cinza apenas, e o RGB, que representa a cor como

uma combinação de vermelho, verde, e azul. As escalas de cinza usam um número de

bits que varia de acordo com o número de tons de cinza que se deseja representar,

tipicamente até 256. Assim para representar 8 tons são usados 3 bits por ponto.

(14)

Tipicamente o 0 (zero) representa o preto e o 255 o branco.

Figura 2.1 – Imagem em tons de cinza

No caso da RGB usam-se 8 bits para representar até 256 valores para cada cor.

Tendo 8 bits de vermelho, 8 bits de azul e 8 bits de verde é possível representar

qualquer cor que um monitor atual pode mostrar. Essa combinação das 3 cores pode

representar até 2 ^ 24 cores e é chamada True Color. O próprio olho humano não

consegue diferenciar muitas das cores mais próximas. Também é usada uma graduação

que representa cada cor por um número real entre 0 e 1.

Figura 2.2 – Imagem RGB

A etapa de Pré-processamento visa corrigir defeitos básicos da imagem, muitas

vezes surgidos durante o processo de aquisição. Durante essa esta etapa pode ser feito

um realce em determinas características da imagem. Também nessa fase defeitos

observados durante a digitalização podem ser corrigidos, como imagens de alto ou

baixo contraste.

A Segmentação é a etapa mais crítica e visa distinguir os elementos da imagem

entre si e do fundo. Permite agrupar pixels contíguos em regiões. Devido à ausência de

(15)

um modelo formal, esse processo que tenta imitar o complexo processo cognitivo

realizado pelo cérebro humano, tornando-se basicamente empírico. Mas para corrigir

eventuais falhas desse processo pode existir uma etapa seguinte, de

Pós-processamento.

Com os objetos que compõem a imagem já separados, chega a etapa de

Extração de Atributos, que obtém informações sobres esses objetos, como medidas de

diâmetro, largura, aspecto, e outros. Com esses dados é possível fazer a Classificação e

reconhecimento dos objetos na cena.

2.2 Ferramentas

Embora as técnicas abordadas daqui para frente se refiram a tons-de-cinza, elas

também podem ser aplicadas para imagens coloridas, operando sobre cada cor primária

em separado.

2.2.1 Histograma de Tons-de-Cinza

Entre as operações mais simples sobre imagens digitais está o histograma. Esta

operação pode revelar muita informação sobre uma imagem. Consiste de uma função

mostrando quantas vezes cada tom aparece na imagem. O histograma mostra o

tom-de-cinza no eixo das abscissas enquanto a freqüência de ocorrências está no das ordenadas.

Quando é produzido um histograma, toda a informação espacial é perdida.

Entretanto isso não afeta seus principais usos: detectar quando a digitalização não

encontrou bons resultados, ou indicar que transformações a aplicar na imagem.

Imagens com baixo-contraste são aquelas que onde vários tons não são usados.

Assim a imagem ocupa mais espaço que o necessário. Já o contrário também é ruim,

pois os detalhes são perdidos. Esse problema aparece através de picos nas extremidades

do histograma (0 e 256).

(16)

2.2.1.1 Contraste Normal

Figura 2.3 – Imagem com contraste normal

Figura 2.4 – Histograma do canal verde da imagem 2.3.

2.2.1.2 Baixo Contraste

(17)

Figura 2.6 – Histograma do canal vermelho da imagem 2.5.

2.2.1.3 Alto Contraste

Figura 2.7 – Imagem com alto contraste.

Figura 2.8 – Histograma do canal azul da imagem 2.7.

2.2.2 Operações Pontuais

Outro tipo de operação simples sobre imagens digitais é a operação pontual.

Diferente do histograma, a operação pontual toma uma imagem como entrada e produz

(18)

outra como saída. Ao contrário de outras técnicas usadas mais a diante, nesta operação a

cor de um ponto é apenas dependente da cor do mesmo ponto na imagem original, e não

de outros pontos.

Matematicamente falando a nova imagem B é gerada pela imagem A assim:

B(x,y) = f[A(x,y)]

Assim se a função f é linear:

f(x) = ax + b

Esse caso (quando f é linear) recebe um nome próprio: Operações Lineares

sobre pontos (linear point operations) e merece uma análise especial sobre seus

parâmetros a e b.

a) Quando

a é 1 (um) e b é 0 (zero), a imagem não se altera.

b) O contraste é reduzido quando a é menor que 1 (um) e incrementado quando é

maior.

c) Quando a é 1 (um) e b é diferente de 0 (zero), a imagem inteira é escurecida ou

clareada.

d) Finalmente a negativo inverte (complementa) as cores. O que é claro fica escuro

e vice-versa.

Figura 2.9 – Imagem obtida através de: f(x) = 255 – x

Operações pontuais podem acrescentar contornos à imagem. Ou também

limiarização, que divide a imagem em regiões disjuntas baseado nos tons-de-cinza, o

que permite definir fronteiras ou a construção de máscaras para outras operações. Com a

escolha de uma função f adequada a imagem gerada terá o histograma desejado,

retangular ou gaussiano, ajudando na comparação de imagens digitalizadas de modos

(19)

diferentes.

2.2.3 Operações Algébricas

Para juntar 2 imagens existem as operações algébricas, que tomam as imagens

ponto-a-ponto e realizam uma operação matemática básica (adição, subtração,

multiplicação ou divisão por uma constante). Essas operações podem ser combinadas e

a operação pode ser qualquer função com dois argumentos.

A adição de imagens é aplicada freqüentemente em seqüências de imagens com

ruído aleatório, reduzindo o mesmo na imagem resultante. Pode também ser usada para

colar uma imagem sobre a outra.

Para remover um padrão presente na imagem a subtração é usada. Esse padrão

pode ser um padrão de sombreamento no fundo da imagem ou um ruído periódico. A

subtração também é usada para detectar movimento, computando as diferenças entre

imagens da mesma cena, ou no cálculo do gradiente que é usado para detectar bordas.

A operação de multiplicação pode ser usada junto de máscaras para borrar partes

duma imagem deixando intactas as partes de interesse.

2.2.4 Segmentação

Para realizar uma análise no conteúdo de uma imagem, é importante primeiro

segmentá-la, isto é, encontrar suas partes: os objetos da cena. Muitos estudos foram

feitos e existem inúmeras metodologias para fazer a segmentação de imagens, como o

chamado Reconhecimento de Padrões Óticos. Essa estratégia assume que a imagem

contém vários objetos e seu objetivo é encontrá-los, distinguindo entre os vários tipos.

Numa primeira etapa todos os objetos da imagem são encontrados e separados

uns dos outros e do resto da imagem. Em seguida cada objeto é analisado em separado,

e algumas informações são então extraídas. Essas medidas são postas num vetor de

características que é usado pela última etapa, que classifica os objetos entre os diversos

tipos reconhecidos pelo sistema.

O projeto de um sistema de reconhecimento de padrões pode ser dividido em 5

partes:

a) O projeto do localizador de objetos envolve a escolha do algoritmo para a

separação de objetos na cena.

(20)

b) A seleção das propriedades que melhor permitirão a posterior classificação

acontece na seleção de características.

c) O estabelecimento do algoritmo de classificação com base na matemática e da

estrutura de classificação ocorre na fase de projeto do classificador.

d) Os parâmetros onde o classificador permite ajustes são corrigidos durante o

treinamento do classificador.

e) Os erros de classificação devem ser determinados, finalizando todo o projeto

com a avaliação de performance.

Definições: A segmentação particiona uma imagem em regiões distintas. Região é um

conjunto de pixels conectados. Nesse todos os pixels são adjacentes ou se tocam. Entre

dois pixels quaisquer num conjunto conectado, existe um caminho conectando ambos.

Existem duas perspectivas para a segmentação de imagens. Numa os pixels são

analisados e agrupados pela cor em regiões (aproximação por regiões). Noutra os

contornos entre as regiões são localizados primeiro (aproximação por contornos).

2.2.4.1 Segmentação de Imagens por Limiarização

Essa técnica de aproximação por regiões é simples e rápida. É útil para cenas

com objetos sólidos sobre um fundo com o qual contrastam. Nela todos os pixels com

tom de cinza igual ou maior ao limiar fazem parte do objeto, mas os outros não. Assim

as bordas são todos o pixels pertencentes à região que tocam pixels fora da região.

Para que a limiarização funcione bem, o objeto deve ter em seu interior um tom

de cinza uniforme, e o fundo também, sendo ambos os níveis diferentes. Se esse não é o

caso, mas ocorre outra propriedade que atende esses requisitos, então essa propriedade

pode ser convertida para tom de cinza para que a técnica seja aplicada.

(21)

Figura 2.10 – Imagem limiarizada com limiar “lim = 100”

Limiarização Global: nesse tipo o limiar é mantido constante por toda a imagem.

Limiarização Adaptativa: quando o contraste entre o objeto e o resto da cena varia ao

longo da imagem, uma função que varia lentamente conforme a posição na imagem

pode ser usada como limiar.

Em geral, a variação do valor do limiar pode ter um considerável impacto no

tamanho do objeto, a menos que a imagem tenha margens muito íngremes. Por isso,

para não prejudicar as medidas futuras (baseadas na forma e tamanho do objeto), a

escolha de um método ótimo, ou quase, é importante. Baseando-se num histograma

onde estejam presentes os dois picos que caracterizam o contraste entre o objeto e o

fundo, o ponto de mínimo entre os 2 pontos de máximo é uma boa aproximação para

um valor de limiar.

2.2.4.1.1 Limiarização da Imagem Gradiente

Esta técnica foi criada por Kirsh, e é do tipo “aproximação por contorno”. Nela,

uma limiarização é aplicada sobre a imagem gradiente com um limiar relativamente

baixo. Esse limiar é gradualmente aumentado até que as partes pertencentes ao objeto e

ao fundo se toquem. Nesse momento os pontos de encontro são os contornos. É um

método lento e só funciona se a primeira limiarização não uniu o objeto com o fundo. O

gradiente é uma função que aplicada aos pontos da imagem apresenta valores altos para

áreas com declives íngremes, como as bordas de um objeto.

(22)

2.2.4.2 Estrutura da Imagem Segmentada

O método mais simples (mas que desperdiça recursos) consiste em usar uma

nova imagem para guardar os objetos encontrados na imagem original. Os objetos

seriam diferenciados então por uma codificação de cores, uma para cada objeto.

Outra alternativa seria codificar apenas os contornos de cada objeto em

separado, guardando duas coordenadas (x,y) onde o contorno começa e uma série de

códigos de bits indicando qual dos pixels adjacentes é a continuação do contorno.

Os objetos também podem ser codificados por linhas, indicando para cada linha

o início e fim de cada segmento acima do limiar. Essa técnica tem a vantagem de se

encaixar perfeitamente no processamento de uma limiarização e de facilitar a extração

de informações importantes como área, perímetro, comprimento, largura e outras.

2.3 Medidas e Classificação

Para distinguir objetos de tipos diferentes é preciso que as características que

possam diferenciar os mesmos sejam extraídas da imagem segmentada e enviadas ao

classificador. Essas características são uma descrição do objeto que, se bem escolhidas,

podem tornar o processo de classificação mais eficaz.

Obviamente, nem todas as possíveis características são calculadas. Embora esse

processo seja intuitivo, 4 avaliações podem ser feitas para ajudar na escolha das

características que serão implementadas:

1. Distinção: os valores das características avaliadas devem ser significativamente

diferentes entre objetos de tipos diferentes. Ex: se os objetos devem ser

classificados entre grandes e pequenos, o diâmetro pode diferenciá-los.

2. Confiabilidade: os objetos de mesma classe devem ter valores similares. Ex:

diferenciar frutas pela cor pode não ser confiável se elas apresentarem diferenças

na cor dependendo de sua maturação.

3. Independência: não devem ser usadas características que sejam altamente

correlatas.

4. Poucas informações: com muitas características para avaliar torna-se lento o

treinamento do classificador porque sua complexidade cresce exponencialmente.

Poucas informações não correlatas favorecem a performance.

(23)

O classificador teve muitas estruturas investigadas, mas muitas decisões são

basicamente uma regra de limiarização. Tendo o projeto do classificador sido feito, com

a escolha de sua estrutura e das características, é o momento de treiná-lo para

determinar os valores dos limiares. Um conjunto de treinamento é usado, os erros são

medidos e os limiares determinados para minimizar tais erros. A performance então

pode ser medida, mas é mais realista que seja usado um conjunto somente para testes.

2.3.1 Medidas de tamanho

Todas as características abaixo estão relacionadas com o tamanho do objeto:

A. Área: número de pixels dentro da imagem e no contorno multiplicado pela área

de um único pixel.

B. Densidade Ótica Integrada: soma dos tons de cinza de todos os pixels dentro

do objeto.

C. Comprimento e Largura: o cálculo desses valores é muito simples, desde que

os objetos não estejam rotacionados, mas também existem cálculos para estes.

D. Perímetro: o número de pixels no contorno do objeto pode sofrer alterações

significativas se a imagem apresenta ruído.

2.3.2 Medidas de forma

Agora as características que estão relacionadas com a forma do objeto:

A. Retangularidade: razão entre a área do objeto e a área do menor retângulo que

poderia contê-lo. Os valores variam na faixa (0,1] e pi/4 é assumido como valor

de objetos circulares.

B. Circularidade: o método mais usado de se avaliar a circularidade é dividindo o

perímetro ao quadrado pela área do objeto, assim valores superiores a 4 pi são

considerados círculos.

C. Perímetro: o número de pixels no contorno do objeto pode sofrer alterações

significativas se a imagem apresenta ruído.

(24)

2.3.3 Classificação

Os mecanismos de classificação estão baseados na Estatística e são apresentados

agora.

2.3.3.1 Probabilidades

Conhecendo as amostras, podemos determinar as probabilidades a priori, que

meramente relacionam à chance de um objeto em particular ser de alguma classe, sem

conhecer suas características. Se a probabilidade for relacionada a uma característica do

objeto, então ela é condicional.

Para juntar a as probabilidades a priori, condicionais e as medidas obtidas para

determinado objeto e calcular a probabilidade dele pertencer a determinada classe,

existe o Teorema de Bayes, que é chamada de probabilidade a posteriori.

2.3.3.2 Regra de Decisão

A função de custo é usada para quantificar o risco, e dá o custo de uma

classificação de um objeto de classe A erroneamente classificado B. A regra de decisão

de Bayes define que um objeto deve ser atribuído a uma classe que apresente o mínimo

risco condicionado.

2.3.3.3 Treinamento

Os dados de treinamento do classificador podem já estar classificados por uma

entidade livre de erros ou não, resultado num treinamento supervisionado ou não. Um

tipo de treinamento supervisionado chama-se estimativa de máxima probabilidade.

Ele assume que os parâmetros a serem estimados são desconhecidos, mas fixos. Os

dados de treinamento são considerados com grande chance de representarem

precisamente os dados reais, assim os parâmetros são determinados baseados nisso.

2.3.3.4 Performance

(25)

classificador a um conjunto de testes, semelhante ao conjunto de treinamento, mas

diferente dele. As etapas anteriores do processamento digital de imagens são muito

importantes para o resultado final do classificador, porque este é negativamente afetado

por má qualidade nas imagens.

(26)

3. Robótica

Conforme dito antes, a robótica tem se desenvolvido muito nos últimos anos e

tem se tornado muito importante para a humanidade.

O

termo

robô foi criado por Karel Capek, um ator e escritor Tcheco. Ele

introduziu esse termo ao mundo em 1921, numa peça chamada: Robôs Universais de

Rossum. A peça, que foi encenada primeiro em Praga, atingiu grande sucesso e como

resultado foi encenada também por toda a Europa e Estados Unidos. A peça trata da

desumanizarão do homem numa sociedade tecnológica.

Apesar de criador do termo, ele não anteviu os meios. Na sua visão os robôs não

seriam construídos de partes mecânicas, mas através de manipulações química. Ele

defendeu sua idéia num ensaio chamado “O autor dos Robôs se defende”, de 1935:

“É com horror, francamente, que ele rejeita toda a responsabilidade pela idéia de

que instrumentos metálicos poderiam algum dia substituir seres humanos, e que pelos

meios de fios metálicos poderia despertar algo como vida, amor, ou rebelião. Ele

poderia considerar sua negra esperança ser ou uma superestimação das máquinas, ou

uma grave ofensa contra a vida” (tradução de Robotics-faq).

Já o termo robótica refere-se ao estudo e uso de robôs. Esse termo foi cunhado

por Isaac Asimov, um escritor e cientista americano que nasceu na Rússia. Em 1942 ele

publicou uma história chamada “Eu, Robô”, onde o termo foi usado pela primeira vez.

Também foi ele que definiu as três leis da robótica (depois ele mesmo acrescentou a lei

zero):

Lei Zero: Um robô não pode causar mal à humanidade ou, por omissão,

permitir que a humanidade sofra algum mal, nem permitir que ela própria o faça.

Lei Um: Um robô não pode ferir um ser humano ou, por omissão, permitir que

um ser humano sofra algum mal.

Lei Dois: Um robô deve obedecer às ordens que lhe sejam dadas por seres

humanos, exceto nos casos que em tais ordens contrariem a Primeira Lei.

Lei Três: Um robô deve proteger sua própria existência, desde que tal proteção

não entre em conflito com a Primeira e a Segunda Leis.

(27)

3.1 Robô

Classicamente define-se um robô como um “manipulador multifuncional

programável, projetado para mover materiais através de movimentos programados que

realizam um variedade de tarefas”(Robot Institute of America, 1979). Entretanto numa

visão mais atual pode-se dizer que um robô é um: “agente artificial ativo cujo ambiente

é o mundo físico”. Um agente por sua vez pode ser definido como algo que percebe seu

ambiente através de sensores e atua nesse mesmo ambiente através de atuadores

(RUSSEL95). Robôs autônomos são aqueles que alteram seus planos durante a

execução, além de interagir com o ambiente.

3.2 Histórico

Os primeiros robôs industriais surgiram entre os anos 50 e 60. George Devol e

Joe Engelberger desenvolveram os Unimates. Devol patenteou as primeiras máquinas

de transferência de materiais. Já Engelberger fundou uma empresa chamada Unimation

que foi pioneira na comercialização de robôs. Por esse motivo a ele é atribuído o título

de Pai da Robótica (Robotics-faq).

Com o desenvolvimento dos controladores e linguagens, e o aperfeiçoamento de

sensores e motores os robôs se tornaram mais precisos. No começo da década de 80 a

indústria automotiva investiu maciçamente no desenvolvimento da robótica, assim a

maioria das fábricas hoje em paises desenvolvidos é quase completamente

automatizada.

3.3 Lego RCX

O kit de construção de robôs que a Lego comercializa como Lego Mindstorms™

foi produzido através de uma associação entre a fabricante de brinquedos Lego e o

Massachusetts Institute of Technology (MIT) nos EUA.

O MIT recebeu financiamento para suas pesquisas em robótica, aprendizado

infantil e outros tópicos avançados. No MIT foi desenvolvido um robô semelhante ao

que é comercializado pela Lego. Em retribuição aos fundos investidos, a Lego usa as

idéias criadas no MIT nos seus brinquedos. O Lego Mindstorms™ foi lançado em 1999.

(28)

Os produtos da linha Mindstorms variam entre 100 e 200 dólares. Há também

uma câmera (vendida separadamente) que permite que imagens sejam captadas para um

computador com porta USB.

3.3.1 Hardware

Um micro controlador Hitachi H8/3292, que é um processador 8 bits e funciona

a 16MHZ, comanda o robô. Ele tem 16 Kbytes de ROM programável, 512 bytes de

RAM interna, 8 registradores de 16bits cada e pode controlar até 3 motores, 3 sensores e

a porta serial de comunicação infravermelha. Os motores e sensores ficam encapsulados

em peças externas que podem ser encaixadas livremente no robô, como é comum nos

brinquedos Lego.

Figura 3.1 – RCX

O RCX é um circuito eletrônico que encapsula o microcontrolador e outras

partes do robô em um revestimento de plástico que permite a montagem de peças Lego

sobre ou sob ele. Ele possui 32Kbytes de RAM, um chip para controle dos motores,

outro para controle da tela. Ele é alimentado por um circuito de pilhas que gera 9V. Há

também botões para a operação do robô, uma interface infra-vermelha, um tela que

(29)

permite mostrar uns poucos caracteres e contatos para conectar sensores ou motores.

Figura 3.2 – Motor

Figura 3.3 – Sensores de luz(cor) e toque.

Quando o robô é ligado (pode usar baterias ou um conector AC que vem no kit)

ele executa um driver presente em 16 KiloBytes de memória ROM. Outros 16 Kilobytes

de firmware são transferidos para o microcontrolador. Então o robô passa a aceitar

comandos do PC através da porta de comunicação.

O usuário também pode transferir programas na forma de bytecode, que ocupem

uma área de memória de até 6 Kilobytes, para serem interpretados pelo firmware.

3.3.2 Comunicação

As trocas de informação entre o robô e o PC ocorrem sem fio ligando ambos,

através de raios infravermelhos. Mas entre a base de transmissão e o PC a comunicação

é serial através de um cabo DB9.

(30)

Figura 3.4 – Torre de comunicação infra-vermelha

3.3.3 LegOS

É um sistema operacional desenvolvido cooperativamente através da Internet

que pode ser usado para substituir o SO de fábrica, que acompanha o robô. Ele permite

programação em C e C++ junto com uma biblioteca de funções úteis tanto para

programação em geral quando para acessar o hardware presente. Markus L. Noga foi

seu criador e a Lego não participou do seu desenvolvimento.

Figura 3.5 – Programa criado pela Lego para desenvolvimento do robô

Existem outras alternativas com mais recursos que o programa para

desenvolvimento da Lego, entretanto nenhuma oferece tantos benefícios quanto o

LegOS. Seu único inconveniente é a necessidade de carregar o SO para o RCX antes do

programa. No LegOS o desenvolvimento é feito em C ou C++ e o código é compilado

(31)

usando o popular compilador GCC. Por isso, o código executado é nativo, e não mais

interpretado como no software original. Benefícios adicionais são o uso de todos os

32Kbytes para variáveis (antes limitadas a 32), a possibilidade de armazenar até 8

programas e o fato de ser um SO multitarefa que escalona os processos

preemptivamente de acordo com as prioridades.

3.3.3.1 Biblioteca de funções do LegOS

Para controle dos motores, sensores, da comunicação, tela, criação de processos,

cálculos matemáticos (inclusive com números de ponto flutuante IEEE float e double) o

LegOS disponibiliza um ampla biblioteca de funções. Existem também outras

funcionalidades de uso geral na biblioteca, apenas para facilitar o desenvolvimento,

como geração de números aleatórios, semáforos POSIX, manipulação de cadeias de

caracteres, etc.

3.3.3.1.1 Motores

A biblioteca <dmotor.h> tem as funções que permitem o controle dos motores

acoplados ao robô. Nas funções abaixo, X deve ser substituído por a, b, ou c, para

indicar o 1

o

, 2

o

ou 3

o

motor:

enum MotorDirection. É uma enumeração que possui 3 valores: fwd, rev e

brake.

motor_X_dir(enum MotorDirection). Para mudar a direção em que o motor

opera: fwd quer dizer pra frente, rev quer dizer pra trás (ré), e brake quer

dizer parar(ou freiar).

motor_X_speed(unsigned char). Altera a velocidade do motor. A velocidade

deve estar entre 0 e 255.

3.3.3.1.2 Sensor de Luz

O nível de luminosidade captado pelos sensores é acessado lendo uma constante

que é atualizada pelo SO a cada 0,25 ms. Existem 3 constantes, que são chamadas

(32)

LIGHT_1, LIGHT_2 e LIGHT_3 e elas estão disponíveis na biblioteca <dsensor.h>.

Podem ser acoplados até três sensores de luminosidade que correspondem as

constantes citadas, mas eles podem ser acessados de maneira diferente, ativa ou passiva,

e para isso devem ser configurados com uma das funções abaixo (X deve ser substituído

por a, b, ou c para indicar o 1

o

, 2

o

ou 3

o

sensor):

ds_passive(&SENSOR_X). Muda o sensor para modo passivo. Nesse

modo, o sensor apenas capta a luminosidade do ambiente sem interferir.

ds_active(&SENSOR_X). Muda o sensor para modo ativo. Assim o

próprio sensor emite luz e capta a luminosidade refletida.

3.3.3.1.3 Sensor de Toque

Acessado através das constantes TOUCH_1, TOUCH_2 e TOUCH_3, que são

atualizadas e operadas como as do sensor de luz e também são acessadas através da

biblioteca <dsensor.h>. Essas variáveis podem assumir 2 valores: 1 quando foi

detectado toque, ou 0 quando não.

3.3.3.1.4 LCD

O RCX possui uma tela que pode ser usadas para mostrar pequenas mensagens.

Assim a depuração de programas fica um pouca mais fácil. As funções abaixo ficam

disponíveis incluindo a biblioteca <dlcd.h>.

lcd_int(int). O inteiro é mostrado no LCD.

lcd_clear(). Apaga o que foi escrito na tela.

cputs(char*). Escreve os primeiros 5 caracteres da string na tela.

3.3.3.1.5 Botões

Os botões também podem ser usados na programação do RCX. Assim pode-se

alternar entre várias opções que alteram o robô durante o funcionamento. Essas funções

(33)

estão disponíveis na biblioteca <dbutton.h>.

PRESSED(int a, int b). Esta macro retorna verdadeiro se o botão b esta

pressionado. O argumento a deve ser substituído por dbutton(), que

retorna o estado geral dos botões. O argumento b indica qual botão deve

estar pressionado: BUTTON_PROGRAM,

BUTTOM_ONOFF,

BUTTON_RUN, ou BUTTON_VIEW.

RELEASE(int a, int b). Esta macro funciona como a anterior, mas retorna

verdadeiro se o botão não está pressionado.

3.3.3.1.6 Processos

Várias funções semelhantes às encontradas no sistema operacional UNIX para

controle de processos estão na biblioteca <unistd.h>.

execi(função, argc, argv). Cria um novo processo chamando a função

com os argumentos argc e argv, como se fosse a função main.

exit(int). Finaliza o processo atual.

yield(). O processo atual libera o CPU para ser usado por outro processo.

wait_event(função, int). Chama a função até que ela retorne um valor

diferente de zero. Assim ela trava o processo atual até que um condição

seja satisfeita.

sleep(int x). O processo atual é suspenso por x segundos.

msleep(int x), Igual a função anterior, mas por apenas x milisegundos.

kill(pid_t pid). Força o fim da execução do processo pid.

3.3.3.2 O Protocolo LNP

Para que fosse possível trocar informações com o robô em tempo de execução os

desenvolvedores do LegOS desenvolveram o “LegOS Networking Protocol”. Essa

(34)

comunicação é realizada através de infravermelho, usando a porta infravermelha do

RCX e a torre de comunicação infravermelha conectada ao computador. Essa

comunicação pode ocorrer através de dois tipos de mensagens: Integrity Messages e

Addressing Messages.

3.3.3.2.1 Integrity Messages

Essa mensagem é envia da por Broadcast, assim qualquer RCX ou computador

apto vai recebê-la.

Figura 3.6 – Formato das Integrity Messages

O campo F0 é o identificador do pacote, e tem 1 byte. LEN também tem 1 byte e

traz o tamanho do bloco IDATA. IDATA é um bloco de dados com entre 0 e 255 bytes

que leva a mensagem em si. Para checagem de erros o campo CHK contém o checksum

da mensagem. Totalizando a mensagem tem no máximo 258 bytes.

3.3.3.2.2 Addressing Messages

Para mandar mensagens para um RCX específico, as Addressing messages tem

campos para identificar o nó quem envia e a quem é endereçada.

Figura 3.7 – Formato das Addressing Messages

Nesse tipo de mensagem algums campos permanecem iguais aos das Integrity

Messages, tanto em tamanho quanto em função. Os novos campos DEST e SRC são

para os números dos nós destino e o origem, respectivamente, e ambos tem 1 byte. O

campo ADATA é o novo campo de dados em tem o tamanho de IDATA subtraído dos

tamanhos de DEST e SRC, uma Addressing Message pode enviar até 253 bytes de

(35)

informação útil.

Num meio de transmissão como o ar, não há como impedir que outros aparelhos

ou qualquer RCX próximo receba o sinal, e assim o LegOS de qualquer que não seja o

do campo DEST ignora a Integrity Message, não a repassando às camadas de aplicação.

3.3.3.2.3 Funções do LegOS para comunicação

O LegOS possui funções para enviar e receber tanto Integrity messages quanto

Addressing Messages. Elas são acessíveis através das bibliotecas <lnp/lnp.h> e

<lnp/lnp-logical.h>. Abaixo seguem as utilizadas neste trabalho:

lnp_logical_range(int). Altera a potência do sinal emitido: 0 quando o RCX está

próximo da torre de comunicação; 1 para enviar um sinal forte que permite o

RCX se afastar da torre de comunicação.

lnp_integrity_write(const unsigned char* data, const char length). Envia uma

integrity message.

lnp_integrity_set_handler(void (*hander)(const unsigned char* data, const char

length). Seta a rotina tratadora das Integrity Messages. Essa rotina é chamada

(36)

4. Implementação

O sistema implementado, que permite que o robô seja controlado a partir de

informações obtidas de imagens captadas por uma câmera, tem seu processamento

dividido. Parte dos dados são processados pelo PC ao qual a câmera está conectada, e a

outra parte do processamento é realizada no robô.

Como a comunicação infra-vermelha que ocorre entre PC e RCX não alcança

altas taxas de transmissão, todo o processamento de detecção de objetos sobre a imagem

é realizado no próprio PC. Assim poucos dados são transmitidos entre PC e RCX,

aliviando também a quantidade de cálculos que o processador mais limitado presente no

robô tem de fazer.

Figura 4.1 – Visão Geral do sistema.

As técnicas de Processamento Digital de Imagens usadas são apresentadas no

item 4.1, junto aos parâmetros usados e com as adaptações necessárias para os

experimentos realizados. Cada classe tem sua finalidade exposta e as funções mais

importantes são descritas extensivamente.

O protocolo de comunicação (equivalente à camada de transporte do Modelo de

Referência OSI) é descrito em seguida e as implementações no PC e no robô são

rapidamente vistas no item 4.2.

Finalmente no item 4.3 o programa que controla o robô tem seus mecanismos de

comunicação e controle (tanto sensores como motores) analisados.

(37)

4.1 Captura e Processamento das Imagens

Todo esse processo é realizado no PC com as várias tarefas dividas nas classes:

CBitmapEx, CFrameGrabber, CAboutDlg, CMainFrame, CFrameGrabberTestApp,

CFrameGrabberTestDoc, CFrameGrabberTestView e Regiao. O programa foi

desenvolvido em C++ usando a biblioteca para captura de vídeo do SO Windows® e a

biblioteca Microsoft Foundation Classes(MFC) para construir a interface gráfica.

4.1.1 Classe Região

Ao detectar um objeto numa imagem é necessário armazenar seus pontos para

determinar seu tamanho, seu ponto centróide, sua cor ou outras informações que serão

usadas no Classificador (ver 2.3.3.3). Nesse programa os objetos são classificados por

sua cor: o robô apresenta uma cor e seu alvo apresenta outra.

Abaixo estão seus métodos mais importantes:

cor(). Retorna a cor do objeto na região (BLUE, GREEN ou RED)

cor(COR). Altera a cor do objeto na região.

tamanho(). Retorna o tamanho (número de pontos) da região.

adiciona(x, y). Acrescenta mais um ponto na região.

centroide(). Retorna um par (x,y) com a posição do centróide da região.

4.1.2 Classe CBitmapEx

Essa classe é na verdade apenas uma subclasse de CBitmap, já presente na MFC.

CBitmap por sua vez é um encapsulamento em C++ do modo como os bitmaps são

tratados no Windows.

O principal recurso que a classe CBitmapEx oferece é o método

CreateFromDib(), que copia um Device Independent Bitmap(DIB) para dentro do

objeto. Esse método é importante porque a captura de um quadro através da câmera de

vídeo no windows retorna um DIB.

(38)

método BitBlt() para desenhar numa janela ou outra superfície do programa. O método

BitBlt() é usado para desenhar o bitmap na janela principal do programa.

4.1.3 Classe CFrameGrabber

O Windows oferece diversas funções de baixo nível para captura de vídeo

através da biblioteca <vfw.h>. Entretanto usar essas funções é um inconveniente em

programas de alto nível, assim a classe CFrameGrabber existe para permitir uma

interface de alto nível ao programador que deseja capturar vídeo no Windows.

Para obter um quadro basta chamar o método GetDIB(). Um novo quadro está

disponível a cada 20ms, por isso se essa função voltar a ser chamada em um intervalo

de tempo menor, o mesmo quadro será retornado.

Como o Windows aceita que várias câmeras ou outros mecanismos de captura

estejam conectados ao mesmo tempo, o método VideoSourceDialog() permite que o

dispositivo desejado seja escolhido através de uma janela de configuração. Para alterar

os parâmetros com que as imagens serão digitalizadas pela câmera,

VideoFormatDialog() mostra uma janela onde resolução, número de cores, contraste, ou

outros parâmetros podem ser alterados.

4.1.4 Classe CAboutDlg

CAboutDlg apenas mostra a janela “Sobre” do programa:

(39)

4.1.5 Classe CFrameGrabberTestApp

O padrão de desenvolvimento de programas chamado de “Modelo – Visão” é

muito difundido atualmente. Nesse padrão há uma separação entre a classe que

armazena as informações e a classe que é responsável por mostrar essas informações ao

usuário. A finalidade desse padrão é aumentar a portabilidade e extensibilidade do

código ao evitar que a lógica da aplicação fique misturada ao código da interface com o

usuário.

Todos programas que usam a biblioteca MFC devem seguir esse padrão. Desta

maneira essa classe herda de CWinApp e apenas deve inicializar as instâncias de

CframeGrabberTestView (Visão), CframeGrabberTestDoc (Modelo) e CMainFrame

(Janela Principal).

4.1.6 Classe CMainFrame

Essa classe é bem simples, somente herda de CFrameWnd e redefine alguns de

seus métodos, justamente os que vão construir a janela principal do programa.

Figura 4.3 – Janela Principal com um quadro capturado.

4.1.7 Classe CFrameGrabberTestView

Seguindo o padrão “Modelo – Visão” da MFC, essa classe herda de CView. Seu

papel nesse padrão é o de Visão, ou seja, sua responsabilidade é redesenhar a janela

toda vez que o Modelo mudou. Também é essa classe que faz a comunicação com a

(40)

câmera através de um objeto da classe CFrameGrabber.

O

método

OnDraw() é chamado toda vez que o modelo mudou, ou logo que a

janela é criada. Ele checa se o objeto da classe CFrameGrabber pode ser usado. Se não

for possível ele mostra uma mensagem na janela atestando que não existe um

dispositivo de captura conectado ao computador, ou que ele já está sendo usado por

outro programa.

4.1.7.1 Método OnTimer

A detecção dos movimentos do robô é um processo contínuo, porque o robô ou

seu alvo pode se mover a qualquer instante. Por isso um timer é programado pelo objeto

da classe CFrameGrabberTestView para chamar o método OnTimer() a cada 600ms.

Deste modo os movimentos do robô são continuamente calculados e sua trajetória

corrigida.

1: void CFrameGrabberTestView::OnTimer(UINT nIDEvent) 2: {

3: if(!m_FrameGrabber.GetSafeHwnd()) return;

4: CFrameGrabberTestDoc* pDoc = GetDocument(); 5: ASSERT_VALID(pDoc);

6: LPBITMAPINFO lpBi = m_FrameGrabber.GetDIB();

7: if(suavizar) 8: filtro_suavizar(lpBi); 9: filtro1(lpBi); 10: switch(color) { 11: case GRAY: 12: to_graylevel(lpBi); 13: break; 14: case RED: 15: to_red(lpBi); 16: break; 17: case GREEN: 18: to_green(lpBi); 19: break; 20: case BLUE: 21: to_blue(lpBi); 22: break; 23: default: 24: filtro2(lpBi);

(41)

25: break; 26: } 27: if(!pDoc->m_ImageBitmap.GetSafeHandle()) { 28: pDoc->m_ImageBitmap.CreateFromDib(lpBi); 29: InvalidateRect(NULL); 30: } else { 31: pDoc->ProcessImage(lpBi); 32: } 33: }

Esse método controla várias transformações que podem ser feitas na imagem,

algumas que não tem nenhuma relação com o processo de detecção de movimento, mas

permitem analisar a imagem na tela do PC sob vários aspectos. Assim nas linhas 12, 15,

18 e 21 a figura pode ser convertida para tons-de-cinza, ou ter uma componente da cor

(verde, vermelha ou azul) realçada zerando as outras componentes.

Existe a possibilidade de um filtro inicial ser aplicado sobre a imagem para

corrigir falhas no processo de digitalização (linha 9). Embora a função filtro1() não

realize nenhuma operação sobre a imagem, esta chamada de função foi colocada aqui

para permitir que versões posteriores do programa suportem esse recurso. De modo

semelhante a função filtro2() chamada na linha 24 pode ser alterada para realizar

alguma operação importante somente em imagens que permanecerão na codificação

RGB.

No caso de existir ruído nas imagens, causando que alguns pixels tenham valores

muito diferentes dos seus vizinhos o usuário pode escolher por suavizar a imagem.

Assim para cada pixel passa a ter o valor da média do valor antigo do pixel e de seus

oito vizinhos segundo a figura (linha 7 e 8):

Figura 4.4 – Método de Suavização

O programa não processa o 1

o

quadro capturado, mas salva num objeto da classe

(42)

ProcessImage() da classe CFrameGrabberTestDoc.

4.1.8 Classe CFrameGrabberTestDoc

Essa classe é muito importante, pois no padrão “Modelo - Visão” ela ocupa o

papel de Modelo. Ou seja, ela contém e manipula as informações que serão exibidas por

CFrameGrabberTestView. Um objeto dessa classe também é responsável por calcular a

posição dos objetos na cena e chamar as rotinas que enviarão os dados ao robô. Para

atender as especificações da MFC, ela herda de CDocument.

Um objeto desta classe pode estar em diversos estados: visualizando os quadros

capturados (PROCESSOR_SIMPLE_VIEWER), processando toda cena capturada para

detectar os objetos que estão na cena (PROCESSOR_MOTION_DETECTOR), ou

parado apenas mostrando a última cena que pode pertencer a um dos 2 estados

anteriores (PROCESSOR_PAUSED). O estado atual é armazenado na variável

m_ProcessorMode do objeto.

A última imagem processada é sempre armazenada na variável m_ImageBitmap

do objeto. Desta forma o objeto da classe CFrameGrabberTestView pode usar essa

variável (que é pública) para mostrar a imagem processada na janela.

O

objeto

transporte da classe CTransport é usado para fazer a comunicação com

o RCX. Ele será descrito mais tarde junto da descrição do protocolo e dos mecanismos

de comunicação (item 4.2).

4.1.8.1 Método ProcessImage

Esse é o método mais importante da classe porque ele é o único que é chamado

de fora da classe (do objeto da classe CFrameGrabberTestView). Abaixo seu código e

uma descrição do que cada instrução faz:

1: void CFrameGrabberTestDoc::ProcessImage(LPBITMAPINFO lpBi) 2: {

3: static BOOL bRunNow = FALSE; 4: if(bRunNow || !lpBi) return; 5: bRunNow = TRUE;

6: switch(m_ProcessorMode) {

(43)

8: m_ImageBitmap.CreateFromDib(lpBi); 9: UpdateAllViews(NULL);

10: break;

11: case PROCESSOR_MOTION_DETECTOR: 12: if(IMAGEBITS(lpBi)!=24) {

13: AfxMessageBox("Can't run filter: unsupported color resolution!",MB_ICONWARNING); 14: m_ProcessorMode =PROCESSOR_SIMPLE_VIEWER; 15: break; 16: } 17: Limiarizar(lpBi); 18: SeparaRegioes(lpBi); 19: Envia(lpBi); 20: m_ImageBitmap.CreateFromDib(lpBi); 21: UpdateAllViews(NULL); 22: break; 23: } 24: bRunNow = FALSE; 25: }

O método recebe como parâmetro um ponteiro para uma estrutura

BITMAPINFO, que no Windows é a responsável por armazenar todas as informações de

um DIB, seu cabeçalho com informações sobre as cores, resolução, codificação, etc, e

os próprios pixels da imagem (linha 1).

As linhas 8 e 20 copiam o bitmap recebido como argumento pro objeto

m_ImageBitmap, enquanto 9 e 21 manda que todos os objetos com papel de Visão da

aplicação redesenhem suas telas. Assim o método OnDraw() do objeto da classe

CFrameGrabberTestView será chamado para redesenhar a janela, e desta vez usará a

nova imagem salva em m_ImageBitmap.

Como essa aplicação foi desenvolvida para que a detecção de imagem fosse feita

sobre uma imagem RGB de 24 bits, a linha 12 confere se o bitmap capturado é

compatível com essa restrição.

Finalmente a imagem é processada, primeiro através da limiarização expressa na

linha 17, depois as regiões são separadas na 18 e finalmente a trajetória do robô é

calculada e enviada ao RCX na 19.

(44)

4.1.8.2 Método Limiarizar

Cada pixel da imagem tem sua componente (Verde, Azul ou Vermelho)

predominante determinada por esse método. Para armazenar essas informações são

usadas três matrizes de valores booleanos. Assim para cada posição (i,j) dessas matrizes

somente uma delas tem valor true.

1: void CFrameGrabberTestDoc::Limiarizar(LPBITMAPINFO lpBi) 2: {

3: int arena_dx = IMAGEWIDTH(lpBi); 4: int arena_dy = IMAGEHEIGHT(lpBi);

5: BYTE * ptr =(BYTE *)IMAGEDATA(lpBi);

6: for(int y=0; y< arena_dy;y++) {

7: for(int x=0, pos = 0; x<arena_dx; x++, pos+=3) {

8: switch(max_rgb(ptr+pos)){

9: case RED:

10: Red[x][y] = true; Green[x][y] = false; Blue[x][y] = false;

11: break;

12: case GREEN:

13: Red[x][y] = false; Green[x][y] = true; Blue[x][y] = false;

14: break;

15: case BLUE:

16: Red[x][y] = false; Green[x][y] = false; Blue[x][y] = true;

17: break;

18: case MRGB:

19: Red[x][y] = false; Green[x][y] = false; Blue[x][y] = false;

20: break; } 21: } 22: ptr += arena_dx*3; 23: } 24: }

A função que calcula a componente predominante num pixel chama-se

max_rgb(BYTE* ptr). Ela compara cada componente e determina o maior, se a maior

for pelo menos 25 níveis (cada componente do RGB vai de 0 a 255) acima do 2

o

ela é

determinada a componente predominante. Senão, MRGB é o valor retornado para

indicar que nenhuma componente é mais forte que as outras.

(45)

4.1.8.3 Método SeparaRegioes

O objetivo desse método é encontrar as maiores regiões contíguas de pixels das

cores vermelha e verde, a partir das informações que Limiarizar() colocou nas matrizes

Red, Green e Blue.

O procedimento consiste em percorrer o bitmap marcando numa matriz de

valores booleanos os pixels já pesquisados. Se o pixel ainda não foi pesquisado,

determinar sua cor predominante e procurar recursivamente em todas as direções por

pixels adjacentes não pesquisados da mesma cor, acrescentando a um objeto temporário

da classe Regiao. Quando não existem mais nós adjacentes, é determinado se a região é

grande o suficiente, isto é, tem mais de 300 pontos. Se esse for o caso esse objeto é

salvo em rVerde ou rVerm, pois o robô ou seu alvo já foram encontrados na imagem.

4.1.8.4 Método Envia

A partir das regiões detectadas (o robô e o alvo), é preciso determinar a direção

em que o robô está indo para poder determinar para que lado fazer a volta e quanto ele

deve virar. Para isso são usados os pontos centróide das regiões encontradas na imagem,

e duas variáveis do objeto da classe CFrameGrabberTestDoc: rVerde e rVerm.

Assim enquanto o centróide de rVerm e de rVerde é considerado a posição atual

do robô, pVerm e pVerde são os centróides encontrados na iteração anterior. Assim

correspondem à posição anterior do robô.

Figura 4.5 – Reta usada para determinar a direção do robô

(46)

Y1 (centróide de pVerde) são usados para determinar a direção do robô. Assim a reta

que liga X0 à X1 é a direção em que o robô segue, e ligando os pontos X1 à Y1 obtemos

a reta que indica a direção que o robô deveria tomar.

Calculando o ângulo entre a retas obtemos o quanto o robô deve virar para

seguir em linha reta para o alvo. A direção a tomar (direita ou esquerda) é determinada

comparando X0, X1 e Y1 e os coeficientes angulares das retas r e s. Neste caso pela

figura fica claro que deveria ser à direita, mas se os pontos X0 e X1 fosse invertidos, por

exemplo, o correto seria virar (180

o.

– â) graus à esquerda. A distância entre os pontos

X1 e Y1 é considerado nos cálculos como distância para o alvo.

O PC só envia dois bytes de dados para o robô e esses são as velocidades em que

os motores direito e esquerdo devem ser ligados, respectivamente, para que ele alcance

o alvo. Por isso esses valores, distância para o alvo, ângulo e direção são usados para

determinar a velocidade dos motores, que pode ser negativa para indicar que o motor

será ligado na marcha ré.

Finalmente após todos os cálculos, se a variável booleana running for

verdadeiro, os dados são transmitidos ao robô chamando o método Send() de

CTransporte com um vetor tendo os valores das velocidades dos motores dentro dele e

o tamanho 2 como parâmetro.

4.2 Comunicação

A implementação do protocolo LNP feita para executar no PC foi dividida em

várias classes. A saber: CComm, CTower e CLNP. Uma classe herda da outra, para

poder reutilizar sua implementação. Somente foi implementado suporte para Integrity

Messages (ver 3.3.3.2). No entanto era necessário prover um controle de erros e

posterior retransmissão de pacotes perdidos, por isso foi implementada a classe

CTransport, que equivale à camada de transporte do modelo de referência OSI.

4.2.1 Classe CComm

Esta classe consiste de uma abstração da porta serial, assim ela usa as funções do

SO windows para permitir que bytes sejam enviados e recebidos pela porta serial do

windows. Uma Thread é criada para enviar e receber os bytes. Os parâmetros usados na

comunicação serial (tais como: taxa de transmissão, paridade, etc) podem ser passados

Referências

Documentos relacionados

a, contacto telefónico e/ou eletrónico). b) Os concorrentes terão de fazer prova da validade da sua licença de atleta na FEP para a época em que estão a competir, nos exatos

b1) Espécies unicelulares e autotróficas são encontradas nos reinos Monera (algumas bactérias e Cianobactérias) e Protista (algas unicelulares). b2) Espécies unicelulares

Unidade 3 –Números racionais não negativos /Expressões algébricas e propriedades das operações - Adição e subtração de números racionais. -Propriedades

Adição, subtração, multiplicação e divisão de números naturais e de frações Termos da adição, da subtração, da multiplicação e da divisão. Propriedades da adição e

• Usar as propriedades das operações (adição, subtração, multiplicação, divisão), as regras da potenciação e a prioridade das operações no cálculo do valor de

Para o exponente, vale o princípio de equilíbrio: &#34;Cada casa decimal que diminui o valor da mantissa aumenta o expoente em uma unidade, e vice-versa&#34;. O resultado

Advertência: Os litigantes, o cônjuge do executado(a) ou os titulares de ônus sobre os bens que não forem localizados para fins de intimação reputar-seão intimados com a

Vale ressaltar que cada tabela corresponde a uma operação matemática (adição, subtração, multiplicação e divisão). Os valores das tabelas correspondem ao lançamento