Saturday, October 22, 2011

Python Radyo

Internet'ten bedava radyo dinleyebilmek icin bazi sayfalar var, fakat hepsine HTML bazli girip, belli yerlere tiklamak, beklemek, vs. gibi isler cok ugrastirici olabiliyor. Python bazli bir program yazilmis, kodlar acik, programi komut satirindan baslatiyorsunuz, bir suru kanal icinden istediginiz seciyorsunuz, alet arka planda o kanaldaki muzigi calan HTML sayfalarina baglanip oradan gelen muzigi canli olarak aktariyor (streaming). Kodlar surada:

Github

Bazi puf noktalar: Radyoyu baslatabilmek icin komut satiri tam ekran (fullscreen) olmali, biz o isi otomatik yapmak icin Ubuntu'da bir ikon yarattik, ve ikon gerekli xterm penceresini gerektigi sekilde baslatiyor. Komut soyle:

xterm -fn *-fixed-*-*-*-20-* -maximize -e "python [DIZIN]/jspricke-radio-6956368/radio.py"

Ayrica, birkac kez kanal degistirince program takilabiliyor, ama bu pek onemli degil, 24/7 islemesi gereken bir program degil zaten, kapatip acinca buyuk bir ihtimalle tekrar islemeye baslayacaktir.

Thursday, October 20, 2011

Otonom Arabalar

Sebastian Thrun ve takiminin Google icin tasarladiklari kendi kendine giden arabanin yazilim, YZ yapisi hakkinda bazi ilginc bilgiler. Video'ya gore arabanin kullandigi ana algilayicisi lazer, ve bu lazer ile arabanin 360 derece etrafi gozleniyor, sadece gorsel girdi ile yetinilmemis. Bilindigi gibi lazer algilayici direk bir uzaklik bilgisi verir. Neyse, tum bu bilgiler ile SLAM isletiliyor ve etrafin haritasi cikartiliyor. Sonra bu haritaya "uymayan", onun disinda kalan, yani sabit durmayan objeler surekli takip ediliyor, insan, bisiklet, diger arabalar, vs gibi.

Monday, October 17, 2011

EPUB -> PDF

EPub dosyalarini PDF'e cevirmek icin program: epub2pdf. Java bazli yazilmis, binary zip dosyasini kullanmak daha iyi.

Wednesday, October 12, 2011

Oyun Programini Oynayan Program - FPS Play

Robot konularinda teorilerin test edilmesi icin simulatorler faydali araclar, grafikleme teknikleri cok ilerledi ve oyun icindeki dunya dis dunyaya benzemeye basladi. Robotlari kontrol eden kodlar bu tur sanal ortamlarda test edilmeye baslandi.

Bogazici CmpE 565 dersinde mesela Unreal Tournament adindaki 1SG (Birinci Sahis Gozunden -FPS-) oyunu uzerine kurulmus USARSim yapisini odevde kullanmistik, bu ortamda disaridan yazilimlarin baglanip 3D oyun ortamindaki sanal robotlarin oyun icindeki kontrolu mumkun oluyor. USARSim'de oyun icindeki fiziksel dunya yapisi, yollar, engeller, agaclar, vs, goruntu, uzaklik bilgileri sanal algilayicilar uzerinden disari aktarilabilmekteydi. Bu bilgiyi ve kontrolu saglamak aslinda 1SG oyunlari icin kolay, grafikleme amaclari icin zaten o bilgiye sahipler, sadece bir arayuz ile disari aktarmalari gerekiyor. UT ve USARSim bu arayuzu sagliyor.

Ilginc ek bir yontem su olabilir: Bir 1SG oyununu masaustumuzde ufaltilmis bir pencerede kosturdugumuz dusunelim. Eger masaustumuzun ekran goruntusunu (screenshot) alabilirsek, ki bu kolay bir istir, o zaman oyun penceresinde olanlarin grafigini alabiliriz. Oyuncuyu kontrol etmek icin ise oyuna aynen gercek bir oyuncunun yapacagi gibi tus, ve mouse tiklamalari, hareketlerini yollayabiliriz.

Bu fikirden hareketle fps-play adli bir proje baslattik. Test icin kullandigimiz oyun populer Quake grafik motorunu kullanan bedava UrbanTerror 1SG oyunudur. Oyun pencerede baslayinca Python bazli kodlar gtk.gdk.Pixbuf kullanarak surekli olarak ekranin belli bir bolumunun "fotografini cekiyor", ve bir dongu icinde bu fotograflar oyuncunun bakisini disari aktariyor. Bu ardi ardina fotograflar OpenCV kutuphanesi ile imaj isleme algoritmalarina tabi tutularak, imaj ve arkasindan yapay zeka hesaplarina tabi tutalabilir, etrafinin haritasini cikarmak, diger oyunculari tanimak, vs. gibi. Bunlardan sonra oyuna tus, mouse bilgisi gondermek icin xdotool Unix kutuphanesini kullaniyoruz. Bu arac disaridan herhangi bir programa sanki gercek bir kisi gibi tus tiklamalari, hatta mouse x,y hareketi ve tiklamasi gonderebiliyor.

Su anda Github'da bulunan kodlar UrbanTerror oyununu OpenCV ekraninda gosterip, aksiyon olarak oyuncuyu biraz ileri hareket ettirip, durdurup, sonra bir el ates ettiriyor.

Bunun ustune neler eklenebilir?

Mesela optik akis (optical flow) kavrami Kalman Filtreleri ile birlestirilebilir; etraftaki objelerin (yer, duvarlar, engeller) etrafinda dolastikca onlarin yerlerini haritamiza yerlestirebiliriz. Etraflarinda gezindigimiz zaman optik akis vektorleri objelerin sekli hakkinda bize ipucu verecektir, bu vektorler, objelerin gercek yerinin dis dunyaya olan "bir tercumesi / yansimasi" olarak gorulebilir. Gizli degisken obje konumu, acik degisken ise optik akis vektorleridir. Kendi hareketimizi bildigimize gore x_{t+1} = Ax_t + w formulundeki A degisimini de (translation) biliyoruz demektir, cunku biz kendi hareketimizi biliyoruz, diger objeler sabit.

Ekran fotografi, tus yollama temelli bu teknik her turlu oyunu disaridan oynamak icin kullanilabilir, oyunun disariya API acmasina gerek kalmaz.

X Windows bazli ekran kapma teknigine gelene kadar diger bazi yollara baktik, mesela OpenGL'e cengel takmak (bir onceki yazi), fakat bazi oyunlar libGL.so kutuphanesini direk kendileri program icinden yukluyorlar (hile yapilmasini engellemek icin, bazilari OpenGL cengellerini duvarlarin arkasini gormek icin kullaniyor mesela), ve temiz yollarla grafiklerini cekip cikartmak mumkun olmuyor. Bu yontemle ekranda gordugumuz her seyi fps-play gorebilir, ve oynayabilir.

Monday, October 10, 2011

LD_PRELOAD ile Fonksiyon Yakalamak

Linux'ta isleyen herhangi bir kodun ic fonksiyonlarinin yerine bir baskasini gecirmek icin kullanilan bir teknik fonksiyon bindirme (function interposition). Kullanim soyle:

LD_PRELOAD=`pwd`/bizim-kodlar.so ./demo.exe

Dinamik kutuphane bizim-kodlar.so icinde derlenmis C/++ kodlari var. LD_PRELOAD degiskeni bir cevre degiskeni, ve orada tanimlanan kutuphaneler, diger tum kutuphanelere gore oncelik kazanir, yani once LD_PRELOAD'da tanimli kodlar isletiliyor. Cengel takmak icin o yuzden bicilmis kaftan.

Ornek: OpenGL kutuphanesinin ekrana bastigi goruntuyu yakalamak mesela, ekrana cizilen goruntuler glXSwapBuffers cagrisi yaparlar, bu cagri yerine kendi yazdigimiz bir fonksiyonu gecirip, esas fonksiyona aktarma yapmadan once arada goruntuyu alip bir dosyaya yazabiliriz. Alttaki kod demo.cpp basit bir OpenGL ornegi, bir objeyi alip surekli donduruyor. Bu cizimi, bindirilmis yeni fonksiyon uzerinden isletince, goruntunun kare kare ciktisi bir imaj dosyasi olarak /tmp altinda yazilacak.

make.sh

# sudo apt-get install freeglut3 freeglut3-dev libglew1.5 libglew1.5-dev libglu1-mesa libglu1-mesa-dev libgl1-mesa-glx libgl1-mesa-dev
g++ -o demo.exe demo.cpp -lglut -lGL -lGLU -lGLEW
gcc -shared -fPIC -o glcapture.so glcapture.c -ldl

load.sh

rm /tmp/*.tga
rm /tmp/*.jpg
LD_PRELOAD=`pwd`/glcapture.so ./demo.exe 

glcapture.c

/*
 * Use something like this:
 *
 * gcc -shared -fPIC -o glcapture.so glcapture.c -ldl
 * LD_PRELOAD=`pwd`/glcapture.so ./demo
 */

#include
#include
#include
#include
#include

#ifndef RTLD_NEXT
#define RTLD_NEXT ((void *) -1l)
#endif

#define WIDTH 640
#define HEIGHT 480
#define FPS 4

static char buf[WIDTH * HEIGHT * 3];
static int frameno = 0;

void glXSwapBuffers( Display *dpy, GLXDrawable drawable )
{
  printf("swap\n");
  void (*real_swap)(Display*, GLXDrawable);
  real_swap = (void(*)(Display*, GLXDrawable))dlsym(RTLD_NEXT, "glXSwapBuffers");

  FILE *ppm;
  char filename[256];
  glReadPixels(0, 0, WIDTH, HEIGHT, GL_BGR, GL_UNSIGNED_BYTE, buf);

  sprintf(filename, "/tmp/frame%05u.tga", frameno++);
  ppm = fopen(filename, "w");
  fwrite("\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00", 12, 1, ppm);
  {
    unsigned short w = WIDTH;
    fwrite(&w, 2, 1, ppm);
  }
  {
    unsigned short h = HEIGHT;
    fwrite(&h, 2, 1, ppm);
  }
  fwrite("\x18\x00", 2, 1, ppm);
  fwrite(buf, WIDTH*HEIGHT*3, 1, ppm);
  fclose(ppm);

  real_swap(dpy, drawable);
}

int gettimeofday(struct timeval *tv, struct timezone *tz)
{
  printf("gettimeofday frame %u\n", frameno);
  //tv->tv_sec = frameno / FPS;
  //tv->tv_usec = ((double)(frameno % FPS) / FPS) * 1000000;
  return 0;
}

int clock_gettime(clockid_t clk_id, struct timespec *tp)
{
  //tp->tv_sec = frameno / FPS;
  //tp->tv_nsec = ((double)(frameno % FPS) / FPS) * 1e9;
  return 0;
}

demo.cpp

#include
#include
#include
#include
#include

static int useRGB = 1;
static int useLighting = 1;
static int useFog = 0;
static int useDB = 1;
static int useLogo = 0;
static int useQuads = 1;

static int tick = -1;
static int moving = 1;

#define GREY 0
#define RED 1
#define GREEN 2
#define BLUE 3
#define CYAN 4
#define MAGENTA 5
#define YELLOW 6
#define BLACK 7

static float materialColor[8][4] =
{
  {0.8, 0.8, 0.8, 1.0},
  {0.8, 0.0, 0.0, 1.0},
  {0.0, 0.8, 0.0, 1.0},
  {0.0, 0.0, 0.8, 1.0},
  {0.0, 0.8, 0.8, 1.0},
  {0.8, 0.0, 0.8, 1.0},
  {0.8, 0.8, 0.0, 1.0},
  {0.0, 0.0, 0.0, 0.6},
};

static float lightPos[4] =
{2.0, 4.0, 2.0, 1.0};
#if 0
static float lightDir[4] =
{-2.0, -4.0, -2.0, 1.0};
#endif
static float lightAmb[4] =
{0.2, 0.2, 0.2, 1.0};
static float lightDiff[4] =
{0.8, 0.8, 0.8, 1.0};
static float lightSpec[4] =
{0.4, 0.4, 0.4, 1.0};

static float groundPlane[4] =
{0.0, 1.0, 0.0, 1.499};
static float backPlane[4] =
{0.0, 0.0, 1.0, 0.899};

static float fogColor[4] =
{0.0, 0.0, 0.0, 0.0};
static float fogIndex[1] =
{0.0};

static unsigned char shadowPattern[128] =
{
  0xaa, 0xaa, 0xaa, 0xaa, 0x55, 0x55, 0x55, 0x55,  /* 50% Grey */
  0xaa, 0xaa, 0xaa, 0xaa, 0x55, 0x55, 0x55, 0x55,
  0xaa, 0xaa, 0xaa, 0xaa, 0x55, 0x55, 0x55, 0x55,
  0xaa, 0xaa, 0xaa, 0xaa, 0x55, 0x55, 0x55, 0x55,
  0xaa, 0xaa, 0xaa, 0xaa, 0x55, 0x55, 0x55, 0x55,
  0xaa, 0xaa, 0xaa, 0xaa, 0x55, 0x55, 0x55, 0x55,
  0xaa, 0xaa, 0xaa, 0xaa, 0x55, 0x55, 0x55, 0x55,
  0xaa, 0xaa, 0xaa, 0xaa, 0x55, 0x55, 0x55, 0x55,
  0xaa, 0xaa, 0xaa, 0xaa, 0x55, 0x55, 0x55, 0x55,
  0xaa, 0xaa, 0xaa, 0xaa, 0x55, 0x55, 0x55, 0x55,
  0xaa, 0xaa, 0xaa, 0xaa, 0x55, 0x55, 0x55, 0x55,
  0xaa, 0xaa, 0xaa, 0xaa, 0x55, 0x55, 0x55, 0x55,
  0xaa, 0xaa, 0xaa, 0xaa, 0x55, 0x55, 0x55, 0x55,
  0xaa, 0xaa, 0xaa, 0xaa, 0x55, 0x55, 0x55, 0x55,
  0xaa, 0xaa, 0xaa, 0xaa, 0x55, 0x55, 0x55, 0x55,
  0xaa, 0xaa, 0xaa, 0xaa, 0x55, 0x55, 0x55, 0x55
};

static unsigned char sgiPattern[128] =
{
  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  /* SGI Logo */
  0xff, 0xbd, 0xff, 0x83, 0xff, 0x5a, 0xff, 0xef,
  0xfe, 0xdb, 0x7f, 0xef, 0xfd, 0xdb, 0xbf, 0xef,
  0xfb, 0xdb, 0xdf, 0xef, 0xf7, 0xdb, 0xef, 0xef,
  0xfb, 0xdb, 0xdf, 0xef, 0xfd, 0xdb, 0xbf, 0x83,
  0xce, 0xdb, 0x73, 0xff, 0xb7, 0x5a, 0xed, 0xff,
  0xbb, 0xdb, 0xdd, 0xc7, 0xbd, 0xdb, 0xbd, 0xbb,
  0xbe, 0xbd, 0x7d, 0xbb, 0xbf, 0x7e, 0xfd, 0xb3,
  0xbe, 0xe7, 0x7d, 0xbf, 0xbd, 0xdb, 0xbd, 0xbf,
  0xbb, 0xbd, 0xdd, 0xbb, 0xb7, 0x7e, 0xed, 0xc7,
  0xce, 0xdb, 0x73, 0xff, 0xfd, 0xdb, 0xbf, 0xff,
  0xfb, 0xdb, 0xdf, 0x87, 0xf7, 0xdb, 0xef, 0xfb,
  0xf7, 0xdb, 0xef, 0xfb, 0xfb, 0xdb, 0xdf, 0xfb,
  0xfd, 0xdb, 0xbf, 0xc7, 0xfe, 0xdb, 0x7f, 0xbf,
  0xff, 0x5a, 0xff, 0xbf, 0xff, 0xbd, 0xff, 0xc3,
  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
};

static float cube_vertexes[6][4][4] =
{
  {
    {-1.0, -1.0, -1.0, 1.0},
    {-1.0, -1.0, 1.0, 1.0},
    {-1.0, 1.0, 1.0, 1.0},
    {-1.0, 1.0, -1.0, 1.0}},

  {
    {1.0, 1.0, 1.0, 1.0},
    {1.0, -1.0, 1.0, 1.0},
    {1.0, -1.0, -1.0, 1.0},
    {1.0, 1.0, -1.0, 1.0}},

  {
    {-1.0, -1.0, -1.0, 1.0},
    {1.0, -1.0, -1.0, 1.0},
    {1.0, -1.0, 1.0, 1.0},
    {-1.0, -1.0, 1.0, 1.0}},

  {
    {1.0, 1.0, 1.0, 1.0},
    {1.0, 1.0, -1.0, 1.0},
    {-1.0, 1.0, -1.0, 1.0},
    {-1.0, 1.0, 1.0, 1.0}},

  {
    {-1.0, -1.0, -1.0, 1.0},
    {-1.0, 1.0, -1.0, 1.0},
    {1.0, 1.0, -1.0, 1.0},
    {1.0, -1.0, -1.0, 1.0}},

  {
    {1.0, 1.0, 1.0, 1.0},
    {-1.0, 1.0, 1.0, 1.0},
    {-1.0, -1.0, 1.0, 1.0},
    {1.0, -1.0, 1.0, 1.0}}
};

static float cube_normals[6][4] =
{
  {-1.0, 0.0, 0.0, 0.0},
  {1.0, 0.0, 0.0, 0.0},
  {0.0, -1.0, 0.0, 0.0},
  {0.0, 1.0, 0.0, 0.0},
  {0.0, 0.0, -1.0, 0.0},
  {0.0, 0.0, 1.0, 0.0}
};

static void
usage(void)
{
  printf("\n");
  printf("usage: scube [options]\n");
  printf("\n");
  printf("    display a spinning cube and its shadow\n");
  printf("\n");
  printf("  Options:\n");
  printf("    -geometry  window size and location\n");
  printf("    -c         toggle color index mode\n");
  printf("    -l         toggle lighting\n");
  printf("    -f         toggle fog\n");
  printf("    -db        toggle double buffering\n");
  printf("    -logo      toggle sgi logo for the shadow pattern\n");
  printf("    -quads     toggle use of GL_QUADS to draw the checkerboard\n");
  printf("\n");
#ifndef EXIT_FAILURE    /* should be defined by ANSI C
                            */
#define EXIT_FAILURE 1
#endif
  exit(EXIT_FAILURE);
}

void
buildColormap(void)
{
  if (useRGB) {
    return;
  } else {
    int mapSize = 1 << glutGet(GLUT_WINDOW_BUFFER_SIZE);
    int rampSize = mapSize / 8;
    int entry;
    int i;

    for (entry = 0; entry < mapSize; ++entry) {
      int hue = entry / rampSize;
      GLfloat val = (entry % rampSize) * (1.0 / (rampSize - 1));
      GLfloat red, green, blue;

      red = (hue == 0 || hue == 1 || hue == 5 || hue == 6) ? val : 0;
      green = (hue == 0 || hue == 2 || hue == 4 || hue == 6) ? val : 0;
      blue = (hue == 0 || hue == 3 || hue == 4 || hue == 5) ? val : 0;

      glutSetColor(entry, red, green, blue);
    }

    for (i = 0; i < 8; ++i) {
      materialColor[i][0] = i * rampSize + 0.2 * (rampSize - 1);
      materialColor[i][1] = i * rampSize + 0.8 * (rampSize - 1);
      materialColor[i][2] = i * rampSize + 1.0 * (rampSize - 1);
      materialColor[i][3] = 0.0;
    }

    fogIndex[0] = -0.2 * (rampSize - 1);
  }
}

static void
setColor(int c)
{
  if (useLighting) {
    if (useRGB) {
      glMaterialfv(GL_FRONT_AND_BACK,
        GL_AMBIENT_AND_DIFFUSE, &materialColor[c][0]);
    } else {
      glMaterialfv(GL_FRONT_AND_BACK,
        GL_COLOR_INDEXES, &materialColor[c][0]);
    }
  } else {
    if (useRGB) {
      glColor4fv(&materialColor[c][0]);
    } else {
      glIndexf(materialColor[c][1]);
    }
  }
}

static void
drawCube(int color)
{
  int i;

  setColor(color);

  for (i = 0; i < 6; ++i) {
    glNormal3fv(&cube_normals[i][0]);
    glBegin(GL_POLYGON);
    glVertex4fv(&cube_vertexes[i][0][0]);
    glVertex4fv(&cube_vertexes[i][1][0]);
    glVertex4fv(&cube_vertexes[i][2][0]);
    glVertex4fv(&cube_vertexes[i][3][0]);
    glEnd();
  }
}

static void
drawCheck(int w, int h, int evenColor, int oddColor)
{
  static int initialized = 0;
  static int usedLighting = 0;
  static GLuint checklist = 0;

  if (!initialized || (usedLighting != useLighting)) {
    static float square_normal[4] =
    {0.0, 0.0, 1.0, 0.0};
    static float square[4][4];
    int i, j;

    if (!checklist) {
      checklist = glGenLists(1);
    }
    glNewList(checklist, GL_COMPILE_AND_EXECUTE);

    if (useQuads) {
      glNormal3fv(square_normal);
      glBegin(GL_QUADS);
    }
    for (j = 0; j < h; ++j) {
      for (i = 0; i < w; ++i) {
        square[0][0] = -1.0 + 2.0 / w * i;
        square[0][1] = -1.0 + 2.0 / h * (j + 1);
        square[0][2] = 0.0;
        square[0][3] = 1.0;

        square[1][0] = -1.0 + 2.0 / w * i;
        square[1][1] = -1.0 + 2.0 / h * j;
        square[1][2] = 0.0;
        square[1][3] = 1.0;

        square[2][0] = -1.0 + 2.0 / w * (i + 1);
        square[2][1] = -1.0 + 2.0 / h * j;
        square[2][2] = 0.0;
        square[2][3] = 1.0;

        square[3][0] = -1.0 + 2.0 / w * (i + 1);
        square[3][1] = -1.0 + 2.0 / h * (j + 1);
        square[3][2] = 0.0;
        square[3][3] = 1.0;

        if (i & 1 ^ j & 1) {
          setColor(oddColor);
        } else {
          setColor(evenColor);
        }

        if (!useQuads) {
          glBegin(GL_POLYGON);
        }
        glVertex4fv(&square[0][0]);
        glVertex4fv(&square[1][0]);
        glVertex4fv(&square[2][0]);
        glVertex4fv(&square[3][0]);
        if (!useQuads) {
          glEnd();
        }
      }
    }

    if (useQuads) {
      glEnd();
    }
    glEndList();

    initialized = 1;
    usedLighting = useLighting;
  } else {
    glCallList(checklist);
  }
}

static void
myShadowMatrix(float ground[4], float light[4])
{
  float dot;
  float shadowMat[4][4];

  dot = ground[0] * light[0] +
    ground[1] * light[1] +
    ground[2] * light[2] +
    ground[3] * light[3];

  shadowMat[0][0] = dot - light[0] * ground[0];
  shadowMat[1][0] = 0.0 - light[0] * ground[1];
  shadowMat[2][0] = 0.0 - light[0] * ground[2];
  shadowMat[3][0] = 0.0 - light[0] * ground[3];

  shadowMat[0][1] = 0.0 - light[1] * ground[0];
  shadowMat[1][1] = dot - light[1] * ground[1];
  shadowMat[2][1] = 0.0 - light[1] * ground[2];
  shadowMat[3][1] = 0.0 - light[1] * ground[3];

  shadowMat[0][2] = 0.0 - light[2] * ground[0];
  shadowMat[1][2] = 0.0 - light[2] * ground[1];
  shadowMat[2][2] = dot - light[2] * ground[2];
  shadowMat[3][2] = 0.0 - light[2] * ground[3];

  shadowMat[0][3] = 0.0 - light[3] * ground[0];
  shadowMat[1][3] = 0.0 - light[3] * ground[1];
  shadowMat[2][3] = 0.0 - light[3] * ground[2];
  shadowMat[3][3] = dot - light[3] * ground[3];

  glMultMatrixf((const GLfloat *) shadowMat);
}

static char *windowNameRGBDB = "shadow cube (OpenGL RGB DB)";
static char *windowNameRGB = "shadow cube (OpenGL RGB)";
static char *windowNameIndexDB = "shadow cube (OpenGL Index DB)";
static char *windowNameIndex = "shadow cube (OpenGL Index)";

void
idle(void)
{
  tick++;
  if (tick >= 120) {
    tick = 0;
  }
  glutPostRedisplay();
}

/* ARGSUSED1 */
void
keyboard(unsigned char ch, int x, int y)
{
  switch (ch) {
  case 27:             /* escape */
    exit(0);
    break;
  case 'L':
  case 'l':
    useLighting = !useLighting;
    useLighting ? glEnable(GL_LIGHTING) :
      glDisable(GL_LIGHTING);
    glutPostRedisplay();
    break;
  case 'F':
  case 'f':
    useFog = !useFog;
    useFog ? glEnable(GL_FOG) : glDisable(GL_FOG);
    glutPostRedisplay();
    break;
  case '1':
    glFogf(GL_FOG_MODE, GL_LINEAR);
    glutPostRedisplay();
    break;
  case '2':
    glFogf(GL_FOG_MODE, GL_EXP);
    glutPostRedisplay();
    break;
  case '3':
    glFogf(GL_FOG_MODE, GL_EXP2);
    glutPostRedisplay();
    break;
  case ' ':
    if (!moving) {
      idle();
      glutPostRedisplay();
    }
  }
}

void
display(void)
{
  GLfloat cubeXform[4][4];

  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

  glPushMatrix();
  glTranslatef(0.0, -1.5, 0.0);
  glRotatef(-90.0, 1, 0, 0);
  glScalef(2.0, 2.0, 2.0);

  drawCheck(6, 6, BLUE, YELLOW);  /* draw ground */
  glPopMatrix();

  glPushMatrix();
  glTranslatef(0.0, 0.0, -0.9);
  glScalef(2.0, 2.0, 2.0);

  drawCheck(6, 6, BLUE, YELLOW);  /* draw back */
  glPopMatrix();

  glPushMatrix();
  glTranslatef(0.0, 0.2, 0.0);
  glScalef(0.3, 0.3, 0.3);
  glRotatef((360.0 / (30 * 1)) * tick, 1, 0, 0);
  glRotatef((360.0 / (30 * 2)) * tick, 0, 1, 0);
  glRotatef((360.0 / (30 * 4)) * tick, 0, 0, 1);
  glScalef(1.0, 2.0, 1.0);
  glGetFloatv(GL_MODELVIEW_MATRIX, (GLfloat *) cubeXform);

  drawCube(RED);        /* draw cube */
  glPopMatrix();

  glDepthMask(GL_FALSE);
  if (useRGB) {
    glEnable(GL_BLEND);
  } else {
    glEnable(GL_POLYGON_STIPPLE);
  }
  if (useFog) {
    glDisable(GL_FOG);
  }
  glPushMatrix();
  myShadowMatrix(groundPlane, lightPos);
  glTranslatef(0.0, 0.0, 2.0);
  glMultMatrixf((const GLfloat *) cubeXform);

  drawCube(BLACK);      /* draw ground shadow */
  glPopMatrix();

  glPushMatrix();
  myShadowMatrix(backPlane, lightPos);
  glTranslatef(0.0, 0.0, 2.0);
  glMultMatrixf((const GLfloat *) cubeXform);

  drawCube(BLACK);      /* draw back shadow */
  glPopMatrix();

  glDepthMask(GL_TRUE);
  if (useRGB) {
    glDisable(GL_BLEND);
  } else {
    glDisable(GL_POLYGON_STIPPLE);
  }
  if (useFog) {
    glEnable(GL_FOG);
  }
  if (useDB) {
    glutSwapBuffers();
  } else {
    glFlush();
  }
}

void
fog_select(int fog)
{
  glFogf(GL_FOG_MODE, fog);
  glutPostRedisplay();
}

void
menu_select(int mode)
{
  switch (mode) {
  case 1:
    moving = 1;
    glutIdleFunc(idle);
    break;
  case 2:
    moving = 0;
    glutIdleFunc(NULL);
    break;
  case 3:
    useFog = !useFog;
    useFog ? glEnable(GL_FOG) : glDisable(GL_FOG);
    glutPostRedisplay();
    break;
  case 4:
    useLighting = !useLighting;
    useLighting ? glEnable(GL_LIGHTING) :
      glDisable(GL_LIGHTING);
    glutPostRedisplay();
    break;
  case 5:
    exit(0);
    break;
  }
}

void
visible(int state)
{
  if (state == GLUT_VISIBLE) {
    if (moving)
      glutIdleFunc(idle);
  } else {
    if (moving)
      glutIdleFunc(NULL);
  }
}

int
main(int argc, char **argv)
{
  int width = 640, height = 480;
  int i;
  char *name;
  int fog_menu;

  glutInitWindowSize(width, height);
  glutInit(&argc, argv);
  /* process commmand line args */
  for (i = 1; i < argc; ++i) {
    if (!strcmp("-c", argv[i])) {
      useRGB = !useRGB;
    } else if (!strcmp("-l", argv[i])) {
      useLighting = !useLighting;
    } else if (!strcmp("-f", argv[i])) {
      useFog = !useFog;
    } else if (!strcmp("-db", argv[i])) {
      useDB = !useDB;
    } else if (!strcmp("-logo", argv[i])) {
      useLogo = !useLogo;
    } else if (!strcmp("-quads", argv[i])) {
      useQuads = !useQuads;
    } else {
      usage();
    }
  }

  /* choose visual */
  if (useRGB) {
    if (useDB) {
      glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
      name = windowNameRGBDB;
    } else {
      glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH);
      name = windowNameRGB;
    }
  } else {
    if (useDB) {
      glutInitDisplayMode(GLUT_DOUBLE | GLUT_INDEX | GLUT_DEPTH);
      name = windowNameIndexDB;
    } else {
      glutInitDisplayMode(GLUT_SINGLE | GLUT_INDEX | GLUT_DEPTH);
      name = windowNameIndex;
    }
  }

  glutCreateWindow(name);

  buildColormap();

  glutKeyboardFunc(keyboard);
  glutDisplayFunc(display);
  glutVisibilityFunc(visible);

  fog_menu = glutCreateMenu(fog_select);
  glutAddMenuEntry("Linear fog", GL_LINEAR);
  glutAddMenuEntry("Exp fog", GL_EXP);
  glutAddMenuEntry("Exp^2 fog", GL_EXP2);

  glutCreateMenu(menu_select);
  glutAddMenuEntry("Start motion", 1);
  glutAddMenuEntry("Stop motion", 2);
  glutAddMenuEntry("Toggle fog", 3);
  glutAddMenuEntry("Toggle lighting", 4);
  glutAddSubMenu("Fog type", fog_menu);
  glutAddMenuEntry("Quit", 5);
  glutAttachMenu(GLUT_RIGHT_BUTTON);

  /* setup context */
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  glFrustum(-1.0, 1.0, -1.0, 1.0, 1.0, 3.0);

  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity();
  glTranslatef(0.0, 0.0, -2.0);

  glEnable(GL_DEPTH_TEST);

  if (useLighting) {
    glEnable(GL_LIGHTING);
  }
  glEnable(GL_LIGHT0);
  glLightfv(GL_LIGHT0, GL_POSITION, lightPos);
  glLightfv(GL_LIGHT0, GL_AMBIENT, lightAmb);
  glLightfv(GL_LIGHT0, GL_DIFFUSE, lightDiff);
  glLightfv(GL_LIGHT0, GL_SPECULAR, lightSpec);
#if 0
  glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, lightDir);
  glLightf(GL_LIGHT0, GL_SPOT_EXPONENT, 80);
  glLightf(GL_LIGHT0, GL_SPOT_CUTOFF, 25);
#endif

  glEnable(GL_NORMALIZE);

  if (useFog) {
    glEnable(GL_FOG);
  }
  glFogfv(GL_FOG_COLOR, fogColor);
  glFogfv(GL_FOG_INDEX, fogIndex);
  glFogf(GL_FOG_MODE, GL_EXP);
  glFogf(GL_FOG_DENSITY, 0.5);
  glFogf(GL_FOG_START, 1.0);
  glFogf(GL_FOG_END, 3.0);

  glEnable(GL_CULL_FACE);
  glCullFace(GL_BACK);

  glShadeModel(GL_SMOOTH);

  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  if (useLogo) {
    glPolygonStipple((const GLubyte *) sgiPattern);
  } else {
    glPolygonStipple((const GLubyte *) shadowPattern);
  }

  glClearColor(0.0, 0.0, 0.0, 1);
  glClearIndex(0);
  glClearDepth(1);

  glutMainLoop();
  return 0;             /* ANSI C requires main to return int. */
}


Saturday, October 1, 2011

OpenCV Imajlarinin Boyutunu Degistirmek (Resize)

Eger OpenCV Resize cagrisi problem yaratiyorsa, bu islemi Python IPL icinden yapabiliriz. Ipl2PIL ile bir OpenCV video karesini PIL imajina cevirebiliyoruz. Bu imaj uzerinde resize(..) cagrisi yapilabilir. Hatta np.array(..) ile bu imaj Numpy dizinine de cevirilebilir. Boyle bir dizin elde edilince her turlu Uygulamali Matematik teknigi bu dizin uzerinde uygulanabilir. PIL imaji OpenCV'ye PIL2Ipl ile geri cevirilebilir.

Alttaki ornek bir kareyi ucte birine indirgiyor.
__scale__ = 3
frame = cvQueryFrame(capture)
gray = cvCreateImage ((frame.width, frame.height), 8, 1)
cvCvtColor( frame, gray, CV_BGR2GRAY )
ipl = Ipl2PIL(gray)
ipl = ipl.resize((int(frame.width/__scale__),int(frame.height/__scale__)),
Image.ANTIALIAS)
nimg = np.array(ipl)
..
ipl2 = PIL2Ipl(ipl)
..
cvShowImage("Example2", ipl2)

Piksel Takibi, Optik Akış (Optical Flow), Lucas Kanade