• fullscreen
  • dmx.pde
  • optical_dmx_controller.pde
  • tracker.pde
  • // Based on Code from tinker.it
    // https://code.google.com/p/tinkerit/wiki/SerialToDmx
    
    class dmx {
    
      Serial myPort;
    
      dmx(Serial port) {
        myPort = port;
      }
    
      void setChannel(int channel, int value) {
        
        // Die Parameter werden in Text konvertiert: bei 132c45w ist 132 der Kanal und 45 der Wert
        // dann wird der text an den Arduino geschikt
        // Convert the parameters into a message of the form: 123c45w where 123 is the channel and 45 is the value
        // then send to the Arduino
        myPort.write( str(channel) + "c" + str(value) + "w" );
      }
    }
    
    
    //
    // Benedikt Frank, Arduino-Kurs SS10, Dozent: Jochen Koubek, Universität Bayreuth
    //
    // Set-Up:
    //
    // Whiteboard mit 4 farbigen Magneten (rot, grün, blau, gelb)
    // gefilmt von einer Webcam
    //
    // Whiteboard with 4 colored Magnets (red, green, blue, yellow)
    // filmed by a wabcam.
    
    
    import codeanticode.gsvideo.*;
    import processing.serial.*;
    
    
    GSPipeline pipe;
    Serial myPort;
    
    //Bildschirmgröße
    //Screensize
    
    int w=640;
    int h=480;
    
    // Ränder, in denen die Punkte nicht gezählt werden
    // Borders 
    
    int borderx=65;
    int bordery=36;
    
    // Faktoren, um die Bildschirmgröße auf DMX-Werte umzurechnen
    // factors to convert screen size to dmx-value
    
    float fx=0.5;
    float fy=0.625;
    
    // DMX-Kanäle für RGB
    // DMX-Channels for RGB
    
    int r=2;
    int g=3;
    int b=4;
    
    // Werte für die DMX-Kanäle 
    // Values of DMX-Channels
    
    int rv1;
    int gv1;
    int bv1;
    
    int rv2;
    int gv2;
    int bv2;
    
    // Werte für zusätzliche Steuerung
    // Values for extra contoller
    
    int cv1;
    int cv2;
    
    //Timer
    
    int timer;
    int timerlength = 1000;
    boolean timerswitch;
    
    //Strobotimer
    
    int strobo;
    int strobolength = 42;
    int strobocount;
    boolean stroboswitch;
    
    
    tracker t;
    dmx led;
    
    
    void setup() {
    
      size(w,h);
    
      // Bild von der Webcam holen
      // Get picture from Webcam
      
      println(Serial.list()); // Zeigt die vorhandenen seriellen Anschlüsse / shows available serial ports on the system
      myPort = new Serial(this, Serial.list()[0], 9600);
      pipe = new GSPipeline(this, "v4l2src device=/dev/video1 ! ffmpegcolorspace ! video/x-raw-rgb, width=640, height=480, bpp=32, depth=24");
    
      t = new tracker (pipe);
      led =new dmx(myPort);
      smooth();
    
      rv1=0;
      gv1=0;
      bv1=0;
      rv2=0;
      gv2=0;
      bv2=0;
    
      cv1=0;
      cv2=0;
    
      timer = millis();
      timerswitch = true;
    
      stroboswitch = true;
    }
    
    
    void draw() {
    
      //neues Bild holen
      //grab new frame
      
      if (pipe.available() == true) {
        pipe.read();
        
        //Bild anzeigen
        //display image
        
        image(pipe, 0, 0 );
      }
    
      pipe.loadPixels();
    
      t.configure();
      t.track();
    
    
      // Farben finden
      // track colors
      
      // Farbe 1 - x-Wert
      // color 1 - x-value
    
      if (t.pos(0,"rot")>=borderx && t.pos(0,"rot")<=w-borderx) {
        rv1 = int(t.pos(0,"rot")*fx);
      }
    
      if (t.pos(0,"gruen")>=borderx && t.pos(0,"gruen")<=w-borderx) {
        gv1 = int(t.pos(0,"gruen")*fx);
      } 
    
      if (t.pos(0,"blau")>=borderx && t.pos(0,"blau")<=w-borderx) {
        bv1 = int(t.pos(0,"blau")*fx);
      }
    
      if (t.pos(0,"gelb")>=borderx && t.pos(0,"gelb")<=w-borderx) {
        cv1 = int(t.pos(0,"gelb")*fx);
      }
    
    
      // Farbe 2 - y-Wert
      // color 2 - y-value
      
      if (t.pos(1,"rot")>=borderx && t.pos(1,"rot")<=w-borderx) {
        rv2 = int(t.pos(1,"rot")*fx);
      }
    
      if (t.pos(1,"gruen")>=borderx && t.pos(1,"gruen")<=w-borderx) {
        gv2 = int(t.pos(1,"gruen")*fx);
      }
    
      if (t.pos(1,"blau")>=borderx && t.pos(1,"blau")<=w-borderx) {
        bv2 = int(t.pos(1,"blau")*fx);
      }
    
      if (t.pos(1,"gelb")>=borderx && t.pos(1,"gelb")<=w-borderx) {
        cv2 = int(t.pos(1,"gelb")*fx);
      }
    
    
      // Timer
    
      timerlength = cv1 * 20;
    
      if (millis() - timer > timerlength) {
    
        timer = millis();
    
        if (timerswitch == true) {
          timerswitch = false;
        } 
        else {
          timerswitch = true;
        }
      }
    
    
      //Strobo
    
      if (millis() - strobo > strobolength) {
    
        strobo = millis();
        strobocount ++;
    
        if (stroboswitch == false && strobocount > cv2/12) {
          stroboswitch = true;
          strobocount = 0;
        } 
        else {
          stroboswitch = false;
        }
      }
    
    
      // Strobo geht aus, wenn der Kontroll-Magnet ganz unten ist
      // Strobo is off, when controll-magnet is at the bottom
    
      if (stroboswitch == false && cv2 < 190) {
        led.setChannel(r,0);
        led.setChannel(g,0);
        led.setChannel(b,0);
      } 
      else {
    
        // Farbwechsel
        // change of colors
    
        if (timerswitch == true) {
    
          led.setChannel(r,rv1);
          led.setChannel(g,gv1);
          led.setChannel(b,bv1);
        }
    
        else {
    
          led.setChannel(r,rv2);
          led.setChannel(g,gv2);
          led.setChannel(b,bv2);
        }
      }
    }
    
    
    // Basiert auf dem Farberkennungs-Algorythmus von Daniel Shiffman
    // Based on a tracking algorithm by Daniel Shiffman
    // http://www.learningprocessing.com/examples/chapter-16/example-16-11/
    
    class tracker {
    
      color trackRed;
      color trackGreen;
      color trackBlue;
      color trackYellow;
      color trackColor;
      color[] colors;
      public int[][] positions;
      float worldRecord;
      GSPipeline pipe;
    
      tracker (GSPipeline pipel) {
        pipe = pipel;
        colors = new color[4];
        positions = new int[2][4];
      }
    
    
      // Konfiguration der Farberkennung
      // Configuration of color tracking
      // 
      // Funktion: Taste für einzelne Farbe (r,g,b,y) gedrückt halten
      // und mit der Maus auf den jeweiligen Farbpunkt im Bild klicken.
      // Function: press key for the color (r,g,b,y) and click the point
      // with the mouse on the screen
    
      void configure() {
    
        if (keyPressed) {
          if (key == 'r' || key == 'R') {
            if (mousePressed == true) {
              // Farbe, die die Maus anklickt, in der Variable trackColor speichern
              // Save color where the mouse is clicked in trackColor variable
              int loc = mouseX + mouseY*pipe.width;
              trackRed = color(pipe.pixels[loc]);
            }
          }
    
          if (key == 'g' || key == 'G') {
            if (mousePressed == true) {
              // Farbe, die die Maus anklickt, in der Variable trackColor speichern
              // Save color where the mouse is clicked in trackColor variable
              int loc = mouseX + mouseY*pipe.width;
              trackGreen = color(pipe.pixels[loc]);
            }
          }
    
          if (key == 'b' || key == 'B') {
            if (mousePressed == true) {
              // Farbe, die die Maus anklickt, in der Variable trackColor speichern
              // Save color where the mouse is clicked in trackColor variable
              int loc = mouseX + mouseY*pipe.width;
              trackBlue = color(pipe.pixels[loc]);
            }
          }
    
          if (key == 'y' || key == 'Y') {
            if (mousePressed == true) {
              // Farbe, die die Maus anklickt, in der Variable trackColor speichern
              // Save color where the mouse is clicked in trackColor variable
              int loc = mouseX + mouseY*pipe.width;
              trackYellow = color(pipe.pixels[loc]);
            }
          }
        }
    
        colors[0]=trackRed;
        colors[1]=trackGreen;
        colors[2]=trackBlue;
        colors[3]=trackYellow;
      }
    
      // Funktion zur Farberkennung
      // Function for color tracking
    
      void track() {
    
        worldRecord = 500;
    
        for (int c=0; c < colors.length; c++) {
    
          trackColor = colors[c];
    
          // Loop, der durch jedes Pixel läuft
          // Begin loop to walk through every pixel
          for (int x = 0; x < pipe.width; x ++ ) {
            for (int y = 0; y < pipe.height; y ++ ) {
              int loc = x + y*pipe.width;
              // Aktuelle Farbe abfragen
              // What is current color
              color currentColor = pipe.pixels[loc];
              float r1 = red(currentColor);
              float g1 = green(currentColor);
              float b1 = blue(currentColor);
              float r2 = red(trackColor);
              float g2 = green(trackColor);
              float b2 = blue(trackColor);
    
              // Mit dem euklidischem Abstand Farben vergleichen  (dist()-Funktion)
              // Using euclidean distance to compare colors (dist()-function)
              float d = dist(r1,g1,b1,r2,g2,b2);
    
              // Wenn die aktuelle Farbe der gesuchten Farbe mehr ähnelt als
              // die näheste Farbe, dann wird die Position und die Differenz
              // gespeichert
              // If current color is more similar to tracked color than
              // closest color, save current location and current difference
              if (d < worldRecord) {
                worldRecord = d;
                positions[0][c] = x;
                positions[1][c] = y;
              }
            }
          }
    
          // Wir betrachten die Farbe als gefunden, wenn die Distanz weniger als 50 beträgt.
          // Die Grenze von 50 ist frei wählbar und kann verändert werden, je nachdem wie
          // genau die Suche sein soll.
          // We only consider the color found if its color distance is less than 50. 
          // This threshold of 50 is arbitrary and you can adjust this number depending
          // on how accurate you require the tracking to be.
          if (worldRecord < 50) { 
    
            // Malt einen Kreis um das erkannte Pixel
            // Draw a circle at the tracked pixel
            fill(trackColor);
            strokeWeight(4.0);
            stroke(0);
            ellipse(positions[0][c],positions[1][c],16,16);
          }
        }
      }
    
      // Funktion zur Ausgabe der Position
      // Function to return positions
    
      int pos(int axis, String tcolor) {
    
        int a=axis;
        String c= tcolor;
        int b=0;
    
        // Fehlermeldung bei falscher Eingabe
        // Error if entry is wrong
        if (a!=0 && a!=1) {
          println("Flasche Postionsangabe. Nur '0' für 'x' und '1' für 'y' sind gültige Werte.");
        }
    
    
        if (c.equals("rot")||c.equals("red")) {
          b=0;
        } 
        if (c.equals("gruen")||c.equals("green")) {
          b=1;
        } 
        if (c.equals("blau")||c.equals("blue")) {
          b=2;
        } 
        if (c.equals("gelb")||c.equals("yellow")) {
          b=3;
        }
    
        return positions[a][b];
      }
    }
    
    

    code

    tweaks (0)

    about this sketch

    This sketch is running as Java applet, exported from Processing.

    license

    advertisement

    Benedikt Frank

    Optical DMX-Controller / Optische DMX-Steuerung

    Add to Faves Me Likey@! 1
    You must login/register to add this sketch to your favorites.

    Prototype for the course "digital media: arduino" at the University of Bayreuth in summer 2010. Arduino sends the DMX-signal to a LED-PAR-Headlight. Color-tracking and the change of light is controlled by processing.

    Prototyp für das Seminar "Digitale Medien: Arduino" an der Uni Bayreuth, Sommersemester 2010. Der Arduino sendet das DMX-Signal an den LED-Scheinwerfer. Bilderkennung und Farbwechsel werden von Processing gesteuert.

    Needs the SerialToDmx-Code running on the Arduino!
    Der SerialToDmx-Code muss auf dem Arduino laufen!
    (http://goo.gl/rWUCY)

    Demo video: http://goo.gl/9jIbj

    You need to login/register to comment.