Augmented Reality Motion Detection: AR Bubble Game with Processing and OpenCV

Hallo.. Selamat datang di A.R.T - setelah kemarin belajar Modelling dan Image Processing dengan VRML. kali ini A.R.T bawa tutorial yang lebih "Wahhh.." lagi. saya kemarin sempat searching beberapa tutorial AR dan tidak sengaja ketemu tutorial Motion Detection dengan Processing dan OpenCV dari si Evil Genius bernama Andy Best. tutorialnya bisa anda temukan disini >> http://andybest.net/2009/02/processing-opencv-tutorial-2-bubbles/


tapi sayang, tutorialnya tidak begitu jelas. maksudnya dia tidak menjelaskan langkah-langkah menginstal Library OpenCV, dia hanya memberikan source code ARnya. jadi saat programnya dijalankan, selalu ada Warning Error "OpenCV.dll not Found" padahal file library tersebut saya cek ada tapi tidak bisa dibaca oleh Processing, saya juga baca di komentar pembacanya, ada juga yang mengalami hal yang sama, tapi tidak ada penjelasan dari Andy untuk mengatasi masalah ini.

akhirnya, saya googling dan menemukan forum processing, ternyata banyak yang mengalami hal yang sama. setelah saya baca diskusinya. akhirnya saya menemukan masalahnya, kita harus menginstall OpenCV_1.1pre1a. setelah diinstal, restart komputer dan akhirnya bisa jalan. well, itu sedikit pengalaman dari saya, oke langsung saja tutorialnya biar kalian bisa mengikutinya.

Note: saya menggunakan Windows XP Sp3 untuk Menjalankan AR ini. 

1. Download Processing 1.2.1 (*saya belum coba di Processing 1.5.1)
A. Instalasi Processing 1.2.1 
saya coba pandu instalasinya terlebih dahulu. dimulai dari Processing 1.2.1 - setelah didownload ekstrak processing 1.2.1 di drive harddisk anda mana saja. kemudian buat shortcut Processing di dekstop biar mudah di aksesnya.















selanjutnya, buka folder processing 1.2.1 dan bukalah processing.exe - tunggu sampai loading selesai. jika layar sketch telah terbuka, coba cek di My Document maka anda akan mendapatkan folder baru bernama processing - folder ini otomatis dibuat, disaat pertama kali anda menjalankan processing.













next, buka folder processing di my document dan buatlah folder baru bernama libraries












B. Instalasi GSVideo 0.8
Instalasi Processing selesai. sekarang, kita install library GSVideo 0.8 - saya anggap kalian sudah mendownload library tersebut. sekarang tinggal ekstrak di dalam folder C:\Documents and Settings\Your Name\My Documents\Processing\libraries














C. Instalasi OpenCV_1.1pre1a 
nah di bagian sini yang kadang suka salah. saya langsung saja coba pandu yah. double clik OpenCV_1.1pre1a kemudian anda akan mendapatkan Welcome Session, cukup klik Next saja. saya akan kasih tau nanti dibagian yang paling penting.















bagian paling terpenting saat instalasi adalah, JANGAN LUPA BERI TANDA CHECKLIST DI PATH SEBELUM DIINSTAL. (*maaf capslock, biar gak salah :p)



















selanjutnya download Open CV Library for Processing disini - setelah didownload. ekstrak dan copy paste Open CV library ke folder libraries processing di My Document.
















instalasi library selesai. selanjutnya kita ngeCoding. buka Processing 1.2.1 anda, dan copy coding dibawah ini. kalo mau di ketik biar paham juga gpp.. :p

import hypermedia.video.*;          //  Imports the OpenCV library

OpenCV opencv;                      //  Creates a new OpenCV object
PImage movementImg;                 //  Creates a new PImage to hold the movement image
int poppedBubbles;                  //  Creates a variable to hold the total number of popped bubbles
ArrayList bubbles;                  //  Creates an ArrayList to hold the Bubble objects
PImage bubblePNG;                   //  Creates a PImage that will hold the image of the bubble
PFont font;                         //  Creates a new font object

void setup()
{
  size ( 640, 480 );                      //  Window size of 640 x 480
  opencv = new OpenCV( this );            //  Initialises the OpenCV library
  opencv.capture( 640, 480 );             //  Sets the capture size to 640 x 480
  movementImg = new PImage( 640, 480 );   //  Initialises the PImage that holds the movement image
  poppedBubbles = 0;                  

  bubbles = new ArrayList();              //  Initialises the ArrayList

  bubblePNG = loadImage("bubble.png");    //  Load the bubble image into memory
  font = loadFont("Serif-48.vlw");        //  Load the font file into memory
  textFont(font, 32);                    

}

void draw()
{
  bubbles.add(new Bubble( (int)random( 0, width - 40), -bubblePNG.height, bubblePNG.width, bubblePNG.height));   //  Adds a new bubble to the array with a random x position

  opencv.read();                              //  Captures a frame from the camera  
  opencv.flip(OpenCV.FLIP_HORIZONTAL);        //  Flips the image horizontally
  image( opencv.image(), 0, 0 );              //  Draws the camera image to the screen
  opencv.absDiff();                           //  Creates a difference image
 
  opencv.convert(OpenCV.GRAY);                //  Converts to greyscale
  opencv.blur(OpenCV.BLUR, 3);                //  Blur to remove camera noise
  opencv.threshold(20);                       //  Thresholds to convert to black and white
  movementImg = opencv.image();               //  Puts the OpenCV buffer into an image object

  for ( int i = 0; i < bubbles.size(); i++ ){    //  For every bubble in the bubbles array
    Bubble _bubble = (Bubble) bubbles.get(i);    //  Copies the current bubble into a temporary object
 
    if(_bubble.update() == 1){                  //  If the bubble's update function returns '1'
      bubbles.remove(i);                        //  then remove the bubble from the array
      _bubble = null;                           //  and make the temporary bubble object null
      i--;                                      //  since we've removed a bubble from the array, we need to subtract 1 from i, or we'll skip the next bubble
 
  }else{                                        //  If the bubble's update function doesn't return '1'
      bubbles.set(i, _bubble);                  //  Copys the updated temporary bubble object back into the array
      _bubble = null;                           //  Makes the temporary bubble object null.
    }
  }

  opencv.remember(OpenCV.SOURCE, OpenCV.FLIP_HORIZONTAL);    //  Remembers the camera image so we can generate a difference image next frame. Since we've
                                                             //  flipped the image earlier, we need to flip it here too.
  text("Bubbles popped: " + poppedBubbles, 20, 40);          //  Displays some text showing how many bubbles have been popped

}

class Bubble
{

  int bubbleX, bubbleY, bubbleWidth, bubbleHeight;    //  Some variables to hold information about the bubble

  Bubble ( int bX, int bY, int bW, int bH )           //  The class constructor- sets the values when a new bubble object is made
  {
    bubbleX = bX;
    bubbleY = bY;
    bubbleWidth = bW;
    bubbleHeight = bH;
  }

  int update()      //   The Bubble update function
  {
    int movementAmount;          //  Create and set a variable to hold the amount of white pixels detected in the area where the bubble is
    movementAmount = 0;
 
    for( int y = bubbleY; y < (bubbleY + (bubbleHeight-1)); y++ ){    //  For loop that cycles through all of the pixels in the area the bubble occupies
      for( int x = bubbleX; x < (bubbleX + (bubbleWidth-1)); x++ ){
     
        if ( x < width && x > 0 && y < height && y > 0 ){             //  If the current pixel is within the screen bondaries
          if (brightness(movementImg.pixels[x + (y * width)]) > 127)  //  and if the brightness is above 127 (in this case, if it is white)
          {
            movementAmount++;                                         //  Add 1 to the movementAmount variable.
          }
        }
      }
    }
 
    if (movementAmount > 5)               //  If more than 5 pixels of movement are detected in the bubble area
    {
      poppedBubbles++;                    //  Add 1 to the variable that holds the number of popped bubbles
      return 1;                           //  Return 1 so that the bubble object is destroyed
 
   }else{                                 //  If less than 5 pixels of movement are detected,
      bubbleY += 10;                      //  increase the y position of the bubble so that it falls down
   
      if (bubbleY > height)               //  If the bubble has dropped off of the bottom of the screen
      {  return 1; }                      //  Return '1' so that the bubble object is destroyed
   
      image(bubblePNG, bubbleX, bubbleY);    //  Draws the bubble to the screen
      return 0;                              //  Returns '0' so that the bubble isn't destroyed
    }
 
  }

}
maaf agak berantakan.. karena keterbatasan Blogger.. hehe. sekarang simpan file dengan nama bubble_game.pde. selanjutnya kita akan memasukkan objek Bubblenya dalam bentuk bubble.png dan juga Serif-48.vlw, caranya drag bubble tersebut ke processing anda. nanti dia secara otomatis didalam folder bubble_game di folder processing di my document, dia akan membentuk folder baru bernama data.













nah sekarang klik Play, maka akan ada game bubble dengan tehnik motion detection. arahkan tangan anda untuk memecahkan bubble-bubble tersebut, dan posting disini berapa skor yang anda dapat yah. :)


















oke guys, thanks for reading my tutorial. dan jika mau source code jadinya, silahkan klik link ini untuk full source code. tinggal di copy paste saja di folder processing anda. selamat mencoba dan semoga berhasil.. bye.. bye.. bye..