SlideShare uma empresa Scribd logo
1 de 145
Baixar para ler offline
RA on-demand
Criando interfaces em tempo de execução.
08:38fb.com/RVA.BR
2
Construção de interfaces on-
demand baseadas em
Realidade Aumentada
Projetiva para Controle de
Hardware (Arduino)
Drª. Ana Maria
Ambrosio
MSc. Christopher
Cerqueira
aluno
doutorado
Dr. Claudio Kirner
Objetivo do Capítulo
SketchSynth
BackStage
08:38fb.com/RVA.BR
4
Objetivo da Apresentação
08:38fb.com/RVA.BR
5
Objetivo da apresentação
• Devido as restrições, vamos montar uma versão simplificada:
• Ausência de projetores para todos os alunos
• Ausência de ARDUINO para todos os alunos
• Mostrar um framework para construção de apps de RA / RC.
• openFrameworks
• Mostrar os recursos de controle de hardware (Arduino)
• Mostrar os recursos de CV (openCV): rastreio de contorno
(infraestrutura e controles) e processamento de imagem
(mão).
• Mostrar tipos comuns para criação de interface.
• openFrameworks
• Aplicações tipo interação em mesa. (Projeção)
08:38fb.com/RVA.BR
6
Agenda:
• Conceito e openFramework
• Criando o primeiro programa em openFrameworks
• Conectando com o Arduino
• Estudos de caso / Construção do ambiente (exemplos):
• 1. Detectar infraestrutura (Apenas rastreio do papel)
• 2. Rastreio do atuador (rastreio da mão)
• 3. Interação com estrutura virtual
• 4. Detectar estrutura física on-demand (sem reprojeção)
• Wrap-Up
3 horas
1,5h
1,5h
08:38fb.com/RVA.BR
7
Conteúdo está em
•http://www.4shared.com/folder/Xka
Uh0KM/Resources.html
• Link tá muito difícil??? Vai em
cscerqueira.com.br
08:38fb.com/RVA.BR
8
CONCEITOS
Básico - Experiências
08:38fb.com/RVA.BR
9
“The product is no longer the
basis of value. The
experience is.”
Venkat Ramaswamy
The Future of Competition
08:38fb.com/RVA.BR
10
Valor de uma boa experiência
08:38fb.com/RVA.BR
11
Interação
Texto, som,
cores, visual,
mecânico ou
físico.
Interface
Mensagens
Usuário Sistema
08:38fb.com/RVA.BR
12
Usabilidade
08:38fb.com/RVA.BR
13
Exemplo:
• Usabilidade:
1. Facilidade de
aprendizado
2. Eficiência
3. Facilidade de
memorização
4. Erros
5. Satisfação subjetiva
Meta-
Mensagens
Usuário Sistema
08:38fb.com/RVA.BR
14
3 níveis
Lógico: Resolvem, solucionam,
facilitam.
Emocional: Satisfazem
necessidades e desejos
afetivos.
Visceral: resolvem questões
fundamentais, sem
consciência.
Impulso.
08:38fb.com/RVA.BR
15
Espera.... Visceral?
08:38fb.com/RVA.BR
16
08:38fb.com/RVA.BR
17
Realidades – Realidade Virtual
interface que permite ao
usuário interagir, em tempo real,
com um mundo
tridimensional gerado por
computador, usando seus
sentidos através de
equipamentos especiais.
SOURCE: NASA (2013a)
08:38
18
fb.com/RVA.BR
Billinghurst Vision
08:38fb.com/RVA.BR
19
Realidades – Realidade Aumentada
uma interfacebaseada na
sobreposição de informações virtuais
geradas por computador (envolvendo
imagens estáticas e dinâmicas, sons
espaciais e sensações hápticas) com o
ambiente físico do usuário, percebida
através de dispositivos tecnológicos e
usando as interações naturais do
usuário, no mundo físico.
Claudio Kirner
SOURCE: Adapted from ESA (2009) and Capua (2008)
08:38
20
fb.com/RVA.BR
Christopher Vision
Informação virtual
Interação Natural
dispositivos tecnológicos
08:38
21
fb.com/RVA.BR
Realidades – Realidade Cruzada
é um ambiente de realidade misturada ubíqua, que
vem da fusão de uma rede de sensores e atuadores
(que coletam e enviam dados relacionados ao
mundo real) com mundos virtuais compartilhados,
usando a interface da realidade
aumentada.
Claudio Kirner
Introdução
08:38fb.com/RVA.BR
22
Kirner’s Diagram – elementos
Source: (KIRNER et al., 2012)
Lego
Cave
08:38fb.com/RVA.BR
23
Realidade Cruzada
Objetos reais
Sensores e
Atuadores
Realidade Aumentada
OCR
NOCR
NOCR
Introdução
08:38fb.com/RVA.BR
24
HIT - ROADMAP
CR AI
HI
AR
IoT
HR
KMatsuda
08:38fb.com/RVA.BR
25
[ ] Hololens
• Talvez o primeiro hardware de RA, com sobreposição, que
entra com força no mercado.
• Google Glass tentou, mas na maioria dos apps não tinha
sobreposição intrínseca.
• Vídeo 1
08:38fb.com/RVA.BR
26
Qual o motivo de RA ainda não ter
pego em atividades de engenharia?
HWs de
interação?
HWs de
visualização?
Frameworks
de rastreio
SWs
Frameworks
geo-localizados
Frameworks
de interação
08:38fb.com/RVA.BR
27
Um dos motivos ao nosso ver é:
• Dificuldade de criação e manipulação de uma interface
de RA a medida que é utilizada.
• Poderíamos então pensar em uma estratégia, de criação
de uma interface física e indicar sua camada virtual a medida
que é necessário (on-demand) e a função desejada.
• Esses minicurso essencialmente é para mostrar uma
opção de criação de interface em RA on demand.
• “Solução simplificada: openFrameworks + visão computacional.”
08:38fb.com/RVA.BR
28
OPENFRAMEWORKS
08:38fb.com/RVA.BR
29
Processing
Adobe Flash
Unity
Cinder
openFrameworks
08:38fb.com/RVA.BR
30
openframeworks.cc
• Vídeo oF1....media_videos7_openFrameworks1.mp4
• Vídeo oF2....media_videos7_openFrameworks2.mp4
08:38fb.com/RVA.BR
31
oF
• Criado para artistase designers
• Desenvolvido por: Zach Liberman, Theo Watson, Artuno
Castro e Chris O’Shea
•Proposta: Arrumar a falta de comunicação entre
diversas bibliotecas em C++, e permitir portabilidade.
• Escrita em C++
• Licença: MIT (educacional e venda)
• Usar quando:
• O projeto renderiza muitos gráficos 3D, e/ou;
• Utilizar muita visão computacional, e/ou;
• Controlar equipamentos, como, por exemplo:
• o ARDUINO.
08:38fb.com/RVA.BR
32
33
08:38fb.com/RVA.BR
C++ Portável!!!!
34
08:38fb.com/RVA.BR
Página Principal –
openframeworks.cc
08:38fb.com/RVA.BR
35
Libs no pacote padrão
• OpenGL, GLEW, GLUT, libtess2 e cairo para gráficos.
• rtAudio, PortAudio ou FMOD e Kiss FFT para entrada, saída e
análise de áudio.
• FreeType para fontes.
• FreeImage para salvar e carregar imagens.
• Quicktime e videoInput para playback e aquisição de vídeo.
• Poco, que contém uma variedade de utilidades.
08:38fb.com/RVA.BR
36
Addons da comunidade:
ofxaddons.com
08:38fb.com/RVA.BR
37
OSX,
Linux,
Windows,
iOS,
Android,
Linux
ARM
08:38fb.com/RVA.BR
38
ERA TROGLODITA (C++)
• Graduação (2010):
• ARToolKit
• PTAMM
• Bolsista DTI (2011):
• basAR
ERA DO FOGO (C++/oF)
• Mestrado (2012):
• Doutorado (2014):
08:38fb.com/RVA.BR
39
MDE (Model Driven Engineering)
MBSE (ModelBased SystemEngineering)
• MDE é um conjunto de práticas de
engenharia, baseadas em ferramentas
que utilizam ao mesmo tempo meta-
modelagem e transformações de modelos
para atingirem automaticamente
objetivos em produção, manutenção ou
operação de sistemas intensivos em
software.
40
Motivador - Matlab
08:38fb.com/RVA.BR
Três tipos principais de aplicações
MDE
MDE
Geração automática Descoberta do Modelo Interoperabilidade de
sistemas
41
Um modelo pode
ser transformado
em outro modelo.
Um meta-modelo é um conjunto
de conceitos e relações que o
modelo pode realizar.
“Filtro” de possibilidade.
Uma representação gera um
conjunto de elementos.
08:38fb.com/RVA.BR
MDE Natural Env.
08:38fb.com/RVA.BR
42
• Introdução à utilização de openFrameworks para o
desenvolvimento de aplicações de RVA
Link
• Construção de aplicações de Realidade Cruzada Projetiva
utilizando openFrameworks e ARDUINO
Link
• Utilização de Realidade Aumentada, com
marcadores(ARToolKitPlus) e outros (utilizando openCV), para
controle e inspeção de hardware, utilizando a interface
ARDUINO.
Link
08:38fb.com/RVA.BR
43
SVR2013 - Resultados
44
08:38fb.com/RVA.BR
SVR2014 - Resultados
08:38
45
fb.com/RVA.BR
WRVA2014 - Resultados
08:38fb.com/RVA.BR
46
PRIMEIRO PROGRAMA EM OF
Vou pular, coloquei aqui para ficar + completo
08:38fb.com/RVA.BR
47
Onde encontrar?
08:38fb.com/RVA.BR
48
Level Easy: Gerador
Automático
49
08:38fb.com/RVA.BR
Escolhendo expansões
50
DocoreoF
Dacomunidade
08:38fb.com/RVA.BR
Estrutura do projeto
08:38fb.com/RVA.BR
51
Exemplo básico
08:38fb.com/RVA.BR
52
// ofApp.cpp
void ofApp::setup(){
mensagem = "Hello SVR2015!!!";
raio = 0;
}
void ofApp::draw(){
ofEnableAlphaBlending(); ofSetColor(ofColor::blue,128);
ofCircle(x_i,y_i,raio);
ofSetColor(ofColor::red);
ofDrawBitmapString(mensagem,mouseX,mouseY);
}
// ofApp.cpp
void ofApp::mouseDragged(int x, int y, int button){
raio = ofDist(x_i,y_i,x,y);
}
void ofApp::mousePressed(int x, int y, int button){
x_i = x;
y_i = y;
}
void ofApp::mouseReleased(int x, int y, int button){
raio = ofDist(x_i,y_i,x,y);
}
// ofApp.h
...
string mensagem;
int x_i,y_i;
float raio;
...
ARDUINO
O que é? Onde vivem?
Existe? Hoje no Glob..
Fritzing, Arduino 1.0, Firmata, exemplo
openFrameworks
08:38fb.com/RVA.BR
53
O que tem no ARDUINO?
08:38
54
fb.com/RVA.BR
Outras versões
08:38
55
fb.com/RVA.BR
Shields
08:38
56
fb.com/RVA.BR
FIRMATA
Literatura indica FIRMATA:
http://firmata.org/wiki/Download
08:38
57
fb.com/RVA.BR
O que a FIRMATA faz!?
• Transforma o ARDUINO numa interface de controle, podendo
ser modificado por um host.
• Quais as vantagens?
• O host controla a execução!
• O host tem mais memória.
• O host resolve as lógicas de controle muito
mais rápido.
• Desvantagens?!
• Tem que ficar atrelado ao host!
08:38
58
fb.com/RVA.BR
Obs.: Mudança da nomenclatura
dos pinos após Firmata 2.3
(Arduino 1.0)
Tomar cuidado na hora de
desenvolver!!!!!!!!!!
08:38fb.com/RVA.BR
59
Instalando a Firmata no
Arduino
• Faça download do
Arduino 1.0.6
http://arduino.cc/en/
Main/Software
• Abra o sketch do
Firmata Standard.
• Transfira para a
board.
08:38fb.com/RVA.BR
60
http://arduino.cc/en/reference/firmata
“esquemático”
08:38
61
fb.com/RVA.BR
• #crashcourse fritzing
• http://fritzing.org/home/
Arduino e openFrameworks
08:38fb.com/RVA.BR
62
Métodos para conectar com o
ARDUINO
 connect()
 disconnect()
 getAnalog()
 getAnalogPinReporting()
 getDigital()
 getDigitalPinMode()
 getPwm()
 getString()
 isArduinoReady()
 isInitialized()
 sendAnalogPinReporting()
 sendByte()
 sendDigital()
 sendDigitalPinMode()
 sendPwm()
 sendReset()
 sendString()
 setUseDelay()
 update()
08:38
63
fb.com/RVA.BR
Código no openFrameworks
• Exploração do exemplo: communicationfirmataExample
08:38fb.com/RVA.BR
64
Fluxograma básico
08:38fb.com/RVA.BR
65
SETUP
Habilita callback
de Arduino Alive
Arduino
Responde Evento
Alive
Configura
Arduino
Loop de execução
– sem Arduino
Enviar comandos
pro Arduino
Recebeu um
evento Digital
Recebeu um
evento Analógico
Loop de execução
– Arduino Update
Código
08:38fb.com/RVA.BR
66
//ofApp.h
#pragma once
#include "ofMain.h"
class ofApp : public ofBaseApp{
public:
…
ofArduino ard;
bool bSetupArduino;
private:
void setupArduino(const int & version);
void digitalPinChanged(const int & pinNum);
void analogPinChanged(const int & pinNum);
void updateArduino();
};
//ofApp.cpp
void ofApp::setup(){
...
ard.connect("COM3", 57600); //conecta com arduino
ofAddListener(ard.EInitialized, this, &ofApp::setupArduino);
bSetupArduino= false;// flag arduino ok 
}
void ofApp::setupArduino(const int & version) {
ofRemoveListener(ard.EInitialized, this, &ofApp::setupArduino);
bSetupArduino = true; // agora pode usar o arduino.
ard.sendDigitalPinMode(2, ARD_INPUT); //pino entrada digital
ard.sendAnalogPinReporting(0, ARD_ANALOG); // pino entrada analógica
ard.sendDigitalPinMode(13, ARD_OUTPUT); // configura pino saída digital
ard.sendDigitalPinMode(11, ARD_PWM); // configura pino saída PWM
ard.sendServoAttach(9); // diz que o pino tem um servo.
ofAddListener(ard.EDigitalPinChanged, this, &ofApp::digitalPinChanged); //callback
para eventos de pino digital.
ofAddListener(ard.EAnalogPinChanged, this, &ofApp::analogPinChanged); //callback
para eventos de pino analógico
}
void ofApp::updateArduino(){
ard.update(); // verifica se algo mudou no Arduino - obrigatório
if (bSetupArduino) {
//envia o que for para o Arduino.
ard.sendPwm(11, (int)(128 + 128 * sin(ofGetElapsedTimef()))); // pwm...
}
}
//ofApp.cpp
void ofApp::digitalPinChanged(const int & pinNum)
{
// trata o pino digital - ard.getDigital(pinNum)
}
void ofApp::analogPinChanged(const int & pinNum)
{
// trata o pino analógico -
ard.getAnalog(pinNum)
}
//outros comandos
ard.sendServo(9, 180, false);
ard.sendDigital(8, ARD_HIGH);
ESTUDO DE CASOS:
08:38fb.com/RVA.BR
67
Casos
• 0.a. O que vamos fazer:
• 1. Detecção de infraestrutura (contornos)
• 2. Detecção de atuador (diferença de
imagens)
• 3. Interação mão / virtual / Arduino
• 4. Rastreio dos controles. (contornos)
• Real (Drawn) e Virtual Matching
08:38fb.com/RVA.BR
68
0.a. O que vamos
fazer:
Ambiente reativo à
altura da areia
Ambiente reativo ao
comportamento dos
pontos (soldados)
08:38fb.com/RVA.BR
70
Conceito de ambiente dividido
em pontos e camadas
08:38fb.com/RVA.BR
71
Diagrama de etapas
08:38fb.com/RVA.BR
72
O que vamos usar para o
exemplo
08:38fb.com/RVA.BR
73
Só use mais hardware quando
realmente precisar.
08:38fb.com/RVA.BR
74
DETECTING INFRASTRUCTURE
Encontrando uma
folha de papel para
servir de referência
para a montagem dos
elementos de
interação.
08:38fb.com/RVA.BR
75
Detectar a infraestrutura
Capturar
Imagem
Procurar
“coisas” brancas
Identificar
polígono
• Maior de todos?
é um
retângulo?
Encontrei a
infraestrutura
Retirar a
imagem da área
ide interação
08:38fb.com/RVA.BR
76
Exemplo: Rastreio de
Marcador
08:38fb.com/RVA.BR
77
USANDO O OPENCV
Cores, blobs e exemplos
08:38fb.com/RVA.BR
78
Cores
RGB-A (red, green, blue)-alfa HSV (hue (cor), saturation, value)
08:38
79
fb.com/RVA.BR
Blobs
• Método de busca de características.
• Blobs compartilham propriedades constantes que podem ser
“percebidas” na imagem.
08:38
80
fb.com/RVA.BR
Construção dos artefatos : Rastreio
Cores
08:38
81
fb.com/RVA.BR
Bonus: Projection Mapping
08:38fb.com/RVA.BR
82
PM
PM
Usos
• Table-tops
• Projeções em paredes
08:38
83
fb.com/RVA.BR
Sensetable
L.A.S.E.R. Tag
Climbing
OASIS
Continuando ....
Usando o addon: ofxCv de Kyle McDonald
https://github.com/kylemcdonald/ofxCv
08:38fb.com/RVA.BR
84
Tipo: ofxCv::ContourFinder
• Tipo/função que procura blobs numa imagem.
• Retorna os blobs e características:
• Posição
• Contorno
• Centroide, média centro, pontos das bordas, menor retângulo
contornável, menor elipse, etc etc etc...
08:38fb.com/RVA.BR
85
Project Generator addons
08:38fb.com/RVA.BR
86
// Camera:
ofVideoGrabber cam; // Video Tracking source
int camHeight;
int camWidth;
ofImage unwarped; // RAW image from camera
// Descobridor de papel
ofxCv::ContourFinder contourFinder;
int thresholdCV;
ofPolyline contour;
ofImage warpedPaper;
bool foundInfra;
// ## Função para retornar tipo de forma geométrica
private:
string findForm(const ofPolyline &poly);
template <class T>
string findForm(const T &poly){
return findForm(ofxCv::toOf(poly)); }
};
Câmera
Procurador
de papel
08:38fb.com/RVA.BR
87
Identificar Formas Convexas
• Entrada: número de vértices
• 3 vértices = TRIANGULO
• 4 vértices e cos +/- 0 = RETÂNGULO
• 5 vértices e cos +/- 0.3 = PENTÁGONO
• 6 vértices e cos +/- 0.5 = HEXÁGONO
• > 6 Círculo
• http://opencv-code.com/tutorials/detecting-simple-shapes-in-an-image/
• https://github.com/bsdnoobz/opencv-code/blob/master/shape-detect.cpp
08:38fb.com/RVA.BR
88
string ofApp::findForm(const ofPolyline &poly){
vector<ofPoint> corners = poly.getVertices(); // pega todos os vértices
if ( corners.size() == 3) return "TRIANGLE";
if ( corners.size() >= 4 && corners.size() <= 6){ // de 4 a 6 vertices
int vtc = corners.size();
vector<double> cos;
for( int j = 2; j < vtc+1; j++) // mandrakaria para organizar cosenos
cos.push_back(angle(corners[j%vtc], corners[j-2], corners[j-1]));
sort(cos.begin(),cos.end());
double minCos = cos.front();
double maxCos = cos.back();
if( vtc == 4 && minCos >= -0.1 && maxCos <= 0.3) {
cv::Rect r = cv::boundingRect(toCv(poly));
double ratio = std::abs(1 - (double)r.width / r.height);
return (ratio <= 0.02) ? "SQUARE" : "RECTANGLE"; }
if( vtc == 5 && minCos >= -0.34 && maxCos <= -0.27) return "PENTAGON";
if( vtc == 6 && minCos >= -0.55 && maxCos <= 0.45) return "HEXAGON";
} else { // testar se circulo }
return "NO_MATCH";}
08:38fb.com/RVA.BR
89
static double angle(ofPoint pt1, ofPoint pt2, ofPoint pt0)
{
double dx1 = pt1.x - pt0.x;
double dy1 = pt1.y - pt0.y;
double dx2 = pt2.x - pt0.x;
double dy2 = pt2.y - pt0.y;
return (dx1*dx2 + dy1*dy2)/sqrt((dx1*dx1 +
dy1*dy1)*(dx2*dx2 + dy2*dy2) + 1e-10);
}
08:38fb.com/RVA.BR
90
void ofApp::setup(){
// Parte 2 - Código do Exemplo
ofLogNotice("[PAPER DETECTOR]") << " Configure CV ";
contourFinder.setMinAreaRadius(10); // configura menor área .
contourFinder.setMaxAreaRadius(200); // configura maior área
thresholdCV = 100; // inicializa o nível da camera.
//contourFinder.setTargetColor(targetColor, trackingColorMode); //
configura cor / padrão
contourFinder.setThreshold(thresholdCV); // configura nível
ofLogNotice("[PAPER DETECTOR]") << " Configure Camera ";
camWidth = 640; camHeight = 480;
cam.initGrabber(camWidth,camHeight);
cam.listDevices();
unwarped.allocate(camWidth, camHeight, OF_IMAGE_COLOR); // //
ALLOCATE RAW IMAGE
warpedPaper.allocate(camWidth,camHeight,OF_IMAGE_COLOR);
}
08:38fb.com/RVA.BR
91
void ofApp::update(){
cam.update();
float area;
if(cam.isFrameNew()){
//ofLogNotice("[PAPER DETECTOR]") << "New Frame";
vector<cv::Point> maxQuad;//maior quadrado na imagem = folha de papel.
float maxArea = -numeric_limits<float>::infinity();//escolhe pela maior área.
contourFinder.findContours(cam); // realiza a procura por folhas brancas em um
fundo preto
int n = contourFinder.size();
for(int i = 0; i < n; i++){
//ofLogNotice("[PAPER DETECTOR]") << "update: " + ofToString(i);
ofPolyline minAreRect = toOf(contourFinder.getMinAreaRect(i));
vector<cv::Point> quad = contourFinder.getFitQuad(i);
area = contourFinder.getContourArea(i); //encontrar o maior quadrado na
imagem = folha de papel.
if (area > maxArea) {
//ofLogNotice("[PAPER DETECTOR]") << "1. " + ofToString(area) + " - " +
ofToString(maxArea);
maxArea = area;
maxQuad = quad;
}
}
08:38fb.com/RVA.BR
92
// teste se foi encontrado algo parecido com um retângulo.
this->foundInfra = false;
if ( this->findForm(maxQuad) == "RECTANGLE"){
this->foundInfra = true;
// warp paper
vector<Point2f> warpPoints;
warpPoints.push_back(maxQuad[3]); // para organizar a ordem dos pontos.
warpPoints.push_back(maxQuad[0]);
warpPoints.push_back(maxQuad[1]);
warpPoints.push_back(maxQuad[2]);
//copy(maxQuad.begin(), maxQuad.end(), back_inserter(warpPoints));
unwarpPerspective(cam, unwarped, warpPoints);
unwarped.update();
}
//ofLogNotice("[PAPER DETECTOR]") << "2. " + ofToString(area) + " - " +
ofToString(maxArea) + " - " + ofToString(this->foundInfra);
}
}
08:38fb.com/RVA.BR
93
void ofApp::draw(){
ofSetColor(ofColor::white); cam.draw(0,0);
ofNoFill();
int n = contourFinder.size();
for(int i = 0; i < n; i++) {
ofSetColor(ofColor::red); // smallest rectangle that fits the contour
ofPolyline minAreRect = toOf(contourFinder.getMinAreaRect(i));
minAreRect.draw();
ofSetColor(yellowPrint); // convex hull of the contour
ofPolyline convexHull = toOf(contourFinder.getConvexHull(i));
convexHull.draw();
ofSetColor(cyanPrint);
vector<cv::Point> quad = contourFinder.getFitQuad(i);
vector<cv::Point>::iterator it;
for (it = quad.begin(); it != quad.end(); it++) ofCircle(toOf(*it),3);
}
ofSetColor(255);
unwarped.draw(640, 0);
if(this->foundInfra){ ofDrawBitmapStringHighlight("Found
infra",10,ofGetHeight() - 80);}
ofDrawBitmapStringHighlight(ofToString(this->thresholdCV),10,ofGetHeight() -
100);
}
08:38fb.com/RVA.BR
94
Resultado Esperado
08:38fb.com/RVA.BR
95
WHERE IS MY HAND? DETECTING THE
ACTUATOR
Detectando a mão, caneta,
ou qualquer outra coisa
(medo) que você queira
usar para fazer interação.
08:38fb.com/RVA.BR
96
Rastrear mão (apontador 2D)
• Restrições (para facilitar)
Fundo homogêneo
Longe das quinas
Uma mão só
• Pseudo-código
• Fazer diferença entra o fundo e o frame atual para encontrar a
mão.
• Com a diferença rastreia o blob.
• Do blob calcula as quinas
• Das quinas pega a mais distante do centroide e que não seja
próximo das quinas ( braço).
08:38fb.com/RVA.BR
97
Lets code.... Babe!!!! 
#include "ofMain.h"
#include "ofxOpenCv.h" //Cabeçalho do OpenCV
#include "ofxCv.h"
class ofApp : public ofBaseApp{
...
int width, height, threshold;
ofVideoGrabber vidGrabber; // Componente do oF que pega a câmera.
ofxCvColorImage colorImage; // imagem capturada pela câmera
ofxCvGrayscaleImage grayBg, grayImage, grayDiff;// bg, cinza, diferença
bool bLearnBackground;
ofxCv::TrackingColorMode trackingColorMode;
ofxCv::ContourFinder contourFinder;
ofColor targetColor;
ofPoint apontador;
ofPoint encontraPontoMaisDistante();
};
08:38fb.com/RVA.BR
98
Tipo: ofPoint
• ofPoint é um tipo muito utilizado no openFrameworks que
faz as vezes de um ponto na área da janela.
• Com ele podemos posicionar pontos na área da janela.
• Essencialmente é um vetor X,Y,Z. Herda de ofVec3f
• Possui propriedades sobrecarregadas de operação de vetores.
08:38fb.com/RVA.BR
99
Setup
void ofApp::setup(){
width = 320; height = 240;
vidGrabber.initGrabber(width, height); //abre câmera
colorImage.allocate(width,height); //aloca memória para as imagens
grayBg.allocate(width,height);
grayImage.allocate(width,height);
grayDiff.allocate(width,height);
contourFinder.setMinAreaRadius(10); //configura rastreador
contourFinder.setMaxAreaRadius(150);
contourFinder.setTargetColor(ofColor::white, TRACK_COLOR_RGB);
threshold = 50;
bLearnBakground = true;
}
08:38fb.com/RVA.BR
100
Comparando imagens
08:38fb.com/RVA.BR
101
Update
void ofApp::update(){
vidGrabber.update(); // Pega frame da câmera
if(vidGrabber.isFrameNew()){ // é um frame novo ???
colorImage.setFromPixels(vidGrabber.getPixels(),width,height);
grayImage = colorImage;
if (bLearnBackground == true){
grayBg = grayImage;// salva o fundo da tela - TO ROUBANDO MESMO!
bLearnBackground = false;}
grayDiff.absDiff(grayBg, grayImage); // fazer fundo x atual
grayDiff.threshold(threshold);
contourFinder.setThreshold(threshold); // procurar blobs no atual
contourFinder.findContours(grayDiff);
apontador = encontraPontoMaisDistante(); // procurar “dedo”
}
}
08:38fb.com/RVA.BR
102
Marcando dedos (pontos
distantes)
08:38fb.com/RVA.BR
103
Ponto mais distante – p1
ofPoint ofApp::encontraPontoMaisDistante(){
int n = contourFinder.size(); //qtidade de blobs capturados
ofPoint maisDistante ; //nosso ponto mais distante
for(int i = 0; i < n; i++) {
ofVec2f centroid = toOf(contourFinder.getCentroid(i)); //Centroide;
ofPolyline convexHull = toOf(contourFinder.getConvexHull(i)); //quinas;
vector<ofPoint> vertices = convexHull.getVertices(); // vetorDeQuinas
vector<ofPoint>::iterator itVec; // para percorrer as quinas.
maisDistante = (*vertices.begin());
float tamMaisDistante = centroid.distanceSquared(maisDistante);
float distanciaAtual = 0;
08:38fb.com/RVA.BR
104
Ponto mais distante – p2
for(itVec = vertices.begin(); itVec != vertices.end(); itVec++){
//encontrar ponto mais distante do dedo --> eliminar as bordas
if( ((*itVec).x > 40) && ((*itVec).x < width - 40) &&
((*itVec).y > 40) && ((*itVec).y < height - 40)){ //elimina bordas
distanciaAtual = centroid.distanceSquared((*itVec));
if(distanciaAtual > tamMaisDistante){ //maior “simple as possible”
maisDistante = (*itVec);
tamMaisDistante = distanciaAtual;
}
}
}
}
return maisDistante;
}
08:38fb.com/RVA.BR
105
Draw
void ofApp::draw(){
ofSetColor(255); grayImage.draw(0, 0); // desenha câmera
ofTranslate(320, 0); grayDiff.draw(0, 0); // desenha threshold
ofTranslate(-320,240); contourFinder.draw(); //desenha contorno
encontrado
ofSetColor(ofColor::hotPink);
ofDrawBitmapString("openCV Threshold: " +
ofToString(threshold),50,50);
ofTranslate(0,-240);
ofFill();
ofSetColor(ofColor::green);
ofCircle(apontador,5); //desenha bola verde no “dedo”
}
08:38fb.com/RVA.BR
106
Resultado desejado:
08:38fb.com/RVA.BR
107
PLAYING IN THE AIR!
Interagindo em
elementos
virtuais com a
mão.
08:38fb.com/RVA.BR
108
Definindo um conjunto de
ações
• Assunto: Controlar um Arduino 
• Ações:
• Acender e Apagar um LED via Arduino, com replicação virtual, via
botão físico e botão virtual.
• Controlar um servo motor a partir de uma barra virtual.
Dica: Esse é um bom algoritmo para fazer o debounce do toque:
http://drmarty.blogspot.com.br/2009/05/best-switch-debounce-routine-ever.html
08:38fb.com/RVA.BR
109
Espalhando controles virtuais pela
área capturada pela câmera
• 1º Projeto de Interface (livre em toda a área)
“É você Google
Glass? É voce
Hololens?”
(Clotilde, 1985)
08:38fb.com/RVA.BR
110
Tipo: ofRectangle
• Tipo que define um retângulo na tela.
• Retângulos são muito usados para definir áreas de toque.
(Forma mais simples)
• O tipo ofRectangle possui:
• X,Y,(Z) do canto superior esquerdo (Referência)
• Height, Width
• Operadores sobrecarregados
• Varias funções de posicionamento
• Adição, crescimento para englobar outros, etc etc etc.
08:38fb.com/RVA.BR
111
Some code... (testartoques?inside())
ofRectangle controleServo;
ofRectangle chaveOff;
ofRectangle chaveOn;
ofPoint LEDIndicativo;
ofColor ledColor;
bool ledStatus;
// Configurar posição dos
elementos da interface
controleServo.set(30,85,40,140);
chaveOff.set(197,160,40,40);
chaveOn.set(237,160,40,40);
LEDIndicativo.set(160,50);
if( this->controleServo.inside(dedo) ) {
// trata para controle doservo}
if( this->chaveOn.inside(dedo)) {
// trata evento do botão On}
if( this->chaveOff.inside(dedo)) {
// trata evento do botão Off}
ofApp.h ofApp.cpp – setup()
ofApp.cpp – update()
08:38fb.com/RVA.BR
112
Resultado desejado
08:38fb.com/RVA.BR
113
Adicionando comandos e
leitura do Arduino
// Setup Arduino()
ard.sendDigitalPinMode(2, ARD_INPUT); // led do exemplo
ard.sendDigitalPinMode(11, ARD_OUTPUT); // botão
ard.sendServoAttach(9); // servo
ofAddListener(ard.EDigitalPinChanged, this,
&ofApp::digitalPinChanged);
void ofApp::digitalPinChanged(const int & pinNum) {
this->ledStatus = ard.getDigital(pinNum);
if ( this->ledStatus == true){
ard.sendDigital(11,ARD_HIGH);
} else {
ard.sendDigital(11,ARD_LOW);
}
}
08:38fb.com/RVA.BR
114
bool ofApp::updateInterface(ofPoint dedo){
if( this->controleServo.inside(dedo) ) { // trata evento com servo
// |controleServo.y ----- dedo.y ---- controleServo.y + controleServo.height|
// |0 --------------------- y --------------------------- 180 |
positionServo = (int) (dedo.y - controleServo.y)*180/controleServo.height;
ard.sendServo(9, positionServo, false);
}
if( this->chaveOn.inside(dedo)) { // trata evento com botão On
ledStatus = 1;
ard.sendDigital(11,ARD_HIGH); // envia comando pro arduino
}
if( this->chaveOff.inside(dedo)) { // trata evento com botão Off
ledStatus = 0;
ard.sendDigital(11,ARD_LOW); //envia comando para o arduino
}
// pega dado do status do led
this->ledStatus == 1 ? this->ledColor = ofColor::green : this->ledColor =
ofColor::white;
return true;
}
08:38fb.com/RVA.BR
115
TRACKING PHYSICAL CONTROLS.
THINGS ARE GETING REAL
Rastreando controles
desenhados na
infraestrutura
08:38fb.com/RVA.BR
116
*Versão projetada
08:38fb.com/RVA.BR
117
Pseudo Código
• Encontrada a infraestrutura:
• Update:
1. Processar imagem
2. Procurar controles
1. Procurar tipo Slide
2. Procurar tipo Switch
3. Procurar tipo Button
3. Tendo os controles
1. Associar um controle a uma função predefinida de uma paleta de
controles
• Draw:
1. Desenhar paleta de funções num canto da infraestrutura
2. Desenhar controles encontrados (Forma e status)
1. Ajustar ponto de vista!!! (mesmo usando vista superior, em caso de
projeção é necessário corrigir, pois câmera e projetor não estão no
mesmo ponto)
08:38fb.com/RVA.BR
118
Processamento de Imagem
Infra
08:38fb.com/RVA.BR
119
Etapas do processamento
2.
Canny
3.
Dilate
4.
Erode
6. contourFinder
infra
08:38fb.com/RVA.BR
120
No “ofApp.h”
// Controles
ofxCv::ContourFindercontrolFinder;
booldoControlDetection;
// auxiliares para forçar as imagens:
cv::Mat grayImg;
cv::Mat canny;
cv::Mat eroded;
cv::Mat dilated;
cv::Mat edgesInput;
cv::Mat edges;
int BORDER;
float ALPHA;
vector<Controle> listaDeControles;
voidtoogleControlDetection() {
doControlDetection == true ? doControlDetection = false :
doControlDetection = true;
};
void encontraControles();
void processaInteracao();
void desenhaControles();
08:38fb.com/RVA.BR
121
Processamento da imagem
void ofApp::encontraControles(){
Mat img = ofxCv::toCv(this->unwarped);
// Get the image in the right format and run edge detection - cheat -
tricks
ofxCv::convertColor(img, grayImg, CV_RGB2GRAY); //converte a imagem
para cinza
cv::Canny(grayImg, edgesInput, 160, 180, 3); // extrapola as bordas
- edge map
canny = edgesInput;
cv::dilate(edgesInput, edgesInput, Mat::ones(2, 2, CV_8U),
cv::Point(-1, -1), 7); //dilata as bordas
dilated = edgesInput;
cv::erode(edgesInput, edgesInput, Mat::ones(2, 2, CV_8U),
cv::Point(-1, -1), 5); // erode as bordas
eroded = edgesInput;
const cv::Rect &roi = cv::Rect(BORDER, BORDER, edgesInput.cols -
2*BORDER, edgesInput.rows - 2*BORDER);
edgesInput(roi).copyTo(edges);
// Find contours in the edge detected image
controlFinder.findContours(edges);
//... continues
}
08:38fb.com/RVA.BR
122
Procurar Controles
08:38fb.com/RVA.BR
123
Tipos de Controles:
Switch – Posição 0 ou 1, memoriza a função
Button – Posição 0 ou 1, instantâneo, funciona
enquanto clicado, depois perde o valor
Slide - Valor variável entre um máx. e um mín.
08:38fb.com/RVA.BR
124
Identificação dos tipos de
controles
08:38fb.com/RVA.BR
125
Estrutura de dados genérica
(super-hiper-mega simplificada)
enum controlType{
CT_SWITCH,
CT_BUTTON,
CT_SLIDE
};
class Controle {
public:
int id;
controlType type;
int value;
int max;
int min;
//Para desenhar:
ofPoint pos;
ofRectangle posRect;
float radius;
float angle;
void draw(){};
//para preencher os campos
void fillSlider( cv::RotatedRect rotRect){}
void fillSwitch( cv::RotatedRect rotRect){};
void fillButton( cv::Point center, float radius){};
bool interact(ofPoint dedo);
};
Ideal é que
sejam feitas
classes e
polimorfismo
de tudo.
ofxProjAR
R_Infra*
xPAR_Actuator*
r :ofxPAR_ControlManager
xPAR_State*
r<ofxPAR_State*>
) :void
() :void
:void
ate) :bool
) :ofxPAR_State*
ofxPAR_Infra
+ cam :ofVideoGrabber
+ camHeight :int
+ camWidth :int
+ unwarped :ofImage
+ showVideoFeed :bool
+ foundInfra :bool
+ projectorPoints :vector<cv::Point2f>
+ toProjectorMatrix :cv::Mat
+ alignmentComplete :bool
+ projWidth :int
+ projHeight :int
# name :string
+ ofxPAR_Infra()
+ ~ofxPAR_Infra()
+ detect() :void
+ draw() :void
+ update() :void
+ setup() :void
+ getTransformation(int, int) :cv::Mat
+ getContours() :ofPolyline
+ unwarpPoint(ofPoint&, int, int) :ofPoint
+ getCamera() :ofVideoGrabber
+ setCamera(ofVideoGrabber) :void
+ setCamera(int, int) :void
+ getRawUnwarped() :ofImage
+ toogleVideoFeed() :void
+ isInfraFound() :bool
+ addCalibrationPoints(int, int) :void
+ resetCalibration() :void
+ doCalibration() :void
+ drawProjectionLimits() :void
# computeProjectorAlignment() :void
# loadProjectorAlignment() :bool
# saveProjectorAlignment() :bool
# resetProjectorAlignment() :void
ofxPAR_Infra_PaperDetector
# trackingColorMode :ofxCv::TrackingColorMode
# contourFinder :ofxCv::ContourFinder
# targetColor :ofColor
# thresholdCV :int
# contour :ofPolyline
# paperImage :cv::Mat
# paper :vector<cv::Point>
# adaptedToScreenSize :vector<cv::Point>
+ ofxPAR_Infra_PaperDetector()
+ ~ofxPAR_Infra_PaperDetector()
+ draw() :void
+ detect() :void
+ calibrate() :void
+ update() :void
+ setup() :void
xPAR_ControlManager
etection :bool
Color {readOnly}
Color {readOnly}
Cv::ContourFinder
v::Mat
Mat
:Mat
:Mat
:cv::Mat
Mat
:vector<ofxPAR_Control *>
int :ofPoint
nt
at
ntrolManager()
ontrolManager()
d
d
orInput(float, float, float, float) :void
:void
Mat) :void
rolDetection() :void
raction(ofPoint&) :void
ls() :void
() :void
ols() :void
e_t) :bool
e_t) :bool
e_t) :bool
ofxPAR_Control
# id :int
# name :string
# value :int
# color :ofColor
# controlType :ControlType
# selected :bool
+ ofxPAR_Control()
+ ~ofxPAR_Control()
+ setId(int) :void
+ draw() :void
+ setColor(ofColor&) :void
+ contains(float, float) :bool
+ contains(ofPoint&) :bool
+ onInteraction(float, float) :bool
+ onInteraction(ofPoint&) :bool
+ setSelection(bool) :void
+ isSelected() :bool
+ getValue() :int
ofxPAR_C_Button
- cx :float
- cy :float
- radius :float
- active :bool
- entered :bool
+ ofxPAR_C_Button()
+ ~ofxPAR_C_Button()
+ ofxPAR_C_Button(float, float, float)
+ draw() :void
+ contains(float, float) :bool
+ onInteraction(float, float) :bool
+ operator==(ofxPAR_C_Button&) :bool
+ operator!=(ofxPAR_C_Button&) :bool
ofxPAR_C_Slider
- value :float
+ ofxPAR_C_Slider()
+ ~ofxPAR_C_Slider()
+ ofxPAR_C_Slider(cv::RotatedRect&)
+ draw() :void
+ onInteraction(float, float) :bool
ofxPAR_C_Switch
- active :bool
+ ofxPAR_C_Switch()
+ ~ofxPAR_C_Switch()
+ ofxPAR_C_Switch(cv::RotatedRect&)
+ draw() :void
+ onInteraction(float, float) :bool
ofxPAR_State
stateType :AppState
name :string
app :ofxProjAR*
ofxPAR_State()
~ofxPAR_State()
draw() :void
update() :void
InfraSetup ofxPAR_State_Play
ofxPAR_Control_Rectangular
# angle :float
# rect :ofRectangle
+ ofxPAR_Control_Rectangular()
+ ~ofxPAR_Control_Rectangular()
+ ofxPAR_Control_Rectangular(cv::RotatedRect&)
+ draw() :void
+ contains(float, float) :bool
+ operator==(ofxPAR_Control_Rectangular&) :bool
+ operator!=(ofxPAR_Control_Rectangular&) :bool
# alignPoint(float, float) :ofVec2f
app
08:38fb.com/RVA.BR
126
Tipo: vector (de classes)
• Vector é uma estrutura para armazenar sequencialmente.
• No C++ vários tipos de estruturas de dados foram definidas usando
containers genéricos. (STL)
vector<Controle> listaDeControles;
• Adição:
Controle a;
listaDeControles.push_back(a);
• Remoção:
listaDeControles.erase( listaDeControles.begin() + x);
• Percorrer:
vector<Controle>::iterator it = listaDeControles.begin();
for(; it != listaDeControles.end(); it++){
it->id; } // se vetor de ponteiros (*it)->
http://www.openframeworks.cc/tutorials/c++%20concepts/001_stl_vectors_basic.html
vector<Controle*> listaDeControles;
08:38fb.com/RVA.BR
127
//... Continuing - void ofApp::encontraControles()
listaDeControles.clear();
int n = controlFinder.size();
for(int i = 0; i< n; i++){
if (isButton(i)) {
float radius;
cv::Point center = controlFinder.getMinEnclosingCircle(i, radius);
Controle *b = new Controle(); b->id = i;
b->fillButton(center, radius);
listaDeControles.push_back(b);
} else if (isSlider(i)) {
cv::RotatedRect rect = controlFinder.getMinAreaRect(i);
Controle *s = new Controle(); s->id = i;
s->fillSlider(rect);
listaDeControles.push_back(s);
} else if (isSwitch(i)) {
cv::RotatedRect rect = controlFinder.getMinAreaRect(i);
Controle *s = new Controle(); s->id = 1;
s->fillSwitch(rect);
listaDeControles.push_back(s);
}
}
}
08:38fb.com/RVA.BR
128
//---------------------------------------------------------
bool ofApp::isButton(int i) {
float radius;
controlFinder.getMinEnclosingCircle(i, radius);
float circleArea = PI * radius * radius;
double contourArea = controlFinder.getContourArea(i);
return abs(1.0 - circleArea / contourArea) < 0.3;
}
//---------------------------------------------------------
bool ofApp::isSlider(int i) {
float radius;
ofVec2f center = ofxCv::toOf(controlFinder.getMinEnclosingCircle(i, radius));
float circleArea = PI * radius * radius;
double contourArea = controlFinder.getContourArea(i);
return circleArea / contourArea > 12;
}
//---------------------------------------------------------
bool ofApp::isSwitch(int i) {
RotatedRect rr = controlFinder.getMinAreaRect(i);
float rectArea = rr.size.width * rr.size.height;
double contourArea = controlFinder.getContourArea(i);
return abs(1.0 - rectArea / contourArea) < 0.25
&& abs(1.0 - (float) rr.size.width / rr.size.height) > 0.1;
}
08:38fb.com/RVA.BR
129
Criaroscontroles-FYI
void fillSlider( cv::RotatedRect rotRect){
this->type = controlType::CT_SLIDE;
const cv::Size &s = rotRect.size;
bool switchHeight = s.width < s.height;
if (switchHeight) {
this->posRect.setFromCenter(ofxCv::toOf(rotRect.center), s.height, s.width);
angle = rotRect.angle + 90;
} else {
this->posRect.setFromCenter(ofxCv::toOf(rotRect.center), s.width, s.height);
angle = rotRect.angle; }
this->value = 0;
};
void fillSwitch( cv::RotatedRect rotRect){
this->type = controlType::CT_SWITCH;
const cv::Size &s = rotRect.size;
bool switchHeight = s.width < s.height;
if (switchHeight) {
this->posRect.setFromCenter(ofxCv::toOf(rotRect.center), s.height, s.width);
angle = rotRect.angle + 90;
} else {
this->posRect.setFromCenter(ofxCv::toOf(rotRect.center), s.width, s.height);
angle = rotRect.angle;
}
this->value = 0;
};
void fillButton( cv::Point center, float radius){
this->type = controlType::CT_BUTTON;
this->pos.x = center.x; this->pos.y = center.y; this->radius = radius;
this->value = 0;
};
08:38fb.com/RVA.BR
130
Draw do botão:
case controlType::CT_BUTTON :{
ofPushMatrix();
ofSetColor(ofColor::green);
ofSetLineWidth(5);
if (this->value == 1) {
ofFill();
} else {
ofNoFill();
}
ofCircle(this->pos, this->radius);
ofPopMatrix();
break;}
08:38fb.com/RVA.BR
131
case controlType::CT_SWITCH:{
ofPushMatrix();
ofTranslate(this->posRect.getCenter());
ofRotate(this->angle);
ofNoFill();
ofSetLineWidth(3);
ofSetColor(ofColor::blue);
ofRect(-this->posRect.width / 2, -this->posRect.height / 2, this-
>posRect.width, this->posRect.height);
ofLine(0, -this->posRect.height / 2, 0, this->posRect.height / 2);
float x = (this->value ? 0 : -this->posRect.width / 2);
ofLine(x, -this->posRect.height / 2, x + this->posRect.width / 2, this-
>posRect.height / 2);
ofLine(x + this->posRect.width / 2, -this->posRect.height / 2, x, this-
>posRect.height / 2);
ofPopMatrix();
break;}
Draw da Chave:
08:38fb.com/RVA.BR
132
case controlType::CT_SLIDE:{
ofPushMatrix();
ofTranslate(this->posRect.getCenter());
ofRotate(this->angle);
ofNoFill();
ofSetLineWidth(4);
ofSetColor(ofColor::red);
// Draw the main shape
ofLine(-this->posRect.width / 2, 0, this->posRect.width / 2, 0);
ofLine(-this->posRect.width / 2, -this->posRect.height / 2, -this->posRect.width / 2, this->posRect.height /
2);
ofLine(this->posRect.width / 2, -this->posRect.height / 2, this->posRect.width / 2, this->posRect.height /
2);
// Draw the tick marks
ofSetLineWidth(2);
for (size_t i = 1; i < 8; i++) {
float dx = ((float) i / 8) * this->posRect.width;
ofLine(-this->posRect.width / 2 + dx, -this->posRect.height / 3, -this->posRect.width / 2 + dx, this-
>posRect.height / 3);
}
// Draw the value marker
float xval = ((float)this->value/100) * this->posRect.width;
float knobHeight = 5 * this->posRect.height / 4;
float knobWidth = this->posRect.width / 8;
// Fill the rectangle with black to erase the background
ofPushStyle();
ofSetColor(0);
ofFill();
ofRect(-this->posRect.width / 2 + xval - knobWidth / 2, -knobHeight / 2, knobWidth, knobHeight);
ofPopStyle();
ofSetLineWidth(5);
ofRect(-this->posRect.width / 2 + xval - knobWidth / 2, -knobHeight / 2, knobWidth, knobHeight);
ofPopMatrix();
break;}
Draw do Slider
08:38fb.com/RVA.BR
133
FINAL LAP: INTERAÇÃO COM OS
CONTROLES
08:38fb.com/RVA.BR
134
Fixar os pontos de corte da
figura!!!!!!!!!!!!!!
08:38fb.com/RVA.BR
135
Inside!?
bool buttonContains(int x, int y){
return ofDistSquared((float)pos.x, (float)pos.y,
(float)x, (float)y) < radius * radius;
}
bool rectContains(int x, int y){
return posRect.inside(x, y);
}
08:38fb.com/RVA.BR
136
switch(type){
case controlType::CT_BUTTON :
if (buttonContains(dedo.x, dedo.y)) {
value == 1 ? value = 0 : value = 1;
return true; }
break;
case controlType::CT_SWITCH :
if(rectContains(dedo.x,dedo.y)) {
bool right = dedo.x > posRect.getCenter().x;
if ((bool)value != right) value = right;
return true;}
break;
case controlType::CT_SLIDE :
if(rectContains(dedo.x,dedo.y)){
value = (int) ((dedo.x - posRect.x)*100 / posRect.width);
return true;}
break;
default: break;
};
interaction
08:38fb.com/RVA.BR
137
Resultado Esperado
08:38fb.com/RVA.BR
138
WRAP-UP
08:38fb.com/RVA.BR
139
O QUE APRENDEMOS HOJE
O QUE
ACONTECEU:
class src
«enumeratio...
controlType
CT_SWITCH
CT_BUTTON
CT_SLIDE
Controle
+ id :int
+ type :controlType
+ value :int
+ max :int
+ min :int
+ pos :ofPoint
+ posRect :ofRectangle
+ radius :float
+ angle :float
+ fillSlider(rotRect :cv::RotatedRect) :void
+ fillSwitch(rotRect :cv::RotatedRect) :void
+ fillButton(center :cv::Point, radius :float) :void
+ draw() :void
+ buttonContains(x :int, y :int) :bool
+ rectContains(x :int, y :int) :bool
+ interact(dedo :ofPoint) :bool
ofBaseApp
ofApp
+ debugApp :bool
+ cam :ofVideoGrabber
+ camHeight :int
+ camWidth :int
+ original :ofImage
+ paperFinder :ofxCv::ContourFinder
+ warpedPaper :ofImage
+ verticesInfra :vector<Point2f>
+ foundInfra :bool
+ StopToGetInfraPosition :bool
+ controlFinder :ofxCv::ContourFinder
+ doControlDetection :bool
+ grayImg :cv::Mat
+ canny :cv::Mat
+ eroded :cv::Mat
+ dilated :cv::Mat
+ edgesInput :cv::Mat
+ edges :cv::Mat
+ BORDER :int
+ ALPHA :float
+ listaDeControles :vector<Controle*>
+ colorImage :ofxCvColorImage
+ grayBg :ofxCvGrayscaleImage
+ grayImage :ofxCvGrayscaleImage
+ grayDiff :ofxCvGrayscaleImage
+ bLearnBackground :bool
+ trackingColorMode :ofxCv::TrackingColorMode
+ handFinder :ofxCv::ContourFinder
+ targetColor :ofColor
+ apontador :ofPoint
+ setup() :void
+ update() :void
+ draw() :void
+ keyReleased(key :int) :void
+ trataInfraestrutura() :void
+ desenhaInfraestrutura(x :int, y :int) :void
+ encontraControles(source :ofImage) :void
+ isButton(i :int) :bool
+ isSwitch(i :int) :bool
+ isSlider(i :int) :bool
+ desenhaControles(x :int, y :int) :void
+ processaInteracao() :void
+ encontraPontoMaisDistante() :ofPoint
+ desenhaMao(x :int, y :int) :void
+ encontraMao(source :ofImage) :void
+ findForm(poly :ofPolyline&) :string
+ findForm(poly :T&) :string
+type
08:38fb.com/RVA.BR
140
class Class Model
ofBaseApp
ofApp
+ par :ofxProjAR
+ setup() :void
+ update() :void
+ draw() :void
+ keyPressed(int) :void
+ keyReleased(int) :void
+ mouseMoved(int, int) :void
+ mouseDragged(int, int, int) :void
+ mousePressed(int, int, int) :void
+ mouseReleased(int, int, int) :void
+ windowResized(int, int) :void
+ dragEvent(ofDragInfo) :void
+ gotMessage(ofMessage) :void
ofxProjAR
+ m_infra :ofxPAR_Infra*
+ m_actuator :ofxPAR_Actuator*
+ controlManager :ofxPAR_ControlManager
+ debug :bool
- actualState :ofxPAR_State*
- stateList :vector<ofxPAR_State*>
+ ofxProjAR()
+ ~ofxProjAR()
+ standardSetup() :void
+ standardUpdate() :void
+ standardDraw() :void
+ setState(AppState) :bool
+ getActualState() :ofxPAR_State*
ofxPAR_Infra
+ cam :ofVideoGrabber
+ camHeight :int
+ camWidth :int
+ unwarped :ofImage
+ showVideoFeed :bool
+ foundInfra :bool
+ projectorPoints :vector<cv::Point2f>
+ toProjectorMatrix :cv::Mat
+ alignmentComplete :bool
+ projWidth :int
+ projHeight :int
# name :string
+ ofxPAR_Infra()
+ ~ofxPAR_Infra()
+ detect() :void
+ draw() :void
+ update() :void
+ setup() :void
+ getTransformation(int, int) :cv::Mat
+ getContours() :ofPolyline
+ unwarpPoint(ofPoint&, int, int) :ofPoint
+ getCamera() :ofVideoGrabber
+ setCamera(ofVideoGrabber) :void
+ setCamera(int, int) :void
+ getRawUnwarped() :ofImage
+ toogleVideoFeed() :void
+ isInfraFound() :bool
+ addCalibrationPoints(int, int) :void
+ resetCalibration() :void
+ doCalibration() :void
+ drawProjectionLimits() :void
# computeProjectorAlignment() :void
# loadProjectorAlignment() :bool
# saveProjectorAlignment() :bool
# resetProjectorAlignment() :void
ofxPAR_Infra_PaperDetector
# trackingColorMode :ofxCv::TrackingColorMode
# contourFinder :ofxCv::ContourFinder
# targetColor :ofColor
# thresholdCV :int
# contour :ofPolyline
# paperImage :cv::Mat
# paper :vector<cv::Point>
# adaptedToScreenSize :vector<cv::Point>
+ ofxPAR_Infra_PaperDetector()
+ ~ofxPAR_Infra_PaperDetector()
+ draw() :void
+ detect() :void
+ calibrate() :void
+ update() :void
+ setup() :void
+ getTransformation(int, int) :cv::Mat
+ getContours() :ofPolyline
+ unwarpPoint(ofPoint&, int, int) :ofPoint
- configureCV() :void
- drawPaperContour() :void
- drawPaperContourIn(int, int) :void
- unwarp(S&, D&) :void
- unwarp(D&) :void
- unwarpPointIntern(ofPoint&, int, int) :ofPoint
ofxPAR_Actuator
+ topBackground :ofxCv::RunningBackground
+ foreground :cv::Mat
+ ofxPAR_Actuator()
+ ~ofxPAR_Actuator()
+ draw() :void
+ drawDetectorInput(float, float, float, float) :void
+ detect(T&, S&, ofPolyline&) :bool
+ detect(cv::Mat&, ofPolyline&) :bool
+ getActuatorPoint() :ofPoint
+ setActuatorThresold(int) :void
ofxPAR_HandDetector
- topFinder :ofxCv::ContourFinder
- sideFinder :ofxCv::ContourFinder
- topFilled :cv::Mat
- contour :ofPolyline
- fingers :vector<size_t>
- fingerPoint :ofPoint
- foundFingerInLast :bool
- fingerThreshold :int
- fAlpha :float
- elem2x2 :cv::Mat
- elem3x3 :cv::Mat
- useCenter :cv::Point {readOnly}
+ ofxPAR_HandDetector()
+ ~ofxPAR_HandDetector()
+ draw() :void
+ drawDetectorInput(float, float, float, float) :void
+ detect(cv::Mat&, ofPolyline&) :bool
+ getActuatorPoint() :ofPoint
+ setActuatorThresold(int) :void
- findFingers(ofPolyline&) :bool
- getFingerPoint() :ofPoint
ofxPAR_ControlManager
+ doControlDetection :bool
+ accent1 :ofColor {readOnly}
+ accent2 :ofColor {readOnly}
+ finder :ofxCv::ContourFinder
+ grayImg :cv::Mat
+ canny :cv::Mat
+ eroded :cv::Mat
+ dilated :cv::Mat
+ edgesInput :cv::Mat
+ edges :cv::Mat
+ controlList :vector<ofxPAR_Control *>
+ lastInputPoint :ofPoint
+ BORDER :int
+ ALPHA :float
+ ofxPAR_ControlManager()
+ ~ofxPAR_ControlManager()
+ setup() :void
+ reset() :void
+ drawDetectorInput(float, float, float, float) :void
+ detect(T&) :void
+ detect(cv::Mat) :void
+ toogleControlDetection() :void
+ processInteraction(ofPoint&) :void
+ drawControls() :void
+ drawDebug() :void
+ assignControls() :void
+ isButton(size_t) :bool
+ isSlider(size_t) :bool
+ isSwitch(size_t) :bool
ofxPAR_Control
# id :int
# name :string
# value :int
# color :ofColor
# controlType :ControlType
# selected :bool
+ ofxPAR_Control()
+ ~ofxPAR_Control()
+ setId(int) :void
+ draw() :void
+ setColor(ofColor&) :void
+ contains(float, float) :bool
+ contains(ofPoint&) :bool
+ onInteraction(float, float) :bool
+ onInteraction(ofPoint&) :bool
+ setSelection(bool) :void
+ isSelected() :bool
+ getValue() :int
ofxPAR_C_Button
- cx :float
- cy :float
- radius :float
- active :bool
- entered :bool
+ ofxPAR_C_Button()
+ ~ofxPAR_C_Button()
+ ofxPAR_C_Button(float, float, float)
+ draw() :void
+ contains(float, float) :bool
+ onInteraction(float, float) :bool
+ operator==(ofxPAR_C_Button&) :bool
+ operator!=(ofxPAR_C_Button&) :bool
ofxPAR_C_Slider
- value :float
+ ofxPAR_C_Slider()
+ ~ofxPAR_C_Slider()
+ ofxPAR_C_Slider(cv::RotatedRect&)
+ draw() :void
+ onInteraction(float, float) :bool
ofxPAR_C_Switch
- active :bool
+ ofxPAR_C_Switch()
+ ~ofxPAR_C_Switch()
+ ofxPAR_C_Switch(cv::RotatedRect&)
+ draw() :void
+ onInteraction(float, float) :bool
ofxPAR_State
+ stateType :AppState
+ name :string
+ app :ofxProjAR*
+ ofxPAR_State()
+ ~ofxPAR_State()
+ draw() :void
+ update() :void
ofxPAR_State_Idle
+ ofxPAR_State_Idle()
+ ~ofxPAR_State_Idle()
+ draw() :void
+ update() :void
ofxPAR_State_InfraSetup
+ ofxPAR_State_InfraSetup()
+ ~ofxPAR_State_InfraSetup()
+ draw() :void
+ update() :void
ofxPAR_State_Play
+ ofxPAR_State_Play()
+ ~ofxPAR_State_Play()
+ draw() :void
+ update() :void
- reprojectPaper() :void
ofxPAR_Control_Rectangular
# angle :float
# rect :ofRectangle
+ ofxPAR_Control_Rectangular()
+ ~ofxPAR_Control_Rectangular()
+ ofxPAR_Control_Rectangular(cv::RotatedRect&)
+ draw() :void
+ contains(float, float) :bool
+ operator==(ofxPAR_Control_Rectangular&) :bool
+ operator!=(ofxPAR_Control_Rectangular&) :bool
# alignPoint(float, float) :ofVec2f
+app
IDEAL:
08:38fb.com/RVA.BR
141
• Existe um framework em C++ chamado
openFrameworks. Novo player interessante: Unreal
Engine + Blueprints (AWESOME)
• openFrameworks pode ser expandido com
componentes da comunidade, chamados addons.
• Com ele é possível controlar o Arduino (em C++).
• O Arduino pode se transformar numa interface de
dados usando a lib Firmata.
• Arduino é barato e fácil de usar. Um possível
software para desenhar circuitos é o Fritzing
•Realidade Aumentada é só uma
interface de acesso aos elementos virtuais.
08:38fb.com/RVA.BR
142
• openCV é uma biblioteca de visão computacional.
• Com openCV podemos rastrear cores, diferenças de
imagens, etc.
• Pense se sua aplicação pode usar equipamentos
simples!
• Quanto mais simples e do cotidiano do usuário
melhor.
• Visão computacional nem sempre é um resultado por si.
Ideal são soluções hibridas.
• Adicionando elementos de interação físicos (sensores e
atuadores) à Realidade Aumentada, que fazem a troca
bidirecional de informação cria-se Realidade Cruzada.
08:38fb.com/RVA.BR
143
08:38fb.com/RVA.BR
144
Motivador
Pesquisa
Dúvidas: christophercerqueira@gmail.com
Site: http://cscerqueira.com.br
Facebook: http://fb.com/RVA.BR
Para maiores dúvidas:
INPE – SJC
Prédio Satélite
Sala 95
Drª. Ana Maria
Ambrosio
Msc. Christopher
Cerqueira
aluno
doutorado
Dr. Claudio Kirner
08:38fb.com/RVA.BR
145

Mais conteúdo relacionado

Mais procurados

Do zero ao jogo multiplataforma com cocos2d
Do zero ao jogo multiplataforma com cocos2dDo zero ao jogo multiplataforma com cocos2d
Do zero ao jogo multiplataforma com cocos2dVitor Mattos
 
TDC2015 - Internet das Coisas - OpenDevice
TDC2015 - Internet das Coisas - OpenDeviceTDC2015 - Internet das Coisas - OpenDevice
TDC2015 - Internet das Coisas - OpenDeviceRicardo Rufino
 
Internet das Coisas com Android things e Machine Learning
Internet das Coisas com Android things e Machine LearningInternet das Coisas com Android things e Machine Learning
Internet das Coisas com Android things e Machine LearningAlvaro Viebrantz
 
Desenvolvimento de Jogos com Cocos2d - Apresentação Coderockr Jam
Desenvolvimento de Jogos com Cocos2d - Apresentação Coderockr JamDesenvolvimento de Jogos com Cocos2d - Apresentação Coderockr Jam
Desenvolvimento de Jogos com Cocos2d - Apresentação Coderockr JamAndré Espeiorin
 
Android: Conheça o Futuro Inevitável
Android: Conheça o Futuro InevitávelAndroid: Conheça o Futuro Inevitável
Android: Conheça o Futuro InevitávelCampus Party Brasil
 
Android things, machine learning e maquinas de doces
Android things, machine learning e maquinas de doces Android things, machine learning e maquinas de doces
Android things, machine learning e maquinas de doces Alvaro Viebrantz
 
ArduinoDay 2015 - OpenDevice
ArduinoDay 2015 -  OpenDeviceArduinoDay 2015 -  OpenDevice
ArduinoDay 2015 - OpenDeviceRicardo Rufino
 
Multirão Python - introdução ao py serial com gtk3 e arduino
Multirão Python - introdução ao py serial com gtk3 e arduinoMultirão Python - introdução ao py serial com gtk3 e arduino
Multirão Python - introdução ao py serial com gtk3 e arduinoAntonio Thomacelli
 
Desenvolvendo Aplicativos para o Kinect
Desenvolvendo Aplicativos para o KinectDesenvolvendo Aplicativos para o Kinect
Desenvolvendo Aplicativos para o KinectBruno Campagnolo
 

Mais procurados (11)

Do zero ao jogo multiplataforma com cocos2d
Do zero ao jogo multiplataforma com cocos2dDo zero ao jogo multiplataforma com cocos2d
Do zero ao jogo multiplataforma com cocos2d
 
TDC2015 - Internet das Coisas - OpenDevice
TDC2015 - Internet das Coisas - OpenDeviceTDC2015 - Internet das Coisas - OpenDevice
TDC2015 - Internet das Coisas - OpenDevice
 
Apresentacao KINECT
Apresentacao KINECTApresentacao KINECT
Apresentacao KINECT
 
Internet das Coisas com Android things e Machine Learning
Internet das Coisas com Android things e Machine LearningInternet das Coisas com Android things e Machine Learning
Internet das Coisas com Android things e Machine Learning
 
Desenvolvimento de Jogos com Cocos2d - Apresentação Coderockr Jam
Desenvolvimento de Jogos com Cocos2d - Apresentação Coderockr JamDesenvolvimento de Jogos com Cocos2d - Apresentação Coderockr Jam
Desenvolvimento de Jogos com Cocos2d - Apresentação Coderockr Jam
 
Android: Conheça o Futuro Inevitável
Android: Conheça o Futuro InevitávelAndroid: Conheça o Futuro Inevitável
Android: Conheça o Futuro Inevitável
 
Android things, machine learning e maquinas de doces
Android things, machine learning e maquinas de doces Android things, machine learning e maquinas de doces
Android things, machine learning e maquinas de doces
 
Realidade Aumentada
Realidade AumentadaRealidade Aumentada
Realidade Aumentada
 
ArduinoDay 2015 - OpenDevice
ArduinoDay 2015 -  OpenDeviceArduinoDay 2015 -  OpenDevice
ArduinoDay 2015 - OpenDevice
 
Multirão Python - introdução ao py serial com gtk3 e arduino
Multirão Python - introdução ao py serial com gtk3 e arduinoMultirão Python - introdução ao py serial com gtk3 e arduino
Multirão Python - introdução ao py serial com gtk3 e arduino
 
Desenvolvendo Aplicativos para o Kinect
Desenvolvendo Aplicativos para o KinectDesenvolvendo Aplicativos para o Kinect
Desenvolvendo Aplicativos para o Kinect
 

Semelhante a Construção de interfaces on-demand baseadas em Realidade Aumentada Projetiva para Controle de Hardware (Arduino)

Netduino e .NET Micro Framework
Netduino e .NET Micro FrameworkNetduino e .NET Micro Framework
Netduino e .NET Micro FrameworkIgor Kondrasovas
 
Introdução à utilização de openFrameworks para o desenvolvimento de aplicaçõ...
Introdução à utilização de openFrameworks para  o desenvolvimento de aplicaçõ...Introdução à utilização de openFrameworks para  o desenvolvimento de aplicaçõ...
Introdução à utilização de openFrameworks para o desenvolvimento de aplicaçõ...Christopher Cerqueira
 
OpenDevice IoT - 2016 (LowLevel)
OpenDevice IoT - 2016 (LowLevel)OpenDevice IoT - 2016 (LowLevel)
OpenDevice IoT - 2016 (LowLevel)Ricardo Rufino
 
Node.js - Programação assíncrona e de tempo real
Node.js - Programação assíncrona e de tempo realNode.js - Programação assíncrona e de tempo real
Node.js - Programação assíncrona e de tempo realDiogo Cabral da Silva
 
Demonstrador virtual web com recursos de Realidade Aumentada - Apresentação
Demonstrador virtual web com recursos de Realidade Aumentada - ApresentaçãoDemonstrador virtual web com recursos de Realidade Aumentada - Apresentação
Demonstrador virtual web com recursos de Realidade Aumentada - ApresentaçãoLeonardo Pereira Santos
 
Um Ambiente Grafico para Desenvolvimento de Software de Controle para Robos M...
Um Ambiente Grafico para Desenvolvimento de Software de Controle para Robos M...Um Ambiente Grafico para Desenvolvimento de Software de Controle para Robos M...
Um Ambiente Grafico para Desenvolvimento de Software de Controle para Robos M...Humberto Marchezi
 
Programação de Microcontroladores com .NET Micro Framework
Programação de Microcontroladores com .NET Micro FrameworkProgramação de Microcontroladores com .NET Micro Framework
Programação de Microcontroladores com .NET Micro FrameworkIgor Kondrasovas
 
Conhecendo a Plataforma .NET
Conhecendo a Plataforma .NETConhecendo a Plataforma .NET
Conhecendo a Plataforma .NETPedro Alves Jr.
 
JustJava 2013: Aplicações Desktop HTML5, CSS3, Javascript com Servlets 3
JustJava 2013: Aplicações Desktop HTML5, CSS3, Javascript com Servlets 3JustJava 2013: Aplicações Desktop HTML5, CSS3, Javascript com Servlets 3
JustJava 2013: Aplicações Desktop HTML5, CSS3, Javascript com Servlets 3Loiane Groner
 
Gerenciador do atmega16
Gerenciador do atmega16Gerenciador do atmega16
Gerenciador do atmega16Gabriel Lima
 
Como utilizar a Qualcomm DragonBoard 410c em seus projetos IoT
Como utilizar a Qualcomm DragonBoard 410c em seus projetos IoTComo utilizar a Qualcomm DragonBoard 410c em seus projetos IoT
Como utilizar a Qualcomm DragonBoard 410c em seus projetos IoTFrederico Martins Pedroso Junior
 
ASP.NET vNext no MAC OS
ASP.NET vNext no MAC OSASP.NET vNext no MAC OS
ASP.NET vNext no MAC OSJorge Maia
 
RedGate .NET Reflector
RedGate .NET ReflectorRedGate .NET Reflector
RedGate .NET ReflectorNuno Gomes
 
A Internet das coisas e a programação de micro controladores
A Internet das coisas e a programação de micro controladoresA Internet das coisas e a programação de micro controladores
A Internet das coisas e a programação de micro controladoresIgor Kondrasovas
 
Realidade aumentada.pptx
Realidade aumentada.pptxRealidade aumentada.pptx
Realidade aumentada.pptxArthur Felipe
 
Construção de aplicações de Realidade Cruzada Projetiva utilizando openFramew...
Construção de aplicações de Realidade Cruzada Projetiva utilizando openFramew...Construção de aplicações de Realidade Cruzada Projetiva utilizando openFramew...
Construção de aplicações de Realidade Cruzada Projetiva utilizando openFramew...Christopher Cerqueira
 
Minicurso - Desenvolvendo aplicações web com JavaScript e AngularJS - Estácio...
Minicurso - Desenvolvendo aplicações web com JavaScript e AngularJS - Estácio...Minicurso - Desenvolvendo aplicações web com JavaScript e AngularJS - Estácio...
Minicurso - Desenvolvendo aplicações web com JavaScript e AngularJS - Estácio...Rodrigo Branas
 

Semelhante a Construção de interfaces on-demand baseadas em Realidade Aumentada Projetiva para Controle de Hardware (Arduino) (20)

Palestra realidade aumentada
Palestra   realidade aumentadaPalestra   realidade aumentada
Palestra realidade aumentada
 
Netduino e .NET Micro Framework
Netduino e .NET Micro FrameworkNetduino e .NET Micro Framework
Netduino e .NET Micro Framework
 
OpenKinect, o Kinect para todos
OpenKinect, o Kinect para todosOpenKinect, o Kinect para todos
OpenKinect, o Kinect para todos
 
Introdução à utilização de openFrameworks para o desenvolvimento de aplicaçõ...
Introdução à utilização de openFrameworks para  o desenvolvimento de aplicaçõ...Introdução à utilização de openFrameworks para  o desenvolvimento de aplicaçõ...
Introdução à utilização de openFrameworks para o desenvolvimento de aplicaçõ...
 
OpenDevice IoT - 2016 (LowLevel)
OpenDevice IoT - 2016 (LowLevel)OpenDevice IoT - 2016 (LowLevel)
OpenDevice IoT - 2016 (LowLevel)
 
Node.js - Programação assíncrona e de tempo real
Node.js - Programação assíncrona e de tempo realNode.js - Programação assíncrona e de tempo real
Node.js - Programação assíncrona e de tempo real
 
Demonstrador virtual web com recursos de Realidade Aumentada - Apresentação
Demonstrador virtual web com recursos de Realidade Aumentada - ApresentaçãoDemonstrador virtual web com recursos de Realidade Aumentada - Apresentação
Demonstrador virtual web com recursos de Realidade Aumentada - Apresentação
 
CGPI Aula 27/08/2018
CGPI Aula 27/08/2018CGPI Aula 27/08/2018
CGPI Aula 27/08/2018
 
Um Ambiente Grafico para Desenvolvimento de Software de Controle para Robos M...
Um Ambiente Grafico para Desenvolvimento de Software de Controle para Robos M...Um Ambiente Grafico para Desenvolvimento de Software de Controle para Robos M...
Um Ambiente Grafico para Desenvolvimento de Software de Controle para Robos M...
 
Programação de Microcontroladores com .NET Micro Framework
Programação de Microcontroladores com .NET Micro FrameworkProgramação de Microcontroladores com .NET Micro Framework
Programação de Microcontroladores com .NET Micro Framework
 
Conhecendo a Plataforma .NET
Conhecendo a Plataforma .NETConhecendo a Plataforma .NET
Conhecendo a Plataforma .NET
 
JustJava 2013: Aplicações Desktop HTML5, CSS3, Javascript com Servlets 3
JustJava 2013: Aplicações Desktop HTML5, CSS3, Javascript com Servlets 3JustJava 2013: Aplicações Desktop HTML5, CSS3, Javascript com Servlets 3
JustJava 2013: Aplicações Desktop HTML5, CSS3, Javascript com Servlets 3
 
Gerenciador do atmega16
Gerenciador do atmega16Gerenciador do atmega16
Gerenciador do atmega16
 
Como utilizar a Qualcomm DragonBoard 410c em seus projetos IoT
Como utilizar a Qualcomm DragonBoard 410c em seus projetos IoTComo utilizar a Qualcomm DragonBoard 410c em seus projetos IoT
Como utilizar a Qualcomm DragonBoard 410c em seus projetos IoT
 
ASP.NET vNext no MAC OS
ASP.NET vNext no MAC OSASP.NET vNext no MAC OS
ASP.NET vNext no MAC OS
 
RedGate .NET Reflector
RedGate .NET ReflectorRedGate .NET Reflector
RedGate .NET Reflector
 
A Internet das coisas e a programação de micro controladores
A Internet das coisas e a programação de micro controladoresA Internet das coisas e a programação de micro controladores
A Internet das coisas e a programação de micro controladores
 
Realidade aumentada.pptx
Realidade aumentada.pptxRealidade aumentada.pptx
Realidade aumentada.pptx
 
Construção de aplicações de Realidade Cruzada Projetiva utilizando openFramew...
Construção de aplicações de Realidade Cruzada Projetiva utilizando openFramew...Construção de aplicações de Realidade Cruzada Projetiva utilizando openFramew...
Construção de aplicações de Realidade Cruzada Projetiva utilizando openFramew...
 
Minicurso - Desenvolvendo aplicações web com JavaScript e AngularJS - Estácio...
Minicurso - Desenvolvendo aplicações web com JavaScript e AngularJS - Estácio...Minicurso - Desenvolvendo aplicações web com JavaScript e AngularJS - Estácio...
Minicurso - Desenvolvendo aplicações web com JavaScript e AngularJS - Estácio...
 

Mais de Christopher Cerqueira

MICRO SATÉLITES BRASILEIROS, ELES EXISTEM?
MICRO SATÉLITES BRASILEIROS, ELES EXISTEM?MICRO SATÉLITES BRASILEIROS, ELES EXISTEM?
MICRO SATÉLITES BRASILEIROS, ELES EXISTEM?Christopher Cerqueira
 
Jornada Espacial 2018 - Cubesats: o que são e pra que servem
Jornada Espacial 2018 - Cubesats: o que são e pra que servemJornada Espacial 2018 - Cubesats: o que são e pra que servem
Jornada Espacial 2018 - Cubesats: o que são e pra que servemChristopher Cerqueira
 
[Thesis] Tangible Collaboration applied in Space Systems Concurrent Engineeri...
[Thesis] Tangible Collaboration applied in Space Systems Concurrent Engineeri...[Thesis] Tangible Collaboration applied in Space Systems Concurrent Engineeri...
[Thesis] Tangible Collaboration applied in Space Systems Concurrent Engineeri...Christopher Cerqueira
 
Using Finite State Machines From Concept to Realization
Using Finite State Machines From Concept to RealizationUsing Finite State Machines From Concept to Realization
Using Finite State Machines From Concept to RealizationChristopher Cerqueira
 
A Model Based Concurrent Engineering Framework using ISO-19450 Standard
A Model Based Concurrent Engineering Framework using ISO-19450 StandardA Model Based Concurrent Engineering Framework using ISO-19450 Standard
A Model Based Concurrent Engineering Framework using ISO-19450 StandardChristopher Cerqueira
 
Modelos e metodologias de projeto de sistemas
 Modelos e metodologias de projeto de sistemas Modelos e metodologias de projeto de sistemas
Modelos e metodologias de projeto de sistemasChristopher Cerqueira
 

Mais de Christopher Cerqueira (20)

MICRO SATÉLITES BRASILEIROS, ELES EXISTEM?
MICRO SATÉLITES BRASILEIROS, ELES EXISTEM?MICRO SATÉLITES BRASILEIROS, ELES EXISTEM?
MICRO SATÉLITES BRASILEIROS, ELES EXISTEM?
 
Jornada Espacial 2018 - Cubesats: o que são e pra que servem
Jornada Espacial 2018 - Cubesats: o que são e pra que servemJornada Espacial 2018 - Cubesats: o que são e pra que servem
Jornada Espacial 2018 - Cubesats: o que são e pra que servem
 
CI2018_Simuladores
CI2018_Simuladores CI2018_Simuladores
CI2018_Simuladores
 
CI2018_MBSE4.0
CI2018_MBSE4.0CI2018_MBSE4.0
CI2018_MBSE4.0
 
[Thesis] Tangible Collaboration applied in Space Systems Concurrent Engineeri...
[Thesis] Tangible Collaboration applied in Space Systems Concurrent Engineeri...[Thesis] Tangible Collaboration applied in Space Systems Concurrent Engineeri...
[Thesis] Tangible Collaboration applied in Space Systems Concurrent Engineeri...
 
XV Jornada do Espaço
XV Jornada do EspaçoXV Jornada do Espaço
XV Jornada do Espaço
 
Using Finite State Machines From Concept to Realization
Using Finite State Machines From Concept to RealizationUsing Finite State Machines From Concept to Realization
Using Finite State Machines From Concept to Realization
 
So 01 - processos
So   01 - processosSo   01 - processos
So 01 - processos
 
Redes 05 - aplicação
Redes   05 - aplicaçãoRedes   05 - aplicação
Redes 05 - aplicação
 
Redes 04 - transporte
Redes   04 - transporteRedes   04 - transporte
Redes 04 - transporte
 
Redes 03 - rede
Redes   03 - redeRedes   03 - rede
Redes 03 - rede
 
Redes 02 - enlace
Redes   02 - enlaceRedes   02 - enlace
Redes 02 - enlace
 
Redes 01 - topologia
Redes   01 - topologiaRedes   01 - topologia
Redes 01 - topologia
 
Intro heuristica
Intro heuristicaIntro heuristica
Intro heuristica
 
[Ci2017] Simuladores de Satélites
[Ci2017] Simuladores de Satélites[Ci2017] Simuladores de Satélites
[Ci2017] Simuladores de Satélites
 
MBSE e Espaço 4.0
MBSE e Espaço 4.0MBSE e Espaço 4.0
MBSE e Espaço 4.0
 
A Model Based Concurrent Engineering Framework using ISO-19450 Standard
A Model Based Concurrent Engineering Framework using ISO-19450 StandardA Model Based Concurrent Engineering Framework using ISO-19450 Standard
A Model Based Concurrent Engineering Framework using ISO-19450 Standard
 
Introdução à Engenharia Espacial
Introdução à Engenharia EspacialIntrodução à Engenharia Espacial
Introdução à Engenharia Espacial
 
CubeSats e Software Embarcado
CubeSats e Software EmbarcadoCubeSats e Software Embarcado
CubeSats e Software Embarcado
 
Modelos e metodologias de projeto de sistemas
 Modelos e metodologias de projeto de sistemas Modelos e metodologias de projeto de sistemas
Modelos e metodologias de projeto de sistemas
 

Último

Baladão sobre Variação Linguistica para o spaece.pptx
Baladão sobre Variação Linguistica para o spaece.pptxBaladão sobre Variação Linguistica para o spaece.pptx
Baladão sobre Variação Linguistica para o spaece.pptxacaciocarmo1
 
VALORES HUMANOS NA DISCIPLINA DE ENSINO RELIGIOSO
VALORES HUMANOS NA DISCIPLINA DE ENSINO RELIGIOSOVALORES HUMANOS NA DISCIPLINA DE ENSINO RELIGIOSO
VALORES HUMANOS NA DISCIPLINA DE ENSINO RELIGIOSOBiatrizGomes1
 
O guia definitivo para conquistar a aprovação em concurso público.pdf
O guia definitivo para conquistar a aprovação em concurso público.pdfO guia definitivo para conquistar a aprovação em concurso público.pdf
O guia definitivo para conquistar a aprovação em concurso público.pdfErasmo Portavoz
 
Geometria 5to Educacion Primaria EDU Ccesa007.pdf
Geometria  5to Educacion Primaria EDU  Ccesa007.pdfGeometria  5to Educacion Primaria EDU  Ccesa007.pdf
Geometria 5to Educacion Primaria EDU Ccesa007.pdfDemetrio Ccesa Rayme
 
Prática de interpretação de imagens de satélite no QGIS
Prática de interpretação de imagens de satélite no QGISPrática de interpretação de imagens de satélite no QGIS
Prática de interpretação de imagens de satélite no QGISVitor Vieira Vasconcelos
 
Currículo escolar na perspectiva da educação inclusiva.pdf
Currículo escolar na perspectiva da educação inclusiva.pdfCurrículo escolar na perspectiva da educação inclusiva.pdf
Currículo escolar na perspectiva da educação inclusiva.pdfIedaGoethe
 
Investimentos. EDUCAÇÃO FINANCEIRA 8º ANO
Investimentos. EDUCAÇÃO FINANCEIRA 8º ANOInvestimentos. EDUCAÇÃO FINANCEIRA 8º ANO
Investimentos. EDUCAÇÃO FINANCEIRA 8º ANOMarcosViniciusLemesL
 
ÁREA DE FIGURAS PLANAS - DESCRITOR DE MATEMATICA D12 ENSINO MEDIO.pptx
ÁREA DE FIGURAS PLANAS - DESCRITOR DE MATEMATICA D12 ENSINO MEDIO.pptxÁREA DE FIGURAS PLANAS - DESCRITOR DE MATEMATICA D12 ENSINO MEDIO.pptx
ÁREA DE FIGURAS PLANAS - DESCRITOR DE MATEMATICA D12 ENSINO MEDIO.pptxDeyvidBriel
 
Cultura e Sociedade - Texto de Apoio.pdf
Cultura e Sociedade - Texto de Apoio.pdfCultura e Sociedade - Texto de Apoio.pdf
Cultura e Sociedade - Texto de Apoio.pdfaulasgege
 
Cartilha 1º Ano Alfabetização _ 1º Ano Ensino Fundamental
Cartilha 1º Ano Alfabetização _ 1º Ano Ensino FundamentalCartilha 1º Ano Alfabetização _ 1º Ano Ensino Fundamental
Cartilha 1º Ano Alfabetização _ 1º Ano Ensino Fundamentalgeone480617
 
Empreendedorismo: O que é ser empreendedor?
Empreendedorismo: O que é ser empreendedor?Empreendedorismo: O que é ser empreendedor?
Empreendedorismo: O que é ser empreendedor?MrciaRocha48
 
Educação São Paulo centro de mídias da SP
Educação São Paulo centro de mídias da SPEducação São Paulo centro de mídias da SP
Educação São Paulo centro de mídias da SPanandatss1
 
Noções de Orçamento Público AFO - CNU - Aula 1 - Alunos.pdf
Noções de Orçamento Público AFO - CNU - Aula 1 - Alunos.pdfNoções de Orçamento Público AFO - CNU - Aula 1 - Alunos.pdf
Noções de Orçamento Público AFO - CNU - Aula 1 - Alunos.pdfdottoor
 
QUARTA - 1EM SOCIOLOGIA - Aprender a pesquisar.pptx
QUARTA - 1EM SOCIOLOGIA - Aprender a pesquisar.pptxQUARTA - 1EM SOCIOLOGIA - Aprender a pesquisar.pptx
QUARTA - 1EM SOCIOLOGIA - Aprender a pesquisar.pptxIsabellaGomes58
 
Slides Lição 3, Betel, Ordenança para congregar e prestar culto racional, 2Tr...
Slides Lição 3, Betel, Ordenança para congregar e prestar culto racional, 2Tr...Slides Lição 3, Betel, Ordenança para congregar e prestar culto racional, 2Tr...
Slides Lição 3, Betel, Ordenança para congregar e prestar culto racional, 2Tr...LuizHenriquedeAlmeid6
 
HABILIDADES ESSENCIAIS - MATEMÁTICA 4º ANO.pdf
HABILIDADES ESSENCIAIS  - MATEMÁTICA 4º ANO.pdfHABILIDADES ESSENCIAIS  - MATEMÁTICA 4º ANO.pdf
HABILIDADES ESSENCIAIS - MATEMÁTICA 4º ANO.pdfdio7ff
 
637743470-Mapa-Mental-Portugue-s-1.pdf 4 ano
637743470-Mapa-Mental-Portugue-s-1.pdf 4 ano637743470-Mapa-Mental-Portugue-s-1.pdf 4 ano
637743470-Mapa-Mental-Portugue-s-1.pdf 4 anoAdelmaTorres2
 
A Inteligência Artificial na Educação e a Inclusão Linguística
A Inteligência Artificial na Educação e a Inclusão LinguísticaA Inteligência Artificial na Educação e a Inclusão Linguística
A Inteligência Artificial na Educação e a Inclusão LinguísticaFernanda Ledesma
 
Aula - 2º Ano - Cultura e Sociedade - Conceitos-chave
Aula - 2º Ano - Cultura e Sociedade - Conceitos-chaveAula - 2º Ano - Cultura e Sociedade - Conceitos-chave
Aula - 2º Ano - Cultura e Sociedade - Conceitos-chaveaulasgege
 
geografia 7 ano - relevo, altitude, topos do mundo
geografia 7 ano - relevo, altitude, topos do mundogeografia 7 ano - relevo, altitude, topos do mundo
geografia 7 ano - relevo, altitude, topos do mundonialb
 

Último (20)

Baladão sobre Variação Linguistica para o spaece.pptx
Baladão sobre Variação Linguistica para o spaece.pptxBaladão sobre Variação Linguistica para o spaece.pptx
Baladão sobre Variação Linguistica para o spaece.pptx
 
VALORES HUMANOS NA DISCIPLINA DE ENSINO RELIGIOSO
VALORES HUMANOS NA DISCIPLINA DE ENSINO RELIGIOSOVALORES HUMANOS NA DISCIPLINA DE ENSINO RELIGIOSO
VALORES HUMANOS NA DISCIPLINA DE ENSINO RELIGIOSO
 
O guia definitivo para conquistar a aprovação em concurso público.pdf
O guia definitivo para conquistar a aprovação em concurso público.pdfO guia definitivo para conquistar a aprovação em concurso público.pdf
O guia definitivo para conquistar a aprovação em concurso público.pdf
 
Geometria 5to Educacion Primaria EDU Ccesa007.pdf
Geometria  5to Educacion Primaria EDU  Ccesa007.pdfGeometria  5to Educacion Primaria EDU  Ccesa007.pdf
Geometria 5to Educacion Primaria EDU Ccesa007.pdf
 
Prática de interpretação de imagens de satélite no QGIS
Prática de interpretação de imagens de satélite no QGISPrática de interpretação de imagens de satélite no QGIS
Prática de interpretação de imagens de satélite no QGIS
 
Currículo escolar na perspectiva da educação inclusiva.pdf
Currículo escolar na perspectiva da educação inclusiva.pdfCurrículo escolar na perspectiva da educação inclusiva.pdf
Currículo escolar na perspectiva da educação inclusiva.pdf
 
Investimentos. EDUCAÇÃO FINANCEIRA 8º ANO
Investimentos. EDUCAÇÃO FINANCEIRA 8º ANOInvestimentos. EDUCAÇÃO FINANCEIRA 8º ANO
Investimentos. EDUCAÇÃO FINANCEIRA 8º ANO
 
ÁREA DE FIGURAS PLANAS - DESCRITOR DE MATEMATICA D12 ENSINO MEDIO.pptx
ÁREA DE FIGURAS PLANAS - DESCRITOR DE MATEMATICA D12 ENSINO MEDIO.pptxÁREA DE FIGURAS PLANAS - DESCRITOR DE MATEMATICA D12 ENSINO MEDIO.pptx
ÁREA DE FIGURAS PLANAS - DESCRITOR DE MATEMATICA D12 ENSINO MEDIO.pptx
 
Cultura e Sociedade - Texto de Apoio.pdf
Cultura e Sociedade - Texto de Apoio.pdfCultura e Sociedade - Texto de Apoio.pdf
Cultura e Sociedade - Texto de Apoio.pdf
 
Cartilha 1º Ano Alfabetização _ 1º Ano Ensino Fundamental
Cartilha 1º Ano Alfabetização _ 1º Ano Ensino FundamentalCartilha 1º Ano Alfabetização _ 1º Ano Ensino Fundamental
Cartilha 1º Ano Alfabetização _ 1º Ano Ensino Fundamental
 
Empreendedorismo: O que é ser empreendedor?
Empreendedorismo: O que é ser empreendedor?Empreendedorismo: O que é ser empreendedor?
Empreendedorismo: O que é ser empreendedor?
 
Educação São Paulo centro de mídias da SP
Educação São Paulo centro de mídias da SPEducação São Paulo centro de mídias da SP
Educação São Paulo centro de mídias da SP
 
Noções de Orçamento Público AFO - CNU - Aula 1 - Alunos.pdf
Noções de Orçamento Público AFO - CNU - Aula 1 - Alunos.pdfNoções de Orçamento Público AFO - CNU - Aula 1 - Alunos.pdf
Noções de Orçamento Público AFO - CNU - Aula 1 - Alunos.pdf
 
QUARTA - 1EM SOCIOLOGIA - Aprender a pesquisar.pptx
QUARTA - 1EM SOCIOLOGIA - Aprender a pesquisar.pptxQUARTA - 1EM SOCIOLOGIA - Aprender a pesquisar.pptx
QUARTA - 1EM SOCIOLOGIA - Aprender a pesquisar.pptx
 
Slides Lição 3, Betel, Ordenança para congregar e prestar culto racional, 2Tr...
Slides Lição 3, Betel, Ordenança para congregar e prestar culto racional, 2Tr...Slides Lição 3, Betel, Ordenança para congregar e prestar culto racional, 2Tr...
Slides Lição 3, Betel, Ordenança para congregar e prestar culto racional, 2Tr...
 
HABILIDADES ESSENCIAIS - MATEMÁTICA 4º ANO.pdf
HABILIDADES ESSENCIAIS  - MATEMÁTICA 4º ANO.pdfHABILIDADES ESSENCIAIS  - MATEMÁTICA 4º ANO.pdf
HABILIDADES ESSENCIAIS - MATEMÁTICA 4º ANO.pdf
 
637743470-Mapa-Mental-Portugue-s-1.pdf 4 ano
637743470-Mapa-Mental-Portugue-s-1.pdf 4 ano637743470-Mapa-Mental-Portugue-s-1.pdf 4 ano
637743470-Mapa-Mental-Portugue-s-1.pdf 4 ano
 
A Inteligência Artificial na Educação e a Inclusão Linguística
A Inteligência Artificial na Educação e a Inclusão LinguísticaA Inteligência Artificial na Educação e a Inclusão Linguística
A Inteligência Artificial na Educação e a Inclusão Linguística
 
Aula - 2º Ano - Cultura e Sociedade - Conceitos-chave
Aula - 2º Ano - Cultura e Sociedade - Conceitos-chaveAula - 2º Ano - Cultura e Sociedade - Conceitos-chave
Aula - 2º Ano - Cultura e Sociedade - Conceitos-chave
 
geografia 7 ano - relevo, altitude, topos do mundo
geografia 7 ano - relevo, altitude, topos do mundogeografia 7 ano - relevo, altitude, topos do mundo
geografia 7 ano - relevo, altitude, topos do mundo
 

Construção de interfaces on-demand baseadas em Realidade Aumentada Projetiva para Controle de Hardware (Arduino)

  • 1. RA on-demand Criando interfaces em tempo de execução.
  • 3. Construção de interfaces on- demand baseadas em Realidade Aumentada Projetiva para Controle de Hardware (Arduino) Drª. Ana Maria Ambrosio MSc. Christopher Cerqueira aluno doutorado Dr. Claudio Kirner
  • 6. Objetivo da apresentação • Devido as restrições, vamos montar uma versão simplificada: • Ausência de projetores para todos os alunos • Ausência de ARDUINO para todos os alunos • Mostrar um framework para construção de apps de RA / RC. • openFrameworks • Mostrar os recursos de controle de hardware (Arduino) • Mostrar os recursos de CV (openCV): rastreio de contorno (infraestrutura e controles) e processamento de imagem (mão). • Mostrar tipos comuns para criação de interface. • openFrameworks • Aplicações tipo interação em mesa. (Projeção) 08:38fb.com/RVA.BR 6
  • 7. Agenda: • Conceito e openFramework • Criando o primeiro programa em openFrameworks • Conectando com o Arduino • Estudos de caso / Construção do ambiente (exemplos): • 1. Detectar infraestrutura (Apenas rastreio do papel) • 2. Rastreio do atuador (rastreio da mão) • 3. Interação com estrutura virtual • 4. Detectar estrutura física on-demand (sem reprojeção) • Wrap-Up 3 horas 1,5h 1,5h 08:38fb.com/RVA.BR 7
  • 8. Conteúdo está em •http://www.4shared.com/folder/Xka Uh0KM/Resources.html • Link tá muito difícil??? Vai em cscerqueira.com.br 08:38fb.com/RVA.BR 8
  • 10. “The product is no longer the basis of value. The experience is.” Venkat Ramaswamy The Future of Competition 08:38fb.com/RVA.BR 10
  • 11. Valor de uma boa experiência 08:38fb.com/RVA.BR 11
  • 12. Interação Texto, som, cores, visual, mecânico ou físico. Interface Mensagens Usuário Sistema 08:38fb.com/RVA.BR 12
  • 14. Exemplo: • Usabilidade: 1. Facilidade de aprendizado 2. Eficiência 3. Facilidade de memorização 4. Erros 5. Satisfação subjetiva Meta- Mensagens Usuário Sistema 08:38fb.com/RVA.BR 14
  • 15. 3 níveis Lógico: Resolvem, solucionam, facilitam. Emocional: Satisfazem necessidades e desejos afetivos. Visceral: resolvem questões fundamentais, sem consciência. Impulso. 08:38fb.com/RVA.BR 15
  • 18. Realidades – Realidade Virtual interface que permite ao usuário interagir, em tempo real, com um mundo tridimensional gerado por computador, usando seus sentidos através de equipamentos especiais. SOURCE: NASA (2013a) 08:38 18 fb.com/RVA.BR
  • 20. Realidades – Realidade Aumentada uma interfacebaseada na sobreposição de informações virtuais geradas por computador (envolvendo imagens estáticas e dinâmicas, sons espaciais e sensações hápticas) com o ambiente físico do usuário, percebida através de dispositivos tecnológicos e usando as interações naturais do usuário, no mundo físico. Claudio Kirner SOURCE: Adapted from ESA (2009) and Capua (2008) 08:38 20 fb.com/RVA.BR
  • 21. Christopher Vision Informação virtual Interação Natural dispositivos tecnológicos 08:38 21 fb.com/RVA.BR
  • 22. Realidades – Realidade Cruzada é um ambiente de realidade misturada ubíqua, que vem da fusão de uma rede de sensores e atuadores (que coletam e enviam dados relacionados ao mundo real) com mundos virtuais compartilhados, usando a interface da realidade aumentada. Claudio Kirner Introdução 08:38fb.com/RVA.BR 22
  • 23. Kirner’s Diagram – elementos Source: (KIRNER et al., 2012) Lego Cave 08:38fb.com/RVA.BR 23
  • 24. Realidade Cruzada Objetos reais Sensores e Atuadores Realidade Aumentada OCR NOCR NOCR Introdução 08:38fb.com/RVA.BR 24
  • 25. HIT - ROADMAP CR AI HI AR IoT HR KMatsuda 08:38fb.com/RVA.BR 25
  • 26. [ ] Hololens • Talvez o primeiro hardware de RA, com sobreposição, que entra com força no mercado. • Google Glass tentou, mas na maioria dos apps não tinha sobreposição intrínseca. • Vídeo 1 08:38fb.com/RVA.BR 26
  • 27. Qual o motivo de RA ainda não ter pego em atividades de engenharia? HWs de interação? HWs de visualização? Frameworks de rastreio SWs Frameworks geo-localizados Frameworks de interação 08:38fb.com/RVA.BR 27
  • 28. Um dos motivos ao nosso ver é: • Dificuldade de criação e manipulação de uma interface de RA a medida que é utilizada. • Poderíamos então pensar em uma estratégia, de criação de uma interface física e indicar sua camada virtual a medida que é necessário (on-demand) e a função desejada. • Esses minicurso essencialmente é para mostrar uma opção de criação de interface em RA on demand. • “Solução simplificada: openFrameworks + visão computacional.” 08:38fb.com/RVA.BR 28
  • 31. openframeworks.cc • Vídeo oF1....media_videos7_openFrameworks1.mp4 • Vídeo oF2....media_videos7_openFrameworks2.mp4 08:38fb.com/RVA.BR 31
  • 32. oF • Criado para artistase designers • Desenvolvido por: Zach Liberman, Theo Watson, Artuno Castro e Chris O’Shea •Proposta: Arrumar a falta de comunicação entre diversas bibliotecas em C++, e permitir portabilidade. • Escrita em C++ • Licença: MIT (educacional e venda) • Usar quando: • O projeto renderiza muitos gráficos 3D, e/ou; • Utilizar muita visão computacional, e/ou; • Controlar equipamentos, como, por exemplo: • o ARDUINO. 08:38fb.com/RVA.BR 32
  • 36. Libs no pacote padrão • OpenGL, GLEW, GLUT, libtess2 e cairo para gráficos. • rtAudio, PortAudio ou FMOD e Kiss FFT para entrada, saída e análise de áudio. • FreeType para fontes. • FreeImage para salvar e carregar imagens. • Quicktime e videoInput para playback e aquisição de vídeo. • Poco, que contém uma variedade de utilidades. 08:38fb.com/RVA.BR 36
  • 39. ERA TROGLODITA (C++) • Graduação (2010): • ARToolKit • PTAMM • Bolsista DTI (2011): • basAR ERA DO FOGO (C++/oF) • Mestrado (2012): • Doutorado (2014): 08:38fb.com/RVA.BR 39
  • 40. MDE (Model Driven Engineering) MBSE (ModelBased SystemEngineering) • MDE é um conjunto de práticas de engenharia, baseadas em ferramentas que utilizam ao mesmo tempo meta- modelagem e transformações de modelos para atingirem automaticamente objetivos em produção, manutenção ou operação de sistemas intensivos em software. 40 Motivador - Matlab 08:38fb.com/RVA.BR
  • 41. Três tipos principais de aplicações MDE MDE Geração automática Descoberta do Modelo Interoperabilidade de sistemas 41 Um modelo pode ser transformado em outro modelo. Um meta-modelo é um conjunto de conceitos e relações que o modelo pode realizar. “Filtro” de possibilidade. Uma representação gera um conjunto de elementos. 08:38fb.com/RVA.BR
  • 43. • Introdução à utilização de openFrameworks para o desenvolvimento de aplicações de RVA Link • Construção de aplicações de Realidade Cruzada Projetiva utilizando openFrameworks e ARDUINO Link • Utilização de Realidade Aumentada, com marcadores(ARToolKitPlus) e outros (utilizando openCV), para controle e inspeção de hardware, utilizando a interface ARDUINO. Link 08:38fb.com/RVA.BR 43
  • 47. PRIMEIRO PROGRAMA EM OF Vou pular, coloquei aqui para ficar + completo 08:38fb.com/RVA.BR 47
  • 52. Exemplo básico 08:38fb.com/RVA.BR 52 // ofApp.cpp void ofApp::setup(){ mensagem = "Hello SVR2015!!!"; raio = 0; } void ofApp::draw(){ ofEnableAlphaBlending(); ofSetColor(ofColor::blue,128); ofCircle(x_i,y_i,raio); ofSetColor(ofColor::red); ofDrawBitmapString(mensagem,mouseX,mouseY); } // ofApp.cpp void ofApp::mouseDragged(int x, int y, int button){ raio = ofDist(x_i,y_i,x,y); } void ofApp::mousePressed(int x, int y, int button){ x_i = x; y_i = y; } void ofApp::mouseReleased(int x, int y, int button){ raio = ofDist(x_i,y_i,x,y); } // ofApp.h ... string mensagem; int x_i,y_i; float raio; ...
  • 53. ARDUINO O que é? Onde vivem? Existe? Hoje no Glob.. Fritzing, Arduino 1.0, Firmata, exemplo openFrameworks 08:38fb.com/RVA.BR 53
  • 54. O que tem no ARDUINO? 08:38 54 fb.com/RVA.BR
  • 58. O que a FIRMATA faz!? • Transforma o ARDUINO numa interface de controle, podendo ser modificado por um host. • Quais as vantagens? • O host controla a execução! • O host tem mais memória. • O host resolve as lógicas de controle muito mais rápido. • Desvantagens?! • Tem que ficar atrelado ao host! 08:38 58 fb.com/RVA.BR
  • 59. Obs.: Mudança da nomenclatura dos pinos após Firmata 2.3 (Arduino 1.0) Tomar cuidado na hora de desenvolver!!!!!!!!!! 08:38fb.com/RVA.BR 59
  • 60. Instalando a Firmata no Arduino • Faça download do Arduino 1.0.6 http://arduino.cc/en/ Main/Software • Abra o sketch do Firmata Standard. • Transfira para a board. 08:38fb.com/RVA.BR 60 http://arduino.cc/en/reference/firmata
  • 63. Métodos para conectar com o ARDUINO  connect()  disconnect()  getAnalog()  getAnalogPinReporting()  getDigital()  getDigitalPinMode()  getPwm()  getString()  isArduinoReady()  isInitialized()  sendAnalogPinReporting()  sendByte()  sendDigital()  sendDigitalPinMode()  sendPwm()  sendReset()  sendString()  setUseDelay()  update() 08:38 63 fb.com/RVA.BR
  • 64. Código no openFrameworks • Exploração do exemplo: communicationfirmataExample 08:38fb.com/RVA.BR 64
  • 65. Fluxograma básico 08:38fb.com/RVA.BR 65 SETUP Habilita callback de Arduino Alive Arduino Responde Evento Alive Configura Arduino Loop de execução – sem Arduino Enviar comandos pro Arduino Recebeu um evento Digital Recebeu um evento Analógico Loop de execução – Arduino Update
  • 66. Código 08:38fb.com/RVA.BR 66 //ofApp.h #pragma once #include "ofMain.h" class ofApp : public ofBaseApp{ public: … ofArduino ard; bool bSetupArduino; private: void setupArduino(const int & version); void digitalPinChanged(const int & pinNum); void analogPinChanged(const int & pinNum); void updateArduino(); }; //ofApp.cpp void ofApp::setup(){ ... ard.connect("COM3", 57600); //conecta com arduino ofAddListener(ard.EInitialized, this, &ofApp::setupArduino); bSetupArduino= false;// flag arduino ok  } void ofApp::setupArduino(const int & version) { ofRemoveListener(ard.EInitialized, this, &ofApp::setupArduino); bSetupArduino = true; // agora pode usar o arduino. ard.sendDigitalPinMode(2, ARD_INPUT); //pino entrada digital ard.sendAnalogPinReporting(0, ARD_ANALOG); // pino entrada analógica ard.sendDigitalPinMode(13, ARD_OUTPUT); // configura pino saída digital ard.sendDigitalPinMode(11, ARD_PWM); // configura pino saída PWM ard.sendServoAttach(9); // diz que o pino tem um servo. ofAddListener(ard.EDigitalPinChanged, this, &ofApp::digitalPinChanged); //callback para eventos de pino digital. ofAddListener(ard.EAnalogPinChanged, this, &ofApp::analogPinChanged); //callback para eventos de pino analógico } void ofApp::updateArduino(){ ard.update(); // verifica se algo mudou no Arduino - obrigatório if (bSetupArduino) { //envia o que for para o Arduino. ard.sendPwm(11, (int)(128 + 128 * sin(ofGetElapsedTimef()))); // pwm... } } //ofApp.cpp void ofApp::digitalPinChanged(const int & pinNum) { // trata o pino digital - ard.getDigital(pinNum) } void ofApp::analogPinChanged(const int & pinNum) { // trata o pino analógico - ard.getAnalog(pinNum) } //outros comandos ard.sendServo(9, 180, false); ard.sendDigital(8, ARD_HIGH);
  • 68. Casos • 0.a. O que vamos fazer: • 1. Detecção de infraestrutura (contornos) • 2. Detecção de atuador (diferença de imagens) • 3. Interação mão / virtual / Arduino • 4. Rastreio dos controles. (contornos) • Real (Drawn) e Virtual Matching 08:38fb.com/RVA.BR 68
  • 69. 0.a. O que vamos fazer:
  • 70. Ambiente reativo à altura da areia Ambiente reativo ao comportamento dos pontos (soldados) 08:38fb.com/RVA.BR 70
  • 71. Conceito de ambiente dividido em pontos e camadas 08:38fb.com/RVA.BR 71
  • 73. O que vamos usar para o exemplo 08:38fb.com/RVA.BR 73
  • 74. Só use mais hardware quando realmente precisar. 08:38fb.com/RVA.BR 74
  • 75. DETECTING INFRASTRUCTURE Encontrando uma folha de papel para servir de referência para a montagem dos elementos de interação. 08:38fb.com/RVA.BR 75
  • 76. Detectar a infraestrutura Capturar Imagem Procurar “coisas” brancas Identificar polígono • Maior de todos? é um retângulo? Encontrei a infraestrutura Retirar a imagem da área ide interação 08:38fb.com/RVA.BR 76
  • 78. USANDO O OPENCV Cores, blobs e exemplos 08:38fb.com/RVA.BR 78
  • 79. Cores RGB-A (red, green, blue)-alfa HSV (hue (cor), saturation, value) 08:38 79 fb.com/RVA.BR
  • 80. Blobs • Método de busca de características. • Blobs compartilham propriedades constantes que podem ser “percebidas” na imagem. 08:38 80 fb.com/RVA.BR
  • 81. Construção dos artefatos : Rastreio Cores 08:38 81 fb.com/RVA.BR
  • 83. Usos • Table-tops • Projeções em paredes 08:38 83 fb.com/RVA.BR Sensetable L.A.S.E.R. Tag Climbing OASIS
  • 84. Continuando .... Usando o addon: ofxCv de Kyle McDonald https://github.com/kylemcdonald/ofxCv 08:38fb.com/RVA.BR 84
  • 85. Tipo: ofxCv::ContourFinder • Tipo/função que procura blobs numa imagem. • Retorna os blobs e características: • Posição • Contorno • Centroide, média centro, pontos das bordas, menor retângulo contornável, menor elipse, etc etc etc... 08:38fb.com/RVA.BR 85
  • 87. // Camera: ofVideoGrabber cam; // Video Tracking source int camHeight; int camWidth; ofImage unwarped; // RAW image from camera // Descobridor de papel ofxCv::ContourFinder contourFinder; int thresholdCV; ofPolyline contour; ofImage warpedPaper; bool foundInfra; // ## Função para retornar tipo de forma geométrica private: string findForm(const ofPolyline &poly); template <class T> string findForm(const T &poly){ return findForm(ofxCv::toOf(poly)); } }; Câmera Procurador de papel 08:38fb.com/RVA.BR 87
  • 88. Identificar Formas Convexas • Entrada: número de vértices • 3 vértices = TRIANGULO • 4 vértices e cos +/- 0 = RETÂNGULO • 5 vértices e cos +/- 0.3 = PENTÁGONO • 6 vértices e cos +/- 0.5 = HEXÁGONO • > 6 Círculo • http://opencv-code.com/tutorials/detecting-simple-shapes-in-an-image/ • https://github.com/bsdnoobz/opencv-code/blob/master/shape-detect.cpp 08:38fb.com/RVA.BR 88
  • 89. string ofApp::findForm(const ofPolyline &poly){ vector<ofPoint> corners = poly.getVertices(); // pega todos os vértices if ( corners.size() == 3) return "TRIANGLE"; if ( corners.size() >= 4 && corners.size() <= 6){ // de 4 a 6 vertices int vtc = corners.size(); vector<double> cos; for( int j = 2; j < vtc+1; j++) // mandrakaria para organizar cosenos cos.push_back(angle(corners[j%vtc], corners[j-2], corners[j-1])); sort(cos.begin(),cos.end()); double minCos = cos.front(); double maxCos = cos.back(); if( vtc == 4 && minCos >= -0.1 && maxCos <= 0.3) { cv::Rect r = cv::boundingRect(toCv(poly)); double ratio = std::abs(1 - (double)r.width / r.height); return (ratio <= 0.02) ? "SQUARE" : "RECTANGLE"; } if( vtc == 5 && minCos >= -0.34 && maxCos <= -0.27) return "PENTAGON"; if( vtc == 6 && minCos >= -0.55 && maxCos <= 0.45) return "HEXAGON"; } else { // testar se circulo } return "NO_MATCH";} 08:38fb.com/RVA.BR 89
  • 90. static double angle(ofPoint pt1, ofPoint pt2, ofPoint pt0) { double dx1 = pt1.x - pt0.x; double dy1 = pt1.y - pt0.y; double dx2 = pt2.x - pt0.x; double dy2 = pt2.y - pt0.y; return (dx1*dx2 + dy1*dy2)/sqrt((dx1*dx1 + dy1*dy1)*(dx2*dx2 + dy2*dy2) + 1e-10); } 08:38fb.com/RVA.BR 90
  • 91. void ofApp::setup(){ // Parte 2 - Código do Exemplo ofLogNotice("[PAPER DETECTOR]") << " Configure CV "; contourFinder.setMinAreaRadius(10); // configura menor área . contourFinder.setMaxAreaRadius(200); // configura maior área thresholdCV = 100; // inicializa o nível da camera. //contourFinder.setTargetColor(targetColor, trackingColorMode); // configura cor / padrão contourFinder.setThreshold(thresholdCV); // configura nível ofLogNotice("[PAPER DETECTOR]") << " Configure Camera "; camWidth = 640; camHeight = 480; cam.initGrabber(camWidth,camHeight); cam.listDevices(); unwarped.allocate(camWidth, camHeight, OF_IMAGE_COLOR); // // ALLOCATE RAW IMAGE warpedPaper.allocate(camWidth,camHeight,OF_IMAGE_COLOR); } 08:38fb.com/RVA.BR 91
  • 92. void ofApp::update(){ cam.update(); float area; if(cam.isFrameNew()){ //ofLogNotice("[PAPER DETECTOR]") << "New Frame"; vector<cv::Point> maxQuad;//maior quadrado na imagem = folha de papel. float maxArea = -numeric_limits<float>::infinity();//escolhe pela maior área. contourFinder.findContours(cam); // realiza a procura por folhas brancas em um fundo preto int n = contourFinder.size(); for(int i = 0; i < n; i++){ //ofLogNotice("[PAPER DETECTOR]") << "update: " + ofToString(i); ofPolyline minAreRect = toOf(contourFinder.getMinAreaRect(i)); vector<cv::Point> quad = contourFinder.getFitQuad(i); area = contourFinder.getContourArea(i); //encontrar o maior quadrado na imagem = folha de papel. if (area > maxArea) { //ofLogNotice("[PAPER DETECTOR]") << "1. " + ofToString(area) + " - " + ofToString(maxArea); maxArea = area; maxQuad = quad; } } 08:38fb.com/RVA.BR 92
  • 93. // teste se foi encontrado algo parecido com um retângulo. this->foundInfra = false; if ( this->findForm(maxQuad) == "RECTANGLE"){ this->foundInfra = true; // warp paper vector<Point2f> warpPoints; warpPoints.push_back(maxQuad[3]); // para organizar a ordem dos pontos. warpPoints.push_back(maxQuad[0]); warpPoints.push_back(maxQuad[1]); warpPoints.push_back(maxQuad[2]); //copy(maxQuad.begin(), maxQuad.end(), back_inserter(warpPoints)); unwarpPerspective(cam, unwarped, warpPoints); unwarped.update(); } //ofLogNotice("[PAPER DETECTOR]") << "2. " + ofToString(area) + " - " + ofToString(maxArea) + " - " + ofToString(this->foundInfra); } } 08:38fb.com/RVA.BR 93
  • 94. void ofApp::draw(){ ofSetColor(ofColor::white); cam.draw(0,0); ofNoFill(); int n = contourFinder.size(); for(int i = 0; i < n; i++) { ofSetColor(ofColor::red); // smallest rectangle that fits the contour ofPolyline minAreRect = toOf(contourFinder.getMinAreaRect(i)); minAreRect.draw(); ofSetColor(yellowPrint); // convex hull of the contour ofPolyline convexHull = toOf(contourFinder.getConvexHull(i)); convexHull.draw(); ofSetColor(cyanPrint); vector<cv::Point> quad = contourFinder.getFitQuad(i); vector<cv::Point>::iterator it; for (it = quad.begin(); it != quad.end(); it++) ofCircle(toOf(*it),3); } ofSetColor(255); unwarped.draw(640, 0); if(this->foundInfra){ ofDrawBitmapStringHighlight("Found infra",10,ofGetHeight() - 80);} ofDrawBitmapStringHighlight(ofToString(this->thresholdCV),10,ofGetHeight() - 100); } 08:38fb.com/RVA.BR 94
  • 96. WHERE IS MY HAND? DETECTING THE ACTUATOR Detectando a mão, caneta, ou qualquer outra coisa (medo) que você queira usar para fazer interação. 08:38fb.com/RVA.BR 96
  • 97. Rastrear mão (apontador 2D) • Restrições (para facilitar) Fundo homogêneo Longe das quinas Uma mão só • Pseudo-código • Fazer diferença entra o fundo e o frame atual para encontrar a mão. • Com a diferença rastreia o blob. • Do blob calcula as quinas • Das quinas pega a mais distante do centroide e que não seja próximo das quinas ( braço). 08:38fb.com/RVA.BR 97
  • 98. Lets code.... Babe!!!!  #include "ofMain.h" #include "ofxOpenCv.h" //Cabeçalho do OpenCV #include "ofxCv.h" class ofApp : public ofBaseApp{ ... int width, height, threshold; ofVideoGrabber vidGrabber; // Componente do oF que pega a câmera. ofxCvColorImage colorImage; // imagem capturada pela câmera ofxCvGrayscaleImage grayBg, grayImage, grayDiff;// bg, cinza, diferença bool bLearnBackground; ofxCv::TrackingColorMode trackingColorMode; ofxCv::ContourFinder contourFinder; ofColor targetColor; ofPoint apontador; ofPoint encontraPontoMaisDistante(); }; 08:38fb.com/RVA.BR 98
  • 99. Tipo: ofPoint • ofPoint é um tipo muito utilizado no openFrameworks que faz as vezes de um ponto na área da janela. • Com ele podemos posicionar pontos na área da janela. • Essencialmente é um vetor X,Y,Z. Herda de ofVec3f • Possui propriedades sobrecarregadas de operação de vetores. 08:38fb.com/RVA.BR 99
  • 100. Setup void ofApp::setup(){ width = 320; height = 240; vidGrabber.initGrabber(width, height); //abre câmera colorImage.allocate(width,height); //aloca memória para as imagens grayBg.allocate(width,height); grayImage.allocate(width,height); grayDiff.allocate(width,height); contourFinder.setMinAreaRadius(10); //configura rastreador contourFinder.setMaxAreaRadius(150); contourFinder.setTargetColor(ofColor::white, TRACK_COLOR_RGB); threshold = 50; bLearnBakground = true; } 08:38fb.com/RVA.BR 100
  • 102. Update void ofApp::update(){ vidGrabber.update(); // Pega frame da câmera if(vidGrabber.isFrameNew()){ // é um frame novo ??? colorImage.setFromPixels(vidGrabber.getPixels(),width,height); grayImage = colorImage; if (bLearnBackground == true){ grayBg = grayImage;// salva o fundo da tela - TO ROUBANDO MESMO! bLearnBackground = false;} grayDiff.absDiff(grayBg, grayImage); // fazer fundo x atual grayDiff.threshold(threshold); contourFinder.setThreshold(threshold); // procurar blobs no atual contourFinder.findContours(grayDiff); apontador = encontraPontoMaisDistante(); // procurar “dedo” } } 08:38fb.com/RVA.BR 102
  • 104. Ponto mais distante – p1 ofPoint ofApp::encontraPontoMaisDistante(){ int n = contourFinder.size(); //qtidade de blobs capturados ofPoint maisDistante ; //nosso ponto mais distante for(int i = 0; i < n; i++) { ofVec2f centroid = toOf(contourFinder.getCentroid(i)); //Centroide; ofPolyline convexHull = toOf(contourFinder.getConvexHull(i)); //quinas; vector<ofPoint> vertices = convexHull.getVertices(); // vetorDeQuinas vector<ofPoint>::iterator itVec; // para percorrer as quinas. maisDistante = (*vertices.begin()); float tamMaisDistante = centroid.distanceSquared(maisDistante); float distanciaAtual = 0; 08:38fb.com/RVA.BR 104
  • 105. Ponto mais distante – p2 for(itVec = vertices.begin(); itVec != vertices.end(); itVec++){ //encontrar ponto mais distante do dedo --> eliminar as bordas if( ((*itVec).x > 40) && ((*itVec).x < width - 40) && ((*itVec).y > 40) && ((*itVec).y < height - 40)){ //elimina bordas distanciaAtual = centroid.distanceSquared((*itVec)); if(distanciaAtual > tamMaisDistante){ //maior “simple as possible” maisDistante = (*itVec); tamMaisDistante = distanciaAtual; } } } } return maisDistante; } 08:38fb.com/RVA.BR 105
  • 106. Draw void ofApp::draw(){ ofSetColor(255); grayImage.draw(0, 0); // desenha câmera ofTranslate(320, 0); grayDiff.draw(0, 0); // desenha threshold ofTranslate(-320,240); contourFinder.draw(); //desenha contorno encontrado ofSetColor(ofColor::hotPink); ofDrawBitmapString("openCV Threshold: " + ofToString(threshold),50,50); ofTranslate(0,-240); ofFill(); ofSetColor(ofColor::green); ofCircle(apontador,5); //desenha bola verde no “dedo” } 08:38fb.com/RVA.BR 106
  • 108. PLAYING IN THE AIR! Interagindo em elementos virtuais com a mão. 08:38fb.com/RVA.BR 108
  • 109. Definindo um conjunto de ações • Assunto: Controlar um Arduino  • Ações: • Acender e Apagar um LED via Arduino, com replicação virtual, via botão físico e botão virtual. • Controlar um servo motor a partir de uma barra virtual. Dica: Esse é um bom algoritmo para fazer o debounce do toque: http://drmarty.blogspot.com.br/2009/05/best-switch-debounce-routine-ever.html 08:38fb.com/RVA.BR 109
  • 110. Espalhando controles virtuais pela área capturada pela câmera • 1º Projeto de Interface (livre em toda a área) “É você Google Glass? É voce Hololens?” (Clotilde, 1985) 08:38fb.com/RVA.BR 110
  • 111. Tipo: ofRectangle • Tipo que define um retângulo na tela. • Retângulos são muito usados para definir áreas de toque. (Forma mais simples) • O tipo ofRectangle possui: • X,Y,(Z) do canto superior esquerdo (Referência) • Height, Width • Operadores sobrecarregados • Varias funções de posicionamento • Adição, crescimento para englobar outros, etc etc etc. 08:38fb.com/RVA.BR 111
  • 112. Some code... (testartoques?inside()) ofRectangle controleServo; ofRectangle chaveOff; ofRectangle chaveOn; ofPoint LEDIndicativo; ofColor ledColor; bool ledStatus; // Configurar posição dos elementos da interface controleServo.set(30,85,40,140); chaveOff.set(197,160,40,40); chaveOn.set(237,160,40,40); LEDIndicativo.set(160,50); if( this->controleServo.inside(dedo) ) { // trata para controle doservo} if( this->chaveOn.inside(dedo)) { // trata evento do botão On} if( this->chaveOff.inside(dedo)) { // trata evento do botão Off} ofApp.h ofApp.cpp – setup() ofApp.cpp – update() 08:38fb.com/RVA.BR 112
  • 114. Adicionando comandos e leitura do Arduino // Setup Arduino() ard.sendDigitalPinMode(2, ARD_INPUT); // led do exemplo ard.sendDigitalPinMode(11, ARD_OUTPUT); // botão ard.sendServoAttach(9); // servo ofAddListener(ard.EDigitalPinChanged, this, &ofApp::digitalPinChanged); void ofApp::digitalPinChanged(const int & pinNum) { this->ledStatus = ard.getDigital(pinNum); if ( this->ledStatus == true){ ard.sendDigital(11,ARD_HIGH); } else { ard.sendDigital(11,ARD_LOW); } } 08:38fb.com/RVA.BR 114
  • 115. bool ofApp::updateInterface(ofPoint dedo){ if( this->controleServo.inside(dedo) ) { // trata evento com servo // |controleServo.y ----- dedo.y ---- controleServo.y + controleServo.height| // |0 --------------------- y --------------------------- 180 | positionServo = (int) (dedo.y - controleServo.y)*180/controleServo.height; ard.sendServo(9, positionServo, false); } if( this->chaveOn.inside(dedo)) { // trata evento com botão On ledStatus = 1; ard.sendDigital(11,ARD_HIGH); // envia comando pro arduino } if( this->chaveOff.inside(dedo)) { // trata evento com botão Off ledStatus = 0; ard.sendDigital(11,ARD_LOW); //envia comando para o arduino } // pega dado do status do led this->ledStatus == 1 ? this->ledColor = ofColor::green : this->ledColor = ofColor::white; return true; } 08:38fb.com/RVA.BR 115
  • 116. TRACKING PHYSICAL CONTROLS. THINGS ARE GETING REAL Rastreando controles desenhados na infraestrutura 08:38fb.com/RVA.BR 116
  • 118. Pseudo Código • Encontrada a infraestrutura: • Update: 1. Processar imagem 2. Procurar controles 1. Procurar tipo Slide 2. Procurar tipo Switch 3. Procurar tipo Button 3. Tendo os controles 1. Associar um controle a uma função predefinida de uma paleta de controles • Draw: 1. Desenhar paleta de funções num canto da infraestrutura 2. Desenhar controles encontrados (Forma e status) 1. Ajustar ponto de vista!!! (mesmo usando vista superior, em caso de projeção é necessário corrigir, pois câmera e projetor não estão no mesmo ponto) 08:38fb.com/RVA.BR 118
  • 120. Etapas do processamento 2. Canny 3. Dilate 4. Erode 6. contourFinder infra 08:38fb.com/RVA.BR 120
  • 121. No “ofApp.h” // Controles ofxCv::ContourFindercontrolFinder; booldoControlDetection; // auxiliares para forçar as imagens: cv::Mat grayImg; cv::Mat canny; cv::Mat eroded; cv::Mat dilated; cv::Mat edgesInput; cv::Mat edges; int BORDER; float ALPHA; vector<Controle> listaDeControles; voidtoogleControlDetection() { doControlDetection == true ? doControlDetection = false : doControlDetection = true; }; void encontraControles(); void processaInteracao(); void desenhaControles(); 08:38fb.com/RVA.BR 121
  • 122. Processamento da imagem void ofApp::encontraControles(){ Mat img = ofxCv::toCv(this->unwarped); // Get the image in the right format and run edge detection - cheat - tricks ofxCv::convertColor(img, grayImg, CV_RGB2GRAY); //converte a imagem para cinza cv::Canny(grayImg, edgesInput, 160, 180, 3); // extrapola as bordas - edge map canny = edgesInput; cv::dilate(edgesInput, edgesInput, Mat::ones(2, 2, CV_8U), cv::Point(-1, -1), 7); //dilata as bordas dilated = edgesInput; cv::erode(edgesInput, edgesInput, Mat::ones(2, 2, CV_8U), cv::Point(-1, -1), 5); // erode as bordas eroded = edgesInput; const cv::Rect &roi = cv::Rect(BORDER, BORDER, edgesInput.cols - 2*BORDER, edgesInput.rows - 2*BORDER); edgesInput(roi).copyTo(edges); // Find contours in the edge detected image controlFinder.findContours(edges); //... continues } 08:38fb.com/RVA.BR 122
  • 124. Tipos de Controles: Switch – Posição 0 ou 1, memoriza a função Button – Posição 0 ou 1, instantâneo, funciona enquanto clicado, depois perde o valor Slide - Valor variável entre um máx. e um mín. 08:38fb.com/RVA.BR 124
  • 125. Identificação dos tipos de controles 08:38fb.com/RVA.BR 125
  • 126. Estrutura de dados genérica (super-hiper-mega simplificada) enum controlType{ CT_SWITCH, CT_BUTTON, CT_SLIDE }; class Controle { public: int id; controlType type; int value; int max; int min; //Para desenhar: ofPoint pos; ofRectangle posRect; float radius; float angle; void draw(){}; //para preencher os campos void fillSlider( cv::RotatedRect rotRect){} void fillSwitch( cv::RotatedRect rotRect){}; void fillButton( cv::Point center, float radius){}; bool interact(ofPoint dedo); }; Ideal é que sejam feitas classes e polimorfismo de tudo. ofxProjAR R_Infra* xPAR_Actuator* r :ofxPAR_ControlManager xPAR_State* r<ofxPAR_State*> ) :void () :void :void ate) :bool ) :ofxPAR_State* ofxPAR_Infra + cam :ofVideoGrabber + camHeight :int + camWidth :int + unwarped :ofImage + showVideoFeed :bool + foundInfra :bool + projectorPoints :vector<cv::Point2f> + toProjectorMatrix :cv::Mat + alignmentComplete :bool + projWidth :int + projHeight :int # name :string + ofxPAR_Infra() + ~ofxPAR_Infra() + detect() :void + draw() :void + update() :void + setup() :void + getTransformation(int, int) :cv::Mat + getContours() :ofPolyline + unwarpPoint(ofPoint&, int, int) :ofPoint + getCamera() :ofVideoGrabber + setCamera(ofVideoGrabber) :void + setCamera(int, int) :void + getRawUnwarped() :ofImage + toogleVideoFeed() :void + isInfraFound() :bool + addCalibrationPoints(int, int) :void + resetCalibration() :void + doCalibration() :void + drawProjectionLimits() :void # computeProjectorAlignment() :void # loadProjectorAlignment() :bool # saveProjectorAlignment() :bool # resetProjectorAlignment() :void ofxPAR_Infra_PaperDetector # trackingColorMode :ofxCv::TrackingColorMode # contourFinder :ofxCv::ContourFinder # targetColor :ofColor # thresholdCV :int # contour :ofPolyline # paperImage :cv::Mat # paper :vector<cv::Point> # adaptedToScreenSize :vector<cv::Point> + ofxPAR_Infra_PaperDetector() + ~ofxPAR_Infra_PaperDetector() + draw() :void + detect() :void + calibrate() :void + update() :void + setup() :void xPAR_ControlManager etection :bool Color {readOnly} Color {readOnly} Cv::ContourFinder v::Mat Mat :Mat :Mat :cv::Mat Mat :vector<ofxPAR_Control *> int :ofPoint nt at ntrolManager() ontrolManager() d d orInput(float, float, float, float) :void :void Mat) :void rolDetection() :void raction(ofPoint&) :void ls() :void () :void ols() :void e_t) :bool e_t) :bool e_t) :bool ofxPAR_Control # id :int # name :string # value :int # color :ofColor # controlType :ControlType # selected :bool + ofxPAR_Control() + ~ofxPAR_Control() + setId(int) :void + draw() :void + setColor(ofColor&) :void + contains(float, float) :bool + contains(ofPoint&) :bool + onInteraction(float, float) :bool + onInteraction(ofPoint&) :bool + setSelection(bool) :void + isSelected() :bool + getValue() :int ofxPAR_C_Button - cx :float - cy :float - radius :float - active :bool - entered :bool + ofxPAR_C_Button() + ~ofxPAR_C_Button() + ofxPAR_C_Button(float, float, float) + draw() :void + contains(float, float) :bool + onInteraction(float, float) :bool + operator==(ofxPAR_C_Button&) :bool + operator!=(ofxPAR_C_Button&) :bool ofxPAR_C_Slider - value :float + ofxPAR_C_Slider() + ~ofxPAR_C_Slider() + ofxPAR_C_Slider(cv::RotatedRect&) + draw() :void + onInteraction(float, float) :bool ofxPAR_C_Switch - active :bool + ofxPAR_C_Switch() + ~ofxPAR_C_Switch() + ofxPAR_C_Switch(cv::RotatedRect&) + draw() :void + onInteraction(float, float) :bool ofxPAR_State stateType :AppState name :string app :ofxProjAR* ofxPAR_State() ~ofxPAR_State() draw() :void update() :void InfraSetup ofxPAR_State_Play ofxPAR_Control_Rectangular # angle :float # rect :ofRectangle + ofxPAR_Control_Rectangular() + ~ofxPAR_Control_Rectangular() + ofxPAR_Control_Rectangular(cv::RotatedRect&) + draw() :void + contains(float, float) :bool + operator==(ofxPAR_Control_Rectangular&) :bool + operator!=(ofxPAR_Control_Rectangular&) :bool # alignPoint(float, float) :ofVec2f app 08:38fb.com/RVA.BR 126
  • 127. Tipo: vector (de classes) • Vector é uma estrutura para armazenar sequencialmente. • No C++ vários tipos de estruturas de dados foram definidas usando containers genéricos. (STL) vector<Controle> listaDeControles; • Adição: Controle a; listaDeControles.push_back(a); • Remoção: listaDeControles.erase( listaDeControles.begin() + x); • Percorrer: vector<Controle>::iterator it = listaDeControles.begin(); for(; it != listaDeControles.end(); it++){ it->id; } // se vetor de ponteiros (*it)-> http://www.openframeworks.cc/tutorials/c++%20concepts/001_stl_vectors_basic.html vector<Controle*> listaDeControles; 08:38fb.com/RVA.BR 127
  • 128. //... Continuing - void ofApp::encontraControles() listaDeControles.clear(); int n = controlFinder.size(); for(int i = 0; i< n; i++){ if (isButton(i)) { float radius; cv::Point center = controlFinder.getMinEnclosingCircle(i, radius); Controle *b = new Controle(); b->id = i; b->fillButton(center, radius); listaDeControles.push_back(b); } else if (isSlider(i)) { cv::RotatedRect rect = controlFinder.getMinAreaRect(i); Controle *s = new Controle(); s->id = i; s->fillSlider(rect); listaDeControles.push_back(s); } else if (isSwitch(i)) { cv::RotatedRect rect = controlFinder.getMinAreaRect(i); Controle *s = new Controle(); s->id = 1; s->fillSwitch(rect); listaDeControles.push_back(s); } } } 08:38fb.com/RVA.BR 128
  • 129. //--------------------------------------------------------- bool ofApp::isButton(int i) { float radius; controlFinder.getMinEnclosingCircle(i, radius); float circleArea = PI * radius * radius; double contourArea = controlFinder.getContourArea(i); return abs(1.0 - circleArea / contourArea) < 0.3; } //--------------------------------------------------------- bool ofApp::isSlider(int i) { float radius; ofVec2f center = ofxCv::toOf(controlFinder.getMinEnclosingCircle(i, radius)); float circleArea = PI * radius * radius; double contourArea = controlFinder.getContourArea(i); return circleArea / contourArea > 12; } //--------------------------------------------------------- bool ofApp::isSwitch(int i) { RotatedRect rr = controlFinder.getMinAreaRect(i); float rectArea = rr.size.width * rr.size.height; double contourArea = controlFinder.getContourArea(i); return abs(1.0 - rectArea / contourArea) < 0.25 && abs(1.0 - (float) rr.size.width / rr.size.height) > 0.1; } 08:38fb.com/RVA.BR 129
  • 130. Criaroscontroles-FYI void fillSlider( cv::RotatedRect rotRect){ this->type = controlType::CT_SLIDE; const cv::Size &s = rotRect.size; bool switchHeight = s.width < s.height; if (switchHeight) { this->posRect.setFromCenter(ofxCv::toOf(rotRect.center), s.height, s.width); angle = rotRect.angle + 90; } else { this->posRect.setFromCenter(ofxCv::toOf(rotRect.center), s.width, s.height); angle = rotRect.angle; } this->value = 0; }; void fillSwitch( cv::RotatedRect rotRect){ this->type = controlType::CT_SWITCH; const cv::Size &s = rotRect.size; bool switchHeight = s.width < s.height; if (switchHeight) { this->posRect.setFromCenter(ofxCv::toOf(rotRect.center), s.height, s.width); angle = rotRect.angle + 90; } else { this->posRect.setFromCenter(ofxCv::toOf(rotRect.center), s.width, s.height); angle = rotRect.angle; } this->value = 0; }; void fillButton( cv::Point center, float radius){ this->type = controlType::CT_BUTTON; this->pos.x = center.x; this->pos.y = center.y; this->radius = radius; this->value = 0; }; 08:38fb.com/RVA.BR 130
  • 131. Draw do botão: case controlType::CT_BUTTON :{ ofPushMatrix(); ofSetColor(ofColor::green); ofSetLineWidth(5); if (this->value == 1) { ofFill(); } else { ofNoFill(); } ofCircle(this->pos, this->radius); ofPopMatrix(); break;} 08:38fb.com/RVA.BR 131
  • 132. case controlType::CT_SWITCH:{ ofPushMatrix(); ofTranslate(this->posRect.getCenter()); ofRotate(this->angle); ofNoFill(); ofSetLineWidth(3); ofSetColor(ofColor::blue); ofRect(-this->posRect.width / 2, -this->posRect.height / 2, this- >posRect.width, this->posRect.height); ofLine(0, -this->posRect.height / 2, 0, this->posRect.height / 2); float x = (this->value ? 0 : -this->posRect.width / 2); ofLine(x, -this->posRect.height / 2, x + this->posRect.width / 2, this- >posRect.height / 2); ofLine(x + this->posRect.width / 2, -this->posRect.height / 2, x, this- >posRect.height / 2); ofPopMatrix(); break;} Draw da Chave: 08:38fb.com/RVA.BR 132
  • 133. case controlType::CT_SLIDE:{ ofPushMatrix(); ofTranslate(this->posRect.getCenter()); ofRotate(this->angle); ofNoFill(); ofSetLineWidth(4); ofSetColor(ofColor::red); // Draw the main shape ofLine(-this->posRect.width / 2, 0, this->posRect.width / 2, 0); ofLine(-this->posRect.width / 2, -this->posRect.height / 2, -this->posRect.width / 2, this->posRect.height / 2); ofLine(this->posRect.width / 2, -this->posRect.height / 2, this->posRect.width / 2, this->posRect.height / 2); // Draw the tick marks ofSetLineWidth(2); for (size_t i = 1; i < 8; i++) { float dx = ((float) i / 8) * this->posRect.width; ofLine(-this->posRect.width / 2 + dx, -this->posRect.height / 3, -this->posRect.width / 2 + dx, this- >posRect.height / 3); } // Draw the value marker float xval = ((float)this->value/100) * this->posRect.width; float knobHeight = 5 * this->posRect.height / 4; float knobWidth = this->posRect.width / 8; // Fill the rectangle with black to erase the background ofPushStyle(); ofSetColor(0); ofFill(); ofRect(-this->posRect.width / 2 + xval - knobWidth / 2, -knobHeight / 2, knobWidth, knobHeight); ofPopStyle(); ofSetLineWidth(5); ofRect(-this->posRect.width / 2 + xval - knobWidth / 2, -knobHeight / 2, knobWidth, knobHeight); ofPopMatrix(); break;} Draw do Slider 08:38fb.com/RVA.BR 133
  • 134. FINAL LAP: INTERAÇÃO COM OS CONTROLES 08:38fb.com/RVA.BR 134
  • 135. Fixar os pontos de corte da figura!!!!!!!!!!!!!! 08:38fb.com/RVA.BR 135
  • 136. Inside!? bool buttonContains(int x, int y){ return ofDistSquared((float)pos.x, (float)pos.y, (float)x, (float)y) < radius * radius; } bool rectContains(int x, int y){ return posRect.inside(x, y); } 08:38fb.com/RVA.BR 136
  • 137. switch(type){ case controlType::CT_BUTTON : if (buttonContains(dedo.x, dedo.y)) { value == 1 ? value = 0 : value = 1; return true; } break; case controlType::CT_SWITCH : if(rectContains(dedo.x,dedo.y)) { bool right = dedo.x > posRect.getCenter().x; if ((bool)value != right) value = right; return true;} break; case controlType::CT_SLIDE : if(rectContains(dedo.x,dedo.y)){ value = (int) ((dedo.x - posRect.x)*100 / posRect.width); return true;} break; default: break; }; interaction 08:38fb.com/RVA.BR 137
  • 140. O QUE ACONTECEU: class src «enumeratio... controlType CT_SWITCH CT_BUTTON CT_SLIDE Controle + id :int + type :controlType + value :int + max :int + min :int + pos :ofPoint + posRect :ofRectangle + radius :float + angle :float + fillSlider(rotRect :cv::RotatedRect) :void + fillSwitch(rotRect :cv::RotatedRect) :void + fillButton(center :cv::Point, radius :float) :void + draw() :void + buttonContains(x :int, y :int) :bool + rectContains(x :int, y :int) :bool + interact(dedo :ofPoint) :bool ofBaseApp ofApp + debugApp :bool + cam :ofVideoGrabber + camHeight :int + camWidth :int + original :ofImage + paperFinder :ofxCv::ContourFinder + warpedPaper :ofImage + verticesInfra :vector<Point2f> + foundInfra :bool + StopToGetInfraPosition :bool + controlFinder :ofxCv::ContourFinder + doControlDetection :bool + grayImg :cv::Mat + canny :cv::Mat + eroded :cv::Mat + dilated :cv::Mat + edgesInput :cv::Mat + edges :cv::Mat + BORDER :int + ALPHA :float + listaDeControles :vector<Controle*> + colorImage :ofxCvColorImage + grayBg :ofxCvGrayscaleImage + grayImage :ofxCvGrayscaleImage + grayDiff :ofxCvGrayscaleImage + bLearnBackground :bool + trackingColorMode :ofxCv::TrackingColorMode + handFinder :ofxCv::ContourFinder + targetColor :ofColor + apontador :ofPoint + setup() :void + update() :void + draw() :void + keyReleased(key :int) :void + trataInfraestrutura() :void + desenhaInfraestrutura(x :int, y :int) :void + encontraControles(source :ofImage) :void + isButton(i :int) :bool + isSwitch(i :int) :bool + isSlider(i :int) :bool + desenhaControles(x :int, y :int) :void + processaInteracao() :void + encontraPontoMaisDistante() :ofPoint + desenhaMao(x :int, y :int) :void + encontraMao(source :ofImage) :void + findForm(poly :ofPolyline&) :string + findForm(poly :T&) :string +type 08:38fb.com/RVA.BR 140
  • 141. class Class Model ofBaseApp ofApp + par :ofxProjAR + setup() :void + update() :void + draw() :void + keyPressed(int) :void + keyReleased(int) :void + mouseMoved(int, int) :void + mouseDragged(int, int, int) :void + mousePressed(int, int, int) :void + mouseReleased(int, int, int) :void + windowResized(int, int) :void + dragEvent(ofDragInfo) :void + gotMessage(ofMessage) :void ofxProjAR + m_infra :ofxPAR_Infra* + m_actuator :ofxPAR_Actuator* + controlManager :ofxPAR_ControlManager + debug :bool - actualState :ofxPAR_State* - stateList :vector<ofxPAR_State*> + ofxProjAR() + ~ofxProjAR() + standardSetup() :void + standardUpdate() :void + standardDraw() :void + setState(AppState) :bool + getActualState() :ofxPAR_State* ofxPAR_Infra + cam :ofVideoGrabber + camHeight :int + camWidth :int + unwarped :ofImage + showVideoFeed :bool + foundInfra :bool + projectorPoints :vector<cv::Point2f> + toProjectorMatrix :cv::Mat + alignmentComplete :bool + projWidth :int + projHeight :int # name :string + ofxPAR_Infra() + ~ofxPAR_Infra() + detect() :void + draw() :void + update() :void + setup() :void + getTransformation(int, int) :cv::Mat + getContours() :ofPolyline + unwarpPoint(ofPoint&, int, int) :ofPoint + getCamera() :ofVideoGrabber + setCamera(ofVideoGrabber) :void + setCamera(int, int) :void + getRawUnwarped() :ofImage + toogleVideoFeed() :void + isInfraFound() :bool + addCalibrationPoints(int, int) :void + resetCalibration() :void + doCalibration() :void + drawProjectionLimits() :void # computeProjectorAlignment() :void # loadProjectorAlignment() :bool # saveProjectorAlignment() :bool # resetProjectorAlignment() :void ofxPAR_Infra_PaperDetector # trackingColorMode :ofxCv::TrackingColorMode # contourFinder :ofxCv::ContourFinder # targetColor :ofColor # thresholdCV :int # contour :ofPolyline # paperImage :cv::Mat # paper :vector<cv::Point> # adaptedToScreenSize :vector<cv::Point> + ofxPAR_Infra_PaperDetector() + ~ofxPAR_Infra_PaperDetector() + draw() :void + detect() :void + calibrate() :void + update() :void + setup() :void + getTransformation(int, int) :cv::Mat + getContours() :ofPolyline + unwarpPoint(ofPoint&, int, int) :ofPoint - configureCV() :void - drawPaperContour() :void - drawPaperContourIn(int, int) :void - unwarp(S&, D&) :void - unwarp(D&) :void - unwarpPointIntern(ofPoint&, int, int) :ofPoint ofxPAR_Actuator + topBackground :ofxCv::RunningBackground + foreground :cv::Mat + ofxPAR_Actuator() + ~ofxPAR_Actuator() + draw() :void + drawDetectorInput(float, float, float, float) :void + detect(T&, S&, ofPolyline&) :bool + detect(cv::Mat&, ofPolyline&) :bool + getActuatorPoint() :ofPoint + setActuatorThresold(int) :void ofxPAR_HandDetector - topFinder :ofxCv::ContourFinder - sideFinder :ofxCv::ContourFinder - topFilled :cv::Mat - contour :ofPolyline - fingers :vector<size_t> - fingerPoint :ofPoint - foundFingerInLast :bool - fingerThreshold :int - fAlpha :float - elem2x2 :cv::Mat - elem3x3 :cv::Mat - useCenter :cv::Point {readOnly} + ofxPAR_HandDetector() + ~ofxPAR_HandDetector() + draw() :void + drawDetectorInput(float, float, float, float) :void + detect(cv::Mat&, ofPolyline&) :bool + getActuatorPoint() :ofPoint + setActuatorThresold(int) :void - findFingers(ofPolyline&) :bool - getFingerPoint() :ofPoint ofxPAR_ControlManager + doControlDetection :bool + accent1 :ofColor {readOnly} + accent2 :ofColor {readOnly} + finder :ofxCv::ContourFinder + grayImg :cv::Mat + canny :cv::Mat + eroded :cv::Mat + dilated :cv::Mat + edgesInput :cv::Mat + edges :cv::Mat + controlList :vector<ofxPAR_Control *> + lastInputPoint :ofPoint + BORDER :int + ALPHA :float + ofxPAR_ControlManager() + ~ofxPAR_ControlManager() + setup() :void + reset() :void + drawDetectorInput(float, float, float, float) :void + detect(T&) :void + detect(cv::Mat) :void + toogleControlDetection() :void + processInteraction(ofPoint&) :void + drawControls() :void + drawDebug() :void + assignControls() :void + isButton(size_t) :bool + isSlider(size_t) :bool + isSwitch(size_t) :bool ofxPAR_Control # id :int # name :string # value :int # color :ofColor # controlType :ControlType # selected :bool + ofxPAR_Control() + ~ofxPAR_Control() + setId(int) :void + draw() :void + setColor(ofColor&) :void + contains(float, float) :bool + contains(ofPoint&) :bool + onInteraction(float, float) :bool + onInteraction(ofPoint&) :bool + setSelection(bool) :void + isSelected() :bool + getValue() :int ofxPAR_C_Button - cx :float - cy :float - radius :float - active :bool - entered :bool + ofxPAR_C_Button() + ~ofxPAR_C_Button() + ofxPAR_C_Button(float, float, float) + draw() :void + contains(float, float) :bool + onInteraction(float, float) :bool + operator==(ofxPAR_C_Button&) :bool + operator!=(ofxPAR_C_Button&) :bool ofxPAR_C_Slider - value :float + ofxPAR_C_Slider() + ~ofxPAR_C_Slider() + ofxPAR_C_Slider(cv::RotatedRect&) + draw() :void + onInteraction(float, float) :bool ofxPAR_C_Switch - active :bool + ofxPAR_C_Switch() + ~ofxPAR_C_Switch() + ofxPAR_C_Switch(cv::RotatedRect&) + draw() :void + onInteraction(float, float) :bool ofxPAR_State + stateType :AppState + name :string + app :ofxProjAR* + ofxPAR_State() + ~ofxPAR_State() + draw() :void + update() :void ofxPAR_State_Idle + ofxPAR_State_Idle() + ~ofxPAR_State_Idle() + draw() :void + update() :void ofxPAR_State_InfraSetup + ofxPAR_State_InfraSetup() + ~ofxPAR_State_InfraSetup() + draw() :void + update() :void ofxPAR_State_Play + ofxPAR_State_Play() + ~ofxPAR_State_Play() + draw() :void + update() :void - reprojectPaper() :void ofxPAR_Control_Rectangular # angle :float # rect :ofRectangle + ofxPAR_Control_Rectangular() + ~ofxPAR_Control_Rectangular() + ofxPAR_Control_Rectangular(cv::RotatedRect&) + draw() :void + contains(float, float) :bool + operator==(ofxPAR_Control_Rectangular&) :bool + operator!=(ofxPAR_Control_Rectangular&) :bool # alignPoint(float, float) :ofVec2f +app IDEAL: 08:38fb.com/RVA.BR 141
  • 142. • Existe um framework em C++ chamado openFrameworks. Novo player interessante: Unreal Engine + Blueprints (AWESOME) • openFrameworks pode ser expandido com componentes da comunidade, chamados addons. • Com ele é possível controlar o Arduino (em C++). • O Arduino pode se transformar numa interface de dados usando a lib Firmata. • Arduino é barato e fácil de usar. Um possível software para desenhar circuitos é o Fritzing •Realidade Aumentada é só uma interface de acesso aos elementos virtuais. 08:38fb.com/RVA.BR 142
  • 143. • openCV é uma biblioteca de visão computacional. • Com openCV podemos rastrear cores, diferenças de imagens, etc. • Pense se sua aplicação pode usar equipamentos simples! • Quanto mais simples e do cotidiano do usuário melhor. • Visão computacional nem sempre é um resultado por si. Ideal são soluções hibridas. • Adicionando elementos de interação físicos (sensores e atuadores) à Realidade Aumentada, que fazem a troca bidirecional de informação cria-se Realidade Cruzada. 08:38fb.com/RVA.BR 143
  • 145. Dúvidas: christophercerqueira@gmail.com Site: http://cscerqueira.com.br Facebook: http://fb.com/RVA.BR Para maiores dúvidas: INPE – SJC Prédio Satélite Sala 95 Drª. Ana Maria Ambrosio Msc. Christopher Cerqueira aluno doutorado Dr. Claudio Kirner 08:38fb.com/RVA.BR 145