rastreamento em tempo real com camera de pan-tilt (real time tracking with pan tilt camera)
DESCRIPTION
Este trabalho visa demonstrar a possibilidade de criação de um sistema com câmera para o rastreamento automático de faces através da utilização de software livre (biblioteca OpenCV, Processing e Arduino) e elementos de hardware simples, fáceis de encontrar e de baixo custo.O projeto utiliza o código de um exemplo da biblioteca OpenCV como ponto de partida para a geração de um sinal que será enviado para o micro controlador, Arduino. Nesta fase, o controlador traduzirá o sinal e enviará comandos para que os servo motores corrijam o erro apresentado através de um movimento preciso.______________________________This paper demonstrates the possibility of creating a system with camera for automatic tracking of faces by using free software library (OpenCV, Processing and Arduino) and hardware elements simple, easy to find and inexpensive.The project uses code from an example of OpenCV library as a starting point for generating a signal that is sent to the microcontroller, Arduino. At this stage, the controller translates the signal and sends commands to the servo motors correct the error made by precise movement.TRANSCRIPT
Curso de Graduação em Engenharia Elétrica
RASTREAMENTO EM TEMPO REAL COM CAMERA DE PAN-TILT
Aluno: Rodrigo Cuel da Silva
Orientador: Prof. Dr. José Eduardo Cogo Castanho
Bauru 2011
UNIVERSIDADE ESTADUAL PAULISTA Faculdade de Engenharia de Bauru
Curso de Engenharia Elétrica
2
RODRIGO CUEL DA SILVA
RASTREAMENTO EM TEMPO REAL COM CÂMERA DE PAN-TILT
Trabalho de Graduação do Curso de Engenharia Elétrica apresentado à Faculdade de Engenharia de Bauru/UNESP. Orientador: Prof. Dr. José Eduardo Cogo Castanho
Bauru 2011
2
FOLHA DE APROVAÇÃO
Autor:
Título:
Trabalho de graduação defendido e aprovado em ____/____/____,
com NOTA ______ (__________), pela comissão julgadora:
(Assinatura) (Titulação/nome/instituição) (Assinatura) (Titulação/nome/instituição) (Assinatura) (Titulação/nome/instituição)
Coordenador do Conselho de Curso de Graduação Engenharia Elétrica
3
DEDICATÓRIA
À minha mãe, Isabel Cristina Cuel, e minha irmã, Yasmin Cristina Cuel da Silva, pelo suporte em todos os momentos. E a Deus, por minha capacitação intelectual.
4
Como é feliz o homem que acha a sabedoria, o homem que
obtém entendimento, pois a sabedoria é mais proveitosa do que a
prata e rende mais do que o ouro. Provérbios 3:13-14
5
RESUMO
Este trabalho visa demonstrar a possibilidade de criação de um sistema com câmera
para o rastreamento automático de faces através da utilização de software livre (biblioteca
OpenCV, Processing e Arduino) e elementos de hardware simples, fáceis de encontrar e de
baixo custo.
O projeto utiliza o código de um exemplo da biblioteca OpenCV como ponto de partida
para a geração de um sinal que será enviado para o micro controlador, Arduino. Nesta fase, o
controlador traduzirá o sinal e enviará comandos para que os servo motores corrijam o erro
apresentado através de um movimento preciso.
6
LISTA DE FIGURAS
FIGURA 1 – CONFIGURAÇÃO DE SERVO-MOTORES EM PAN-TILT.[7] ...................................................... 10
FIGURA 2 – PLATAFORMA ARDUINO (MODELO DUEMILANOVE). ......................................................... 13
FIGURA 3 – AS DUAS PRIMEIRAS CARACTERÍSTICAS HAAR NA CASCATA ORIGINAL DE VIOLA-JONES.
....................................................................................................................................................... 14
FIGURA 4 – EXEMPLO DE CARACTERÍSTICAS HAAR USADOS NO OPENCV. .......................................... 15
FIGURA 5 – TRUQUE DA INTEGRAL DE IMAGEM. ................................................................................... 15
FIGURA 6 – CLASSIFICADOR EM CASCATA É UMA CADEIA DE FILTROS. ............................................... 17
FIGURA 7 – EXEMPLO DE DETECÇÃO DE UMA, OU MAIS FACES COM O PROGRAMA EM PROCESSING ... 18
FIGURA 9 – FOTO DA ESTRUTURA DE PAN E TILT DOS SERVO-MOTORES. ............................................. 23
FIGURA 10 – ARDUINO CONECTADO AOS SERVOS DE PAN E TILT. ........................................................ 24
FIGURA 11 – DIAGRAMA DE BLOCOS DO HARDWARE. .......................................................................... 24
FIGURA 12 – FOTO DO ESCUDO PARA ACOPLAGEM DO HARDWARE AO ARDUINO. ............................... 25
FIGURA 13 – ESCUDO MONTADO SOBRE O ARDUINO. ........................................................................... 26
FIGURA 14 – HARDWARE COMPLETO. ................................................................................................... 26
FIGURA 15 – DETECÇÃO DE FACE DENTRO DA ZONA DE ERRO. ............................................................. 28
FIGURA 16 – FLUXOGRAMA DE CONTROLE DE SERVOS. ........................................................................ 29
7
SUMÁRIO
1. INTRODUÇÃO ................................................................................................................. 8
2. REVISÃO BIBLIOGRÁFICA ......................................................................................... 9
2.1. OPENCV ...................................................................................................................... 10
2.2. PROCESSING ................................................................................................................. 11
2.3. ARDUINO ..................................................................................................................... 12
2.4. DETECÇÃO DE FACE COM OPENCV .............................................................................. 14
2.5. RASTREAMENTO FACIAL .............................................................................................. 18
2.6. SERVO MOTORES DE HOBBY ......................................................................................... 19
3. OBJETIVO DO PROJETO ............................................................................................ 21
4. MATERIAIS E METODOLOGIA ................................................................................ 21
4.1. MATERIAIS ................................................................................................................... 21
4.2. METODOLOGIA ............................................................................................................. 21
5. DESENVOLVIMENTO .................................................................................................. 22
CONCLUSÃO ......................................................................................................................... 30
REFERÊNCIAS ...................................................................................................................... 32
APÊNDICE 1 .......................................................................................................................... 34
APÊNDICE 2 .......................................................................................................................... 38
8
1. INTRODUÇÃO
Durante os últimos anos, o rastreamento de objetos tornou-se um dos campos mais
populares de pesquisa no ramo da visão computacional, devido, em grande parte, à vasta
gama onde tais procedimentos podem ser utilizados.
Na área do rastreamento de objetos, destaca-se o rastreamento facial, que se apresenta
relativamente complexo uma vez que um indivíduo pode carregar consigo uma grande
variedade de expressões, ao contrário de objetos, que se apresentam de forma singular.
O rastreamento facial em tempo real possui aplicações bastante interessantes tais como,
vigilância por vídeo e monitoramento de segurança, interface avançada homem-máquina,
vídeo conferência, realidade virtual e análise de gestos.
No entanto para que ocorra um rastreamento efetivo, é necessário que o sujeito ou
objeto a ser rastreado encontre-se sempre presente dentro do campo de visão da câmera. Para
isso, a câmera deve se movimentar de maneira autônoma e pouco dispendiosa para que esta
tarefa seja cumprida de maneira eficaz.
Este projeto tem como objetivo o desenvolvimento de um sistema básico para
rastreamento em tempo real, de indivíduos, com uma câmera montada sobre uma estrutura de
motores montados em configuração de pan e tilt, onde sua imagem será analisada e então
convertida em movimento através dos motores.
Primeiramente montou-se uma estrutura para que dois servo-motores de hobby fossem
posicionados de maneira a permitir movimentos de pan e tilt, criando-se assim o suporte para
a câmera de vídeo.
Em seguida, a partir de um exemplo da biblioteca OpenCV, construiu-se um código
quer fosse capaz de produzir dados de posição relativa de um rosto presente na imagem e
transferir estes através de uma porta serial para que posteriormente fossem utilizados pelo
micro controlador, Arduino.
Neste passo, o Arduino, responsável pelo controle do servos, se utilizando das
informações do software, reportaria os motores para a uma posição de maneira a corrigir o
“erro” de posição do rosto em relação ao centro da imagem gerada pela câmera.
Testes foram efetuados alterando-se parâmetros do programa com a finalidade de se
descobrir quais deles seriam os mais apropriados para a execução, com maior eficiência, da
tarefa de rastreamento proposta.
9
2. REVISÃO BIBLIOGRÁFICA
Uma identidade, usualmente é identificada através do reconhecimento das
características peculiares a um determinado indivíduo ou objeto. Para um humano, essa tarefa
é tão natural e cotidiana, que muitas vezes passa sem ser notada e não demanda atenção extra,
uma vez que nossos olhos estão acostumados a identificar e se adaptar a padrões distintos.
Tornando o reconhecimento através da visão, um processo bastante simples e automático.[9][10]
No entanto para máquinas e computadores, esta realidade é bastante semelhante, uma
vez que para serem entendidas, as imagens devem ser, antes, processadas. No entanto, este
processo demanda um alto custo computacional, isto é, para a execução de um movimento, o
motor necessita de um sinal gerado pelo micro controlador após receber uma informação de
controle proveniente do software que processou as imagens. O que, em outras palavras,
demandava um tempo expressivo e inviabilizava o rastreamento em tempo real.
No entanto, o desenvolvimento de novos chips, processadores e técnicas de
processamento de dados bem como a evolução do OpenCV, uma caixa de ferramentas que
contém bibliotecas criadas para visão computacional, auxiliaram na otimização deste processo
e contribuíram para a geração de um processamento menos custoso computacionalmente.
Contudo, agora a barreira passaria a ser o hardware. Contudo, devido ao grande
avanço em relação à criação de sensores (CCD e CMOS, entre outros), mini e micro câmeras
leves e de tamanho diminuto, foram desenvolvidas, tornando-as facilmente manipuláveis sem
a necessidade de esforço significativo.[9]
Dessa maneira, acoplando-se dois mini servo-motores a fim de atingir a configuração
de um dispositivo de Pan-Tilt (vide Figura 1) garantindo a liberdade de movimento de
aproximadamente 90 graus na vertical e 180 na horizontal, e posicionando-se uma mini
câmera no topo obtêm-se um hardware básico pronto para o rastreamento de indivíduos ou
objetos.[8]
10
Figura 1 – Configuração de servo-motores em pan-tilt.[7]
2.1. OpenCV O OpenCV é uma biblioteca de algoritmos de softwares de visão computacional
desenhada para aplicativos de visão e pesquisa em computadores pessoais. Em 2000, a
Intel liberou uma versão beta do software para a comunidade Open Source. No ano de
2008, a empresa Willow Garage se tornou responsável pelo OpenCV que recentemente,
passou por uma expansão visando melhorias e atualizações a fim de proporcionar suporte
para uma maior gama de processadores embarcados e sistemas operacionais.
Atualmente em sua versão 2.3, o OpenCV é uma ferramenta multi-plataforma
(disponível para Linux, Macintosh, PC e plataformas móveis como Apple iOS e Android
OS), com um grande foco em aplicações em tempo real, escrita em C/C++ otimizado,
contendo mais de 2.500 funções e inúmeros exemplos de como aplicá-las.[1]
11
As rotinas em OpenCV podem ser escritas através de programas que utilizam
linguagens tais quais C, C++ e Python. Além disso, é possível encontrar na rede, pacotes
que tornam simples a comunicação entre o OpenCV e outros softwares como o Processing
possibilitando que se desenvolva um aplicativo em Java utilizando a própria biblioteca de
visão computacional aberta. Para isso, deve-se instalar no computador em questão a caixa
de ferramentas (Tool box) do OpenCV e, posteriormente, dentro do próprio ambiente de
desenvolvimento, uma biblioteca necessária para a utilização correta da ferramenta.
A comunidade OpenCV conta com mais de quarenta e sete mil membros ao redor
do mundo e uma completa documentação e descrição da ferramenta em seu portal online
(http://www.opencv.org). A utilização do software vai da criação de arte interativa à
exploração de minas, seja pela junção de mapas na web ou através de robótica avançada.[2]
2.2. Processing
Processing, é uma linguagem de programação e ambiente de desenvolvimento que
desde 2001 promove o ensino de software dentro das artes visuais. Inicialmente, o software
foi criado para a servir como um caderno de desenho via software bem como para ensinar
fundamentos de programação de computadores dentro de um contexto visual. O Processing
rapidamente evoluiu para uma ferramenta de trabalho tornando possível a criação e
acabamento de trabalhos profissionais.
O ambiente de desenvolvimento é uma opção livre (open source) que serve de
alternativa a ferramentas de softwares com licenças caras, tornando-o acessível a escolas e
alunos.
Por se tratar de uma licença livre, contribuidores e usuários são encorajados a
compartilhar seus códigos, pesquisas e bibliotecas, expandindo as áreas de aplicação do
software e facilitando o entendimento do mesmo.
O Processing foi criado por Ben Fry e Casey Reas, ambos alunos do Laboratório de
Mídia do MIT, e posteriormente passou por avanços e melhorias nas Universidade Carnegie
Mellon e UCLA
O software Processing é multi-plataforma, podendo ser rodado tanto em Linux/GNU,
Macintosh ou Windows. Através de seu ambiente de desenvolvimento é possível gerar
12
aplicativos independentes e applets, bem como arquivos PDF, DXF e TIFF dentre outros.
Apesar de ter sido construído em Java, linguagens como JavaScript, ActionScript, Ruby,
Python e Scala, foram adaptadas para funcionar com algumas versões experimentais do
Processing.[3]
Os aplicativos em Processing são estruturados da seguinte maneira: Primeiramente
declara-se as variáveis a serem utilizadas, no inicio do programa, fora de qualquer estrutura.
Em seguida o código inserido na função void setup() é rodado apenas uma vez. Desta forma, é
aqui que entram comandos para criação de janelas e obtenção de imagem, por exemplo. Por
último, todo o conteúdo da função void draw() roda, continuamente, de cima a baixo até que
o programa seja parado. Exigindo então que as funções determinadas para o programa entrem
aqui.
O Processing também permite comunicação via porta serial. Para isso, deve-se iniciar a
instância Serial dentro da função void setup() no começo do programa. Posteriormente, dentro
da função void draw(), deve se utilizar o comando Serial.write() para o envio dos comandos
via serial.
2.3. Arduino
Devido a sua ampla disseminação, o Processing gerou outro projeto. O Wiring, que por
sua vez, se utiliza da IDE (Integrated Development Environment – Ambiente de
Desenvolvimento Integrado, em português) do Processing com uma versão simplificada da
linguagem C++ para ensinar artistas como programar micro controladores.[4]
A criação do framework do Wiring levou ao surgimento de outro projeto, denominado
Arduino. Originado em Wiring, o Arduino conta com linguagem de programação exclusiva
com sintaxes simples que em sua essência se assemelha a C/C++. Se utiliza de IDE própria
derivada do Processing e tem por objetivo criar e desenvolver ferramentas acessíveis, de
baixo custo, flexíveis e fáceis de usar por artistas e amadores.
Além do ambiente de desenvolvimento, o Arduino conta com a plataforma micro-
controlada e credenciada sob licença creative commons (CC) baseada no chip micro-
controlador ATmega168, ou ATmega328. Possui 14 pinos de entrada ou saída digitais (sendo
6 passíveis de uso para PWM) e 6 entradas analógicas.
13
Sua memória interna para programa pode variar de 16Kb, para controladores
ATmega168 a 32Kb, para o ATmega328.
Os chips ATmega168 ou 328, oferecem suporte à comunicação serial UART TTL (5v)
disponíveis nos pinos 0 (Rx) e 1 (Tx). Para a comunicação com o computador, um chip
FT232RL, porta a informação para transmissão via USB, e seu driver virtual, disponibiliza
uma porta COM virtual, no computador.[7]
Figura 2 – Plataforma Arduino (modelo Duemilanove).
O micro-controlador embarcado na placa, vem com um bootloader pré programado, o
que torna possível a transferência de programas sem a necessidade de qualquer hardware
externo.
O Arduino é programável através de uma IDE própria. A linguagem utilizada também
é própria, no entanto muito parecida com C e aspectos de C++. Sua estrutura de programa,
baseia-se em dois componentes principais: Setup e Loop.
Setup, configura os pinos de entrada e saída, bem como as variáveis contidas no
programa. O loop, contém as linhas de código e arquitetura do programa .
14
Por ser de baixo custo e possuir interface intuitiva, o Arduino possui uma grande
comunidade de desenvolvedores e entusiastas, tornando-o bastante versátil e de simples
utilização.[3][5]
2.4. Detecção de face com OpenCV
O exemplo de detector de faces do OpenCV[12] utiliza o método que Paul Viola e
Michael Jones[14] publicaram em 2001. Usualmente chamado de método de Viola-Jones, esta
aproximação, para detectar objetos em imagens, combina quatro conceitos chave:
• Características retangulares simples, denominadas características Haar
• Uma Integral de Imagem para detecção rápida de características
• O método AdaBoost de aprendizado de máquina
• Um classificador em cascata para combinar com eficiência tais características
As características que Viola e Jones usaram são baseadas em pequenas ondas Haar.
Ondas Haar são ondas quadradas de comprimento único. Em duas dimensões, uma onda
quadrada é um par de retângulos adjacentes – um claro e outro escuro.
Figura 3 – As duas primeiras características Haar na cascata original de Viola-Jones.
As combinações reais de retângulos usadas para detecção visual de objetos não são
ondas Haar verdadeiras. Na verdade, contém combinações de retângulos mais apropriadas
para tarefas de reconhecimento visual. Devido a esta diferença, estas características são
denominadas características Haar, ao invés de ondas Haar.
15
Figura 4 – Exemplo de características Haar usados no OpenCV.
A presença de uma característica Haar é determinada subtraindo o valor médio do pixel
da região escura do valor médio do pixel da região clara. Se a diferença estiver acima de um
limite (estabelecido durante o processo de aprendizagem), a característica é dada como
presente.
Para determinar a presença ou ausência de centenas de características Haar em toda
localização da imagem e em diferente escalas com eficiência, Viola e Jones utilizaram uma
técnica chamada Integral de Imagem. Em geral, “integrar” significa somar pequenas unidades.
Neste caso, pequenas unidades são valores de pixels. O valor integral para cada pixel é a
soma de todos os pixels acima e a sua esquerda. Começando do lado superior esquerdo e
atravessando até o canto inferior direito, a imagem inteira pode ser integrada com poucas
operações integrais por pixel.
Figura 5 – Truque da Integral de Imagem.
Figura 5 – 1) Após integrar, o pixel em (x, y) contém a soma de todos os valores de
pixel no retângulo hachurado.
Figura 5 – 2) Analogamente à figura 5 – 1, a soma dos valores de pixel no retângulo D
é (x4, y4) - (x2, y2) - (x3, y3) + (x1, y1).
16
Como mostrado na Figura 5 – 1, após a integração, o valor no local de cada pixel, (x,
y), contem a soma de todos os valores de pixels dentro de uma região retangular que tem um
canto na parte superior esquerda da imagem e outro em um local (x, y). Para encontrar o valor
médio do pixel neste retângulo, é necessário apenas dividir o valor em (x, y) pela área do
retângulo.
Se for necessário saber o valor somado para qualquer outro retângulo que não tenha um
canto do lado superior esquerdo, deve se fazer o que ilustra a Figura 5 – 2.
Supondo que fosse necessário obter os valores somados em D. Podemos fazer
A+B+C+D, menos a soma dos retângulos A+B e A+C, mais a soma dos valores dos pixels em
A. Em outras palavras, D = A + B + C + D – (A+B) – (A+C) + A.
Para selecionar as características Haar específicas para usar, e estabelecer os níveis de
limite, Viola e Jones utilizam um método de aprendizado de maquina denominado AdaBoost.
O AdaBoost combina muitos classificadores “fracos” para criar um classificador “forte”.
Aqui, “fraco” significa que o classificador apenas obtém a resposta certa com um pouco mais
de freqüência do que uma adivinhação aleatória teria. No entanto, com uma grande
quantidade de classificadores fracos e cada um pressionando um pouco para a direção correta,
teremos uma forte força combinada para chegar à resposta correta. O AdaBoost seleciona um
conjunto de classificadores fracos para combinar e atribuir um peso para cada um. Esta
combinação balanceada é o classificador forte.
17
Figura 6 – Classificador em cascata é uma cadeia de filtros.
Viola e Jones combinaram uma serie de classificadores AdaBoost como um filtro de
cadeia, mostrado na figura 6, que é especialmente eficiente para a classificação de regiões de
imagens. Cada filtro é um classificador AdaBoost com um número bastante pequeno de
classificadores fracos.
O limite de aceitação em cada nível é estabelecido baixo o suficiente para passar todos,
ou quase todos, exemplos de face no conjunto de treinamento.
Os filtros em cada nível são treinados para classificar imagens de treinamento que
passaram por todos os estágios anteriores. (o conjunto de treinamento é um grande banco de
dados de faces) Durante o uso, se algum desses filtros falhar em passar uma região de
imagem, esta região é imediatamente classificada como “Sem Face”. Quando um filtro passa
18
uma região de imagem, ela vai para o próximo filtro da cadeia. Regiões de imagem que
passam através de todos os filtros na cadeia são classificadas como “Face”.
A ordem dos filtros na cascata é baseada no peso da importância que é atribuída ao
AdaBoost. Os filtros mais pesados devem antes, para eliminar regiões de imagem sem face o
quanto antes, tornando mais simples a tarefa de identificar faces.
Figura 7 – Exemplo de detecção de uma, ou mais faces com o programa em Processing
2.5. Rastreamento facial
Usualmente, para efetuar-se tarefas de rastreamento em um vídeo, utiliza-se algoritmos
próprios como o CamShift[15] (Continuously Adaptive Mean Shift), que se baseia na cor do
objeto para distingui-lo do fundo.
Todavia, o rastreamento facial, para esta aplicação, conta com a utilização das técnicas
de detecção de face, descritas previamente. Através do método de Viola Jones[14], no vídeo
apresentado pela web câmera, faces são detectadas quadro a quadro e sinalizadas através de
retângulos como apresenta a figura 7.
O “vídeo” gerado pela câmera, é visto pelo programa em Processing, como uma
sequência de imagens estáticas, o que torna possível a identificação de características Haar, e
posteriormente sinalização (através de um retângulo) das faces presentes.
19
2.6. Servo motores de hobby
Os servo motores de hobby[6], doravante denominados servos, foram criados com a
finalidade de eliminar a necessidade da criação de um sistema de controle para cada diferente
aplicação.
Através da utilização de servos, etapas como o projeto de sistema de controle, análise
de resposta transiente, ajuste da malha de realimentação, escolha de motor e escolha de
proporção de engrenagens foram muito simplificadas fazendo com que sua utilização fosse
difundida.
Os servo motores, desde a década de 1990, têm usado um padrão de modulação por
largura de pulso para controlar a posição do eixo de saída. O pulso é enviado ao servo via
linha de controle. A linha de controle não fornece tensão diretamente ao motor e sim a uma
entrada do chip de controle, presente dentro da estrutura do servo, que por sua vez controla o
motor que utiliza uma fonte externa de alimentação. Consequentemente, pode-se utilizar
qualquer tecnologia(CMOS, TTL ou componentes discretos) para gerar o sinal de controle.
Como a tensão é suprida separadamente, o terra de tensão deve ser o mesmo terra de
controle para que o dispositivo tenha os mesmos parâmetros e funcione corretamente.
Apesar de possuir apenas três fios, os fabricantes não padronizaram os pinos, no
entanto, em sua maioria, os servos tem um fio preto que indica o terra, vermelho para a tensão
de fonte e o branco para o controle.
Os fios de tensão transportam a maioria da corrente ao motor. A corrente varia de
quase 0 a 9.6mA, quando o servo não recebe nenhum sinal de controle a um máximo de
corrente de 600mA quando operando com carga máxima.
A tensão nominal dos servos é de 5 Volts, ao passo que se aplicado um valor maior,
estes podem ser danificados.
O sinal de controle, como mencionado antes, é feito através de modulação por largura
de pulso, ou PWM. Para um sinal baixo a tensão do sinal deve ser de 0 volts (0 lógico) e 5
volts para um sinal alto (1 lógico).
20
Figura 8 – relação entre largura de pulso e posição do servo.
O controle lógico do servo, antes do sinal modulado (PWM), precisa de um sinal de no
mínimo um milissegundo para
A parte de controle do sinal é fragmentada em tempos mínimos de 1ms, o sinal PWM
de 1ms descrito previamente, e um delay de aproximadamente 20ms. Este delay não é tão
crítico como outras partes do sinal de tempo. Essencialmente, este é o tempo ocioso entre os
sinais de controle. Se os sinais de controle forem repetidos muito rapidamente (ex. delay de
10ms), o servo irá zunir e ficar instável. Se os sinais forem repetidos muito vagarosamente
(ex. delay de 70ms) o servo será desligado entre os sinais e sua posição não permanecerá
constante.
Os servos possuem seu próprio circuito embarcado em sua estrutura. Este circuito
consiste em um comparador de largura de pulso, que compara o sinal de entrada com um
temporizador que possui período que depende da resistência de um potenciômetro conectado
ao eixo do motor. A realimentação é responsável pela estabilidade do circuito de controle. A
diferença entre o sinal de controle e o sinal de realimentação é o sinal de erro. Este sinal de
erro é usado para controlar um flip-flop que altera a direção que a corrente flui pelo motor. A
saída do flip-flop controla um circuito de Ponte H que entrega uma maior corrente ao motor.
21
3. OBJETIVO DO PROJETO
Este projeto tem como propósito o desenvolvimento de um sistema autônomo básico,
de baixo custo, para a identificação de indivíduos, e posteriormente mantê-los no campo de
visão da câmera de acordo com seus movimentos.
Para o desenvolvimento experimental do projeto, foi utilizado uma web câmera VGA
comum, servo motores, plataforma micro controlada, Arduino, para controle de motores e um
programa em Processing para o manipulamento de imagem e geração do sinal de controle.
4. MATERIAIS E METODOLOGIA
Para que este projeto fosse realizado, os materiais listados e a metodologia a seguir
foram utilizados.
4.1. Materiais
Foram utilizados os seguintes materiais:
• Câmera de vídeo para aquisição de imagens (web câmera VGA comum).
• Servo-motores de 9G, comumente utilizados em aplicações de hobby para modelos
radio controlados.
• Configuração para servos em Pan e Tilt.
• OpenCV.
• Processing.
• Arduino.
4.2. Metodologia
O projeto foi dividido da seguinte maneira:
1. Planejamento
Consistiu em pesquisa bibliográfica e início do desenvolvimento do software a ser
22
utilizado para a manipulação de imagens.
2. Desenvolvimento
Consistiu no desenvolvimento do projeto, conclusão do desenvolvimento do
software, montagem dos motores em configuração pan-tilt, calibração do software
e programação do micro controlador.
3. Fase experimental
Foram realizados testes para averiguar a velocidade de resposta, precisão e
viabilidade do sistema criado.
4. Conclusão
Através dos resultados obtidos com as etapas anteriores, e análise crítica do
processo, obteve-se uma conclusão.
5. DESENVOLVIMENTO
Com base na Figura 1, desenvolveu-se uma estrutura capaz de suportar dois servo-
motores na configuração necessária. Como resultado, obteve-se a estrutura apresentada na
foto a seguir.
23
Figura 9 – Foto da estrutura de Pan e Tilt dos servo-motores.
De posse da configuração de servos em pan e tilt juntamente com a câmera, foram
feitas conexões elétricas de maneira a conectar os motores à saída de sinal do micro
controlador.
Como o Arduino possui, em sua estrutura, um regulador de tensão que fornece saídas
estáveis de tensão em 5 e 3.3V, para esta aplicação não foi necessária a utilização de fonte
externa, uma vez que os servos necessitam de uma tensão de 5v e o ATMEGA 168 de 3.3V
para funcionarem corretamente.
Outra funcionalidade da plataforma Arduino, é a criação de “escudos” que podem ser
facilmente conectado sobre a placa, tornando as ligações elétricas mais organizadas e menos
laboriosas. Com este fim, foi criado um escudo que apresenta as mesmas ligações da figura a
seguir.
24
Figura 10 – Arduino conectado aos servos de pan e tilt.
Para facilitar o entendimento, gerou-se o diagrama de blocos que pode ser visto na
próxima figura.
Figura 11 – Diagrama de blocos do hardware.
25
A figura a seguir mostra, em detalhe, o escudo criado para acoplagem do hardware ao
Arduino.
Figura 12 – Foto do escudo para acoplagem do hardware ao Arduino.
26
A imagem a seguir apresenta o detalhe do escudo montado sobre o Arduino.
Figura 13 – Escudo montado sobre o Arduino.
Detalhe do conjunto completo, isto é, Arduino com escudo montado e câmera montada
sobre a estrutura de pan e tilt.
Figura 14 – Hardware completo.
27
Com o hardware pronto, para implementação, utilizou-se a plataforma Mac, uma vez
que todos os aplicativos necessários são multi-plataforma. Garantindo o mesmo
funcionamento em outras plataformas suportadas desde que sob arquitetura Intel.
Foram instalados os aplicativos Arduino, Processing, a biblioteca de OpenCV para
Processing e Fritzing (necessário para gerar as Figuras 10 e 11).
Uma vez que a IDE do Arduino provém do Processing, a sua estrutura se mostrou mais
eficaz quanto a comunicação serial, necessária para transmitir dados obtidos através da
câmera para o micro controlador. O que fez portanto, o Processing, ser escolhido como
ambiente de desenvolvimento da aplicação.
Alterou-se o código de um exemplo de reconhecimento facial que acompanha a
biblioteca de OpenCV, para que o mesmo, além de rastrear faces, fosse capaz de gerar dados
da posição do retângulo, que delimita a face, em relação ao quadro fazendo com que
posteriormente o programa do micro controlador pudesse corrigir o ângulo e manter o
retângulo sempre no centro do quadro.
O programa exemplo, inicializa a câmera, gera uma janela de 320x240 pixels e aplica
um filtro deixando a imagem em escala de cinza, de maneira a reduzir substancialmente os
detalhes desta, podendo assim, de maneira mais simples, com menor quantidade de memoria
alocada e menor custo computacional, executar o reconhecimento e posterior rastreamento da
face presente no quadro.
Após a aplicação do filtro, o software se utiliza do algoritmo de reconhecimento facial
do OpenCV, e gera um retângulo através de comandos e classes do Processing ao redor da
face a ser rastreada.
Para tornar possível a correção da posição do quadro por intermédio do motor, foi
necessário a criação de variáveis, para armazenar o valor referente ao meio da tela, e em
seguida comparar com a posição do retângulo gerado previamente.
A fim de eliminar a constante correção de desvio de angulo, para evitar a tremulação na
imagem, adicionou-se uma variável para armazenar um intervalo de valor, fazendo com que
apenas haja correção do quadro quando a diferença entre o centro da tela e do retângulo for
maior que esta variável. Resultando em uma imagem mais estável e agradável. Como
apresenta a figura a seguir.
28
Figura 15 – Detecção de face dentro da zona de erro.
O código comentado para o aplicativo em Processing pode ser visto no Apêndice 1.
Tendo em mãos os dados obtidos através da análise da imagem gerada pela câmera,
optou-se por transmiti-los via comunicação serial ao Arduino, por ser mais simples e eficaz.
Além do fato de a IDE do Arduino ser derivada do Processing fazendo com que ambos
programas, se comuniquem muito bem, tornando esta escolha uma opção ainda mais atrativa
em relação ao OpenCV puro.
Via serial, são enviados comandos que consistem em dois bytes. O primeiro é a
identidade do servo, ou seja, qual dos motores será selecionado. O segundo consiste na
posição para qual o servo deve se mover.
Para o envio dos bytes, foi necessário selecionar a porta serial COM1 (valor que pode
ser alterado através do programa em Processing caso o Arduino seja utilizado por outra porta).
Caso o micro controlador receba um byte que condiz com a identidade de um dos
servos, ele aguarda pelo próximo byte de posição atribuindo assim, o valor recebido ao servo
previamente identificado.
O programa em Arduino se utiliza da biblioteca de servos, para facilitar e tornar mais
limpa sua implementação.
Basicamente foram criadas duas instâncias. Uma para cada servo, atribuindo pinos para
saída do sinal de controle gerado pelo micro controlador. E uma variável para armazenar os
dados recebidos via porta serial.
29
O programa utiliza um Baud Rate de 57.600bps para a transferência de dados. Apesar
de suportar transferências de até 150.000bps, a taxa de 57.600 foi escolhida a fim de se
respeitar o delay de 20ms imposto pelo servo para que seu comparador tenha tempo de
processar a informação, evitando perda de dados e impedindo que o servo motor se torne
instável.
Desta maneira, ao alimentar o Arduino, ambos os servos se reportam à posição inicial
de 90 graus e dão inicio ao loop de programa que passa a aguardar por informações na porta
serial agindo apenas se o caractere adquirido for condizente com a identidade de um dos
servos e reportando a correção indicada pela próxima informação. Executando assim, a
função desejada. Como indica o fluxograma a seguir.
Figura 16 – Fluxograma de controle de servos.
O programa em Arduino se utiliza de uma biblioteca interna para o controle dos servos.
No entanto, esta biblioteca tem basicamente a função de transformar os dados de movimento
do servo de graus para milissegundos e então gerar o sinal requerido para mover o motor. O
Não atua
Atualiza posição dos
servos
Verifica próximo bit
de dados
Sim Não Confere com identidade do
servo?
Aguarda Caractere na Porta COM
30
Arduino trabalha em uma frequência de 16MHz, conta com um temporizador de 8 bits
(variando a escala de 0 a 255), um fator de redução de escala de 64 (devido ao temporizador
interno utilizado do ATMEGA168) e outro temporizador que conta tempo de subida e descida
(onda triangular). Se o temporizador contar de 0 até 255 e voltar a zero, existirão 510 pulsos
de clock, que deverão ser divididos por 2 (para compensar subida e descida) resultando em
um valor máximo de 255, que é utilizado para calcular a freqüência de saída PWM. Desta
forma a freqüência de saída PWM é de aproximadamente 500Hz, gerando um ciclo de
trabalho de 2ms [13]. De posse deste valor e como ilustra a figura 7, a biblioteca tem como
função, de acordo com a posição desejada e através de uma regra de três, converter o valor em
graus para um valor em ciclo de trabalho em milissegundos. Que por conseguinte reportará o
servos à posição desejada.
O código comentado para o aplicativo em Arduino pode ser visto no Apêndice 2.
CONCLUSÃO
O primeiro passo, foi a criação da estrutura de apoio para movimentos em pan e tilt dos
servos, baseado na figura 1 e observando o alcance máximo dos movimentos para que se
obtivesse um dispositivo que tivesse seus movimentos limitados apenas pelas limitações de
hardware dos servos. Em seguida, montou-se os motores sobre a estrutura deixando-a
completamente funcional.
Calibrou-se o hardware pronto, para que a posição inicial fosse de 90 graus em amos os
servos e em seguida acoplou-se a câmera sobre a estrutura, conferindo a esta, movimento em
ambas direções de pan e tilt.
Para movimentar a câmera de forma autônoma, utilizou-se dados obtidos através da
imagem fornecida por esta. Um programa, escrito em Processing, utilizou bibliotecas do
OpenCV para encontrar faces na imagem e mantê-las sob rastreamento. O mesmo programa
ainda foi responsável por entregar ao Arduino, via comunicação serial, os dados para a
movimentação dos motores pertinentes à correção de erro desejada.
Ainda no programa em Processing, alguns parâmetros foram mudados por motivos de
avaliação e testes.
31
O primeiro a ser variado foi o erro de centro de tela. Foram testados valores entre 1 e
20. Concluiu-se que o valor de erro igual a 15 é ideal, pois abaixo deste valor, o sistema tende
a corrigir a posição muito frequentemente tornando a imagem instável. Acima de 15, a
correção se mostrou lenta e não tão eficaz pois o indivíduo pode se mover com maior
liberdade dentro do quadro e não ter a posição da câmera corrigida.
Posteriormente, variou-se o grau de correção a ser aplicado aos servos. Concluiu-se que
quanto menor o grau, mais preciso foi a correção, portanto para este parâmetro, o melhor
valor encontrado foi de 1. Desta maneira, os motores apresentaram um movimento suave e
certeiro.
As vantagens da utilização de softwares como Processing e Arduino, é bastante visível
na facilidade de comunicação e troca de informações entre ambos, devido a uma origem
comum. No entanto, a necessidade de manter a IDE do Arduino aberta para a recepção de
dados pode representar uma desvantagem quando operando em computadores com recursos
restritos. Além disso, como o Processing utiliza uma linguagem de mais alto nível do que a
utilizada pelas interfaces do OpenCV, o custo computacional se torna maior tornando a
aplicação ligeiramente mais lenta.
Uma alternativa para esta desvantagem, seria a utilização do OpenCV com uma
interface em linguagem de mais baixo nível como C, para otimizar o código e obter uma
resposta em menos tempo.
No entanto, como o sistema deve respeitar velocidade de operação do servo, que é
muito menor do que aquela necessária para o OpenCV encontrar faces no aplicativo em
Processing, concluiu-se que a utilização da metodologia descrita é suficiente para esta
aplicação.
O programa em Processing é capaz, através do OpenCV, de encontrar mais de uma
face no mesmo quadro, caso presente. No entanto, o rastreamento será feito apenas para
aquela que possuir menor distância a partir da câmera, ou seja, o rosto que possuir o maior
quadrado o delimitando.
O sistema mostrou se funcional e responsivo para tanto para movimentos nos eixos de
pan e de tilt separadamente, quanto em ambos simultaneamente, cumprindo assim, o
propósito deste trabalho.
32
REFERÊNCIAS [1] GREGORI, E. - Introdução a visão embarcada e a biblioteca OpenCV, disponível em:
http://www.embedded.com/Home/PrintView?contentItemId=4372167 - acessado em
Outubro de 2012.
[2] OpenCV, disponível em:
http://www.opencv.org/about.html - acessado em Outubro de 2012.
[3] Processing, disponível em:
http://www.processing.org/about - acessado em Outubro de 2012.
[4] Wiring, disponível em:
http://wiring.org.co/about.html - acessado em Outubro de 2012.
[5] Especificações da Placa Arduino Duemilanove, disponível em:
http://www.arduino.cc/en/Main/ArduinoBoardDuemilanove - acessado em Abril de
2011.
[6] SAWICZ, D. - Hobby Servo Fundamentals, disponível em:
http://www.princeton.edu/~mae412/TEXT/NTRAK2002/292-302.pdf - acessado em
Abril de 2011.
[7] Datasheet ATMEGA168, disponível em:
http://www.atmel.com/dyn/resources/prod_documents/doc2545.pdf - acessado em Abril
de 2011.
[8] Kit de pan and tilt para servos, disponível em:
http://letsmakerobots.com/node/11421 - acessado em Abril de 2011.
[9] Sensores CCD Vs. CMOS, comparações, disponível em:
http://www.dalsa.com/corp/markets/ccd_vs_cmos.aspx - acessado em Abril de 2011.
[10] SEBE, N. Machine Learning in Computer Vision, FACIAL EXPRESSION
RECOGNITION, p. 187 – 200. 2005 - Springer
[11] CHEN, C. H.; WANG, P. S. P., Handbook of Pattern Recognition and Computer Vision,
Pattern Recognition with Local Invariant Features, p. 71 – 90. 2004 - World Scientific.
[12] HEWITT, R. – Seing With OpenCV - SERVO Magazine Pg. 48 - 52, Fevereiro de 2007,
T & L Publications, Inc.
[13] SHIRRIFF, K. – Secrets of Arduino PWM. Disponível em:
http://www.arcfn.com/2009/07/secrets-of-arduino-pwm.html - acessado em Novembro
2012.
33
[14] VIOLA; JONES, Viola, P.; Jones, M., Rapid Object Detection using a Boosted Cascade
of Simple Features, Procedings of CVPR, Pg. 511-518, 2011
[15] ALLEN, G.; XU, R.; JIN, J. Object Tracking Using CamShift Algorithm and Multiple
Quantized Feature Spaces. In: NSW 2006, 2006.
34
Apêndice 1
Código comentado para o aplicativo em Processing.
import hypermedia.video.*; import java.awt.Rectangle; import processing.serial.*;
//Inclui a biblioteca de video para capturar imagens da camera. //Inclui uma classe de retangulos que a juda a manter o controle das coordenadas da face. //Inclui a biblioteca serial necessaria para a comunicação com o arduino.
OpenCV opencv; //Cria uma instância da biblioteca OpenCV.
//Valores de contraste e brilho. Int contrast_value = 0; int brightness_value = 0;
Serial port; //A porta serial para a comunicação.
//Identidades para a interface serial de comando em Arduino para os servos de Pan e Til char CanalTilt = 0; char CanalPan = 1;
//Variáveis para armazenar a localização x e y do meio da face detectada. int midFaceY=0; int midFaceX=0;
//Variáveis que correspondem ao meio da tela e serão comparadas aos valores do meio da face. int midScreenY = (height/2); int midScreenX = (width/2);
int midScreenWindow = 15; //"Erro" aceitável para o meio
de tela. //Grau de correção que será aplicado a cada servo cada hora que a posição for atualizada int stepSize=1;
void setup() { //Cria uma janela para o aplicativo.
35
size( width, height ); opencv = new OpenCV( this ); opencv.capture(width, height); opencv.cascade( OpenCV.CASCADE_FRONTAFACE_ALT);
//Abre stream de video. //Carrega a descriçõo de detecção
println(Serial.list()); // Lista portas COM disponíveis (Utilizado para descobrir qual porta serial está seno utilizaada pelo Arduino)
//Seleciona a primeira porta serial da lista (altere o valor entre [] se o aplicativo falhar em conectar o Arduino) port = new Serial(this, Serial.list()[1], 57600); //Baud rate selecionado em
57600 //Print de como utilizar.
println( "Drag mouse on X-axis inside this sketch window to change contrast" ); println( "Drag mouse on Y-axis inside this sketch window to change brightness" );
//Envia os ângulos iniciais de Pan e Tilt ao arduino para o Arduino fazer com que o dispositivo olhe para cima e para frente.
port.write(CanalTilt); port.write(servoTiltPosition); port.write(CanalPan); port.write(servoPanPosition);
}
//Envia a identidade do Servo de Tilt. //Envia a posição de Tilt (Atualmente 90 graus). //Envia a identidade do Servo de Pan. //Envia a posição de Pan (Atualmente 90 graus).
public void stop(){ opencv.stop(); super.stop(); }
void draw() {
opencv.read(); opencv.convert(GRAY ); opencv.contrast( contrast_value ); opencv.brightness( brightness_value );
//Pega um novo quadro. //Converte para cinza.
36
//Procede com a detecção. Rectangle[] faces = opencv.detect( 1.2, 2, OpenCV.HAAR_DO_CANNY_PRUNING, 40, 40 ); //Apresenta a imagem. image( opencv.image(), 0, 0 ); //Desenha área de face (s). noFill(); stroke(255,0,0); for( int i=0; i<faces.length; i++ ) {
rect( faces[i].x, faces[i].y, faces[i].width, faces[i].height );
}
//Descobre se alguma face foi detectada. if(faces.length > 0){
//Se uma face foi detectada, encontra o ponto médio da primeira face no quadro. //NOTA: As coordenadas x e y correspondem ao canto superior esquerdo do retângulo. //portanto, manipulamos estes valores para achar o ponto médio do retângulo. midFaceY = faces[0].y + (faces[0].height/2); midFaceX = faces[0].x + (faces[0].width/2);
//Descobre se a componente y da face está abaixo do meio da tela. if(midFaceY < (midScreenY - midScreenWindow)){
if(servoTiltPosition >= 5)servoTiltPosition -= stepSize;
}
//Se estiver abaixo do meio da tela, atualiza a variável de posição para abaixar o servo de Tilt.
//Descobre se a componente y está acima do meio da tela. else if(midFaceY > (midScreenY + midScreenWindow)){
if(servoTiltPosition <= 175)servoTiltPosition +=stepSize;
}
//Atualiza a variável de posição para elevar o servo de Tilt.
37
//Descobre se a componente X da face está esquerda do meio da tela. if(midFaceX < (midScreenX - midScreenWindow)){
if(servoPanPosition >= 5)servoPanPosition -= stepSize;
}
//Atualiza a variável de posição de Pan para mover o servo para a esquerda.
//Descobre se a componente X da face está a direita do meio da tela. else if(midFaceX > (midScreenX + midScreenWindow)){
if(servoPanPosition <= 175)servoPanPosition +=stepSize;
} }
//Atualiza a variável de posição Pan para mover o servo para a esquerda.
//Atualiza as posições de servo enviando comando serial para o Arduino.
port.write(CanalTilt); port.write(servoTiltPosition); port.write(CanalPan); port.write(servoPanPosition); delay(1);
}
//Envia a identidade do servo de Tilt. //Envia a posição de Tilt atulizada. //Envia a identidade de servo de Pan. //Envia a posição de Pan atualizada.
//Altera os valores de Contraste e Brilho. void mouseDragged() {
contrast_value = (int) map( mouseX, 0,width, -128, 128 ); brightness_value = (int) map( mouseY, 0,width, -128, 128 );
}
38
Apêndice 2
Código comentado para o aplicativo em Arduino
#include <Servo.h> //Biblioteca de servos para o controle de Pan e Tilt
//Variaveis que armazenam as Identidades dos servos. char CanalTilt=0; char CanalPan=1;
//Nome de cada servo. Servo servoTilt; Servo servoPan;
//Variavel para armazenar os dados da porta serial. char CharSerial=0; void setup(){
servoTilt.attach(10); servoPan.attach(11); servoTilt.write(90); servoPan.write(90);
//Servo de Tilt anexado ao pino 10. //Servo de Pan anexado ao pino 11. //Inicialmente seta os servos para a //posiçao de 90 graus.
Serial.begin(57600); }
//Inicia a conexao serial em 57600 bps.
void loop(){ while(Serial.available() <=0); CharSerial =Serial.read(); if(CharSerial == CanalTilt){ while(Serial.available() <=0); servoTilt.write(Serial.read());
}
//Aguarda um caractere na porta serial. //Copia o caractere da porta para a variavel. //Verifica se o caractere e a identidade do servo de Tilt. //Aguarda pelo segundo byte de comando da porta serial. //Ajusta o servo de Tilt para o valor recebido pelo segundo byte de comando.
else if(CharSerial == CanalPan){ while(Serial.available() <= 0);
servoPan.write(Serial.read()); } }
//Verifica se o caractere e a identidade do servo de Pan. //Aguarda pelo segundo byte de comando da porta serial //Ajusta o servo de Tilt para o valor recebido pelo segundo byte de comando.
//Se o caractere recebido nao for a identidade do servo, sera ignorado.