Cette semaine je me suis essayé au motion tracking avec Processing.
En fait il est assez facile d'utiliser sur un macbook la webcam intégrée, notament les I/O gérées par Quicktime. (d'ou coup le code est aussi portable sous Windows :) ).
Pour ma part, en implémentant une classe Cible, j'ai pu "traquer" un pixel de couleur donné et raffraichir la position de ma cible s'affichant a l'écran. Le résultat est assez bluffant même s'il peut être facilement amélioré. En fait mon code est plus un proof of concept, n'étant même pas sur que mon code et ma manière de procéder fonctionnerait.
Je ne sais pas si le tracking se fait habituellement comme cela, mais j'ai intuitivement essayé de "balayer" chaque pixel de mon canvas, si je tombe sur un pixel de couleur voulu, par un habil calcul mathématique je trouve les coordonnées de ce point (loooooooool) et le donne ces coordonnées à ma cible, qui se repositionnera en temps voulu ^^. La capture vidéo est assez facile à comprendre, puisqu'en fait on instancie un objet de classe Capture qui va recevoir a chaque "tic" d'horloge une image raffraichie en provenance de la webcam, le tracking s'effectue sur le canvas, et non sur l'objet myCapture.
Dans mon onglet principal, je code le corps de l'application.
D'abord quelques déclarations et import:
Cette fonction sert à raffraichir notre objet de capture vidéo:
La fonction de tracking, qui pour chaque pixel du canvas, va comparer sa couleur, ici si le pixel sur lequel on itère est blanc, alors sa position est envoyé à la cible:
La fonction principale, appelée à chaque "tic" d'horloge, et qui permet de contrôler le déroulement de notre application:
Et ma bete classe Cible qui servira à iconer le point que je tracke:
En fait il est assez facile d'utiliser sur un macbook la webcam intégrée, notament les I/O gérées par Quicktime. (d'ou coup le code est aussi portable sous Windows :) ).
Pour ma part, en implémentant une classe Cible, j'ai pu "traquer" un pixel de couleur donné et raffraichir la position de ma cible s'affichant a l'écran. Le résultat est assez bluffant même s'il peut être facilement amélioré. En fait mon code est plus un proof of concept, n'étant même pas sur que mon code et ma manière de procéder fonctionnerait.
Je ne sais pas si le tracking se fait habituellement comme cela, mais j'ai intuitivement essayé de "balayer" chaque pixel de mon canvas, si je tombe sur un pixel de couleur voulu, par un habil calcul mathématique je trouve les coordonnées de ce point (loooooooool) et le donne ces coordonnées à ma cible, qui se repositionnera en temps voulu ^^. La capture vidéo est assez facile à comprendre, puisqu'en fait on instancie un objet de classe Capture qui va recevoir a chaque "tic" d'horloge une image raffraichie en provenance de la webcam, le tracking s'effectue sur le canvas, et non sur l'objet myCapture.
Dans mon onglet principal, je code le corps de l'application.
D'abord quelques déclarations et import:
import processing.video.*;Ceci est la fonction qui serra lue une fois par Processing, elle sert à initialiser nos variables:
PFont maFont;
Capture myCapture;
Cible maCible;
void setup()
{
size(640, 480);
Point p = new Point(width / 2, height / 2);
int[] t = new int[3];
t[0] = 255;
t[1] = 0;
t[2] = 0;
maCible = new Cible(p, t);
myCapture = new Capture(this, width, height, 30);
}
Cette fonction sert à raffraichir notre objet de capture vidéo:
void captureEvent(Capture myCapture) {
myCapture.read();
}
La fonction de tracking, qui pour chaque pixel du canvas, va comparer sa couleur, ici si le pixel sur lequel on itère est blanc, alors sa position est envoyé à la cible:
void tracking() {
int[] t = maCible.getColor();
// dans un premier temps je traque le point que je veux
loadPixels();
for(int i = 0; i < width * height; i++) {
if(pixels[i] == color(255, 255, 255)) { // <-- couleur du pt a tracker
Point p = new Point(i % width, i / width);
maCible.setPos(p);
}
}
updatePixels();
// et je dessine la cible
maFont = loadFont("SynchroLET-12.vlw");
textFont(maFont);
Point pos = maCible.getPos();
stroke(t[0], t[1], t[2]);
strokeWeight(1);
line(pos.x - 30, pos.y - 30, pos.x - 20, pos.y - 30);
line(pos.x - 30, pos.y - 30, pos.x - 30, pos.y - 20);
line(pos.x + 30, pos.y - 30, pos.x + 20, pos.y - 30);
line(pos.x + 30, pos.y - 30, pos.x + 30, pos.y - 20);
line(pos.x - 30, pos.y + 30, pos.x - 30, pos.y + 20);
line(pos.x - 30, pos.y + 30, pos.x - 20, pos.y + 30);
line(pos.x + 30, pos.y + 30, pos.x + 20, pos.y + 30);
line(pos.x + 30, pos.y + 30, pos.x + 30, pos.y + 20);
fill(t[0], t[1], t[2]);
text(pos.x + " - " + pos.y, pos.x + 35, pos.y + 40);
}
La fonction principale, appelée à chaque "tic" d'horloge, et qui permet de contrôler le déroulement de notre application:
void draw() {
image(myCapture, 0, 0);
tracking();
println(get(width / 2, height / 2));
}
Et ma bete classe Cible qui servira à iconer le point que je tracke:
import java.awt.Point;
public class Cible {
private Point pos;
private int[] couleur;
public Cible() {
pos = new Point();
couleur = new int[3];
for(int i = 0; i < 3; i++) {
couleur[i] = 0;
}
}
public Cible(Point pos, int[] couleur) {
this.pos = pos;
this.couleur = new int[3];
for(int i = 0; i < 3; i++) {
this.couleur[i] = couleur[i];
}
}
public void setPos(Point pos) {
this.pos = pos;
}
public Point getPos() {
return pos;
}
public void setColor(int[] couleur) {
this.couleur = couleur;
}
public int[] getColor() {
return couleur;
}
// marche pas, la classe est presque pur java
// public void afficheToi() {
// stroke(couleur[0], couleur[1], couleur[2]);
// line(pos.x - 30, pos.y - 30, pos.x - 20, pos.y - 30);
// line(pos.x - 30, pos.y - 30, pos.x - 30, pos.y - 20);
// line(pos.x + 30, pos.y - 30, pos.x + 20, pos.y - 30);
// line(pos.x + 30, pos.y - 30, pos.x + 30, pos.y - 20);
// line(pos.x - 30, pos.y + 30, pos.x - 30, pos.y + 20);
// line(pos.x - 30, pos.y + 30, pos.x - 20, pos.y + 30);
// line(pos.x + 30, pos.y + 30, pos.x + 20, pos.y + 30);
// line(pos.x + 30, pos.y + 30, pos.x + 30, pos.y + 20);
// }
public String toString() {
return "Cible:[pos=" + pos.x + ", " + pos.y + ", couleur=(" + couleur[0] + ", " + couleur[1] + ", " + couleur[2] + ")";
}
}
Aucun commentaire:
Enregistrer un commentaire