OpenCV Sanal Mouse

Kodlar yeniden duzenlenmiştir…

O kadar openCv dememize karsın hiç proje yapmasak ayıp  olurdu heralde.Başlangıc olarak Renk tanımlama yontemiyle Mouse kontrolu programının kodlarını asagıdan bulabilirsiniz….Daha once anlatılan openCv kutphanesi eklemeyi unutmayın…Renk olarak Kırmızı yı sectik…Sizde dilerseniz degiştirebilirsiniz….

Uygulamamız daha öncede bahsedildiği üzere Microsoft Visual Studio 2008 C++ ortamında geliştirilmiştir.Win32 console application olarak yaratılan uygulamaya kullancak olduğumuz kütüphaneleri ekliyoruz.

#include “cv.h”

#include “highgui.h”

Yukarıda anlatılan linker ayarlarını gerçekleştirdikten sonra uygulamamızı yazmaya başlayabiliriz.  yapılacak adımlar;

  • Kameradan Görüntü alma
  • Kırmızı bandın  nerede olduğunu tayin etme
  • Korser pozisyonunun tayini
  • Sol klikler

Kameradan resim alabilmek için openCV kütüphanesinde bulunan fonksiyonları kullanırız.Programı  daha rahat yazabilmek için asagıda belirrtigim fonksiyonu kaldırak zorunda kaldım.Bunun amacı saniyede daha fazla frame alabilmekti. IplImage*resmi_ isle(IplImage* img)

{

//resim

}

İlk yapmamız gereken kaera cihazlarını çalıştırmaktır. Eğer  cihaz yoksa hata mesajı verilerek programdan cıkıs yapılır.

// Kameranın caliştirilmasi

CvCapture* capture = 0;

capture = cvCaptureFromCAM(0);

// Kamera kontrolu

if(!capture)

{

printf(“Kamera calistirilamiyor!…n“);

return -1;

}

Ekranda görebilmemiz için pencereleri oluşturmamız gerekir.Burada üç tane pencere oluşturdum.Bunlardan biri (ana pencere) normal kameramızı görebilmek için , bir tanesi ise (kirmizi) mouse hareketini gorebilmemiz için , (mavi)  sol klikleri  görebilmek içindir.Bunun için aşagıdaki komutar kullanıldı.

cvNamedWindow(“anaekran”);

cvNamedWindow(“kirmizi”);

cvNamedWindow(“mavi”);

Üzerine cizim yapabileceğimiz bir adet daha image e ihtiyacımız var.

    while(true)

{

// kameradan resimleri tutmak için

IplImage* frame = 0;

frame = cvQueryFrame(capture);

Burada kameradan bir frame alıp frame isimli dosyaya onu saklıyoruz.

Dikkat ettiğiniz üzere cizim isimli bir resim oluşturduk.Bunun için herhangi bir hafıza ayrımı yapmadık , NULL olarak tanımlandı.Frame in ilk frame olup olmadığını kontrol etmek için bir kontrol mekanizması tanımlıyoruz.

        // eger ilk frame se resmi oluşturmak için.

if(img_cizim == NULL)

{

img_cizim = cvCreateImage(cvGetSize(frame), 8, 3);

}

IplImage* kirmizi= cvCreateImage(cvGetSize(frame), 8, 1);

IplImage* mavi=cvCreateImage(cvGetSize(frame),8,1);

Mouse kontrolleri için iki farklı image olusturuluyor.

cvInRangeS(frame, cvScalar(0,0,140), cvScalar(40,40,255), kirmizi);//(B,G,R)

Asıl işi yapacak olan komut yukarıdaki cvInRange komutudur.Bu komutta istenilen renk aralıgındaki renkler bulunarak ana frame uzerinde yerleri tyin edilir ve bu renkler binary ye cevrilerek 0 yapılır geri kalan tum renkler 1 yapılır.

Resmin enini ve boyunu almamızın nedeni ilerde kullanılmak uzere degerlerin elde edilmesidir.

int yukseklik=frame->height;

int en=frame->width;

//kırmızı için

CvMoments *hareket = (CvMoments*)malloc(sizeof(CvMoments));//structer

cvMoments(kirmizi, hareket, 1);//(resim,moments, binary 0 -1)

double kirmizimomentx = cvGetSpatialMoment(hareket, 1, 0);

double kirmizimomenty = cvGetSpatialMoment(hareket, 0, 1);

double kirmizi_area = cvGetCentralMoment(hareket, 0, 0);//belirli bir algoritmayla x ve y koordinatlarının bir ortatlaması alnıyor.

int posX = 0;

int posY = 0;

posX = kirmizimomentx/kirmizi_area;

posY = kirmizimomenty/kirmizi_area;

CvMoment komutu binary halindeki resmin içerisindeki 0 ların yerlerini bularak işlem yapaktadır.

Daha önce acıklanan opencv kütüphanesiyle kameradan alınan framelerdeki istenilen renge gore x, y koordinatlarını belirlenmişti.Bu x , y koordinatları kullanılmak üzere bir fonksiyon yazıldı.Fonksiyon asagıda gosterildigi uzere deklere edildi.

void mouseposition(int x,int y)

{

SetCursorPos(x,y);

}

SetCursorPos(x,y) fonksiyonu imlecin hangi koordinatlarda olacağını belirleyip, imleci o kooridnatlarda konumlanasını sağlar.

BOOL SetCursorPos(

int x,

int y

);

Olarak Windows.h kütüphnesinde tanımlanmıştır.

Parameters

x

[in] Specifies the new x-coordinate, in screen coordinates, of the cursor.

y

[in] Specifies the new y-coordinate, in screen coordinates, of the cursor.

Mousun her çözünürlükte doğru olarak hareketinin sağlanması için bir ekran çözünürlüğünü alan fonksiyon yazıldı.

void GetDesktopResolution(int& yatay, int& dikey)

{

RECT desktop;

// Get a handle to the desktop window

const HWND hDesktop = GetDesktopWindow();

// Windowsun genişlik ve en degerlerinin alınabilmesi için

GetWindowRect(hDesktop, &desktop);

// Üst kösenin koordinatları  (0,0) olacaktır.

// ve alttaki kosenin koordinatları (yatay,dikey) biçiminde olcaktır.

yatay = desktop.right;

dikey = desktop.bottom;

}

HWND WINAPI GetDesktopWindow(void); fonkisyonu hiç argüman almayarak tanımlanmıştır.(void).

Main fonkisyonumuuzun içinde

int yatay= 0;

int dusey = 0;

GetDesktopResolution(yatay, dusey); 

Şeklinde fonksiyon cagrılarak işletime alınmıstır.Elde edilen yatay ve dusey degerlerinden daha once elde edilen posX ve posY degerleriyle gerekli işlemler yapıldıktan sonra olusan degerler mouse koordinatları olarak atanmıstır.Opencv den gelen negatif değerler gözardı edilmesi için  bir if kosullandırılması kullanılması mouse için gerekli olmayan değerlerin fonkiyona gonderilmesini engellemiş ve daha basarılı sonuc elde edilmiştir.

mouseposx=yatay-posX*(yatay/en);

mouseposy=posY*(dikey/boy);

Daha once geliştirilen algoritmada yatay/en oranları 2 olarak kabul edilmiş ama du anda uzerinde caliısılan bilgisayarda dogu sonuclar elde edilmesine ragmen baska ortamlarda testen gecemememiştir. Cünkü her bilgisayarın kamera cekim genişliği farklı olup ekrn cozununürlukleri de  farklıdır.Fakat fotograf en/ekran boy oranı her zaman dogru katsayı verecegi  için sorun teskil etmemektedir.

PosX ve posY nin direk mouseposition fonksiyonunumuza gonderilmememesinin sebebi kameradan dolayı ayna etkisinin oluşmasıydı.Yani ekran bize dönuk olduğu için bizim sağ yöne yaptığımız hareketler sol olarak algılanıyordu ve  bu başarılı bir sonuç elde etmede problemdi.

Ekrandaki koordinatları görebilmek için OpenCV den elde ettiğimiz PosX ve PosY değerleri ve ayrıca mouseposx ve mouseposy değerleri ekranda görebilmek adına bu değerleri printf yardımyla console ekranında gorebiliyoruz.

Sol klik işlemleri

CvMoment fonkisyonundn gelen degerler renk algılanmadıgı zaman negatif, diger durumlarda pozitiftir.Bu durumu kullanarak bir asagıdaki algoritmayı yazıldı.

if(solklikx>0 && solkliky>0)//eksi degerlerin mouse fonksiyonuna gitmesini engellemek için…

{

printf(“donguye girdi”);

cvCircle(frame, cvPoint(posX, posY),15,cvScalar(255,0,0),15,8,0);//ekranda gorebilemk için…

//cvCircle(frame, cvPoint(solklikx, solkliky),12,cvScalar(0,255,0),8,8,0);//ekranda gorebilemk için…

solklik=1;

}

/* printf(“%d\n”,solklik);*/

if(solklik==0)

{

mousesolklikbirak(mouseposx,mouseposy);

solklik=2;

printf(“sol birakildi\n”);

}

if(solklik==1)

{

mousesolklikbas(mouseposx,mouseposy);

solklik=0;

printf(“sol basildi\n”);

}

Kullanılan resimlerin ve structerların bırakılması noktaında asagıdaki kodlar yazıldı.

cvShowImage(“kirmizi”, kirmizi);

cvShowImage(“anaekran”, frame);

cvShowImage(“mavi”, mavi);

int c = cvWaitKey(10);

cvReleaseImage(&kirmizi);

cvReleaseImage(&mavi);

delete hareket;

ubuntu 11.04 ilk izlenimler…

Ubuntunun Gnome i bırakıp Utiliye gecmesi her ne kadar laptop kullanıcılarına yonelik olsa da acıkcası begenmedim belki de alısık oldugumuz eski ubuntdan dolayı…Daha 5 dakikadır kullanıyorum fakat şimdiden yorulmaya basladım.Sol tarafta olması ve otomatik gizlenmesi kullanımını zorlastırıyor.Belki bi yerlerinde sttingi vardır bakmam lazım biraz daha…

Diğer gözume carpan ayrıntı openoffice libreoffice olmus… Ne fark var gorecegiz…

inşallah yeni gorunm ubuntu için hayırlı olur…

OpenGL

imge işleme

C#

Hello OpenCV!!!

Görüntü İşlemede Yeni Bir Soluk, OPENCV

OpenCV ne Acaba?

OpenCV, bir resim ya da video içindeki anlamlı bilgileri çıkarıp işleyebilmek için INTEL tarafından C ve C++ dilleri kullanılarak geliştirilmiş, açık kaynak kodlu bir “Bilgisayarla Görme” kütüphanesi…

Bilgisayarlı Görme de neyin nesi demeyin .Bildiginiz üzere bilgisayar için kamerdan aldıgınız  görüntüler anlamsız.anlamsız bilgiler nasıl oluyor da bilgisayar algılıyor diyebilirsiniz  Goreceksiniz li artık cok  kolay… sadece bi kac kod yazmanız gerekcek…:D

OpenCv  http://sourceforge.net/projects/opencvlibrary/ adresinden kolaylıkla indirebileceginiz acık kaynaklı bir kütüphane…Bütün işletim sistemlerinde uyguamalarınızı geliştirebileceginiz bu kütüphane , c ++ ve C # progrmlama dillerini destekliyor. artık yeni sürümlerin de   python ve Ruby  destegi de mevcut.

Kurulum anlatmayacagım zaten Visual 2008 e opencv kurulumu pek cok yerden bulabilirsiniz.Daha cok kodlar uzerinden bildiklerimi anlatmaya calişiacagım Goreceksiniz eglenceli olacak…

OpenCV kutuphanesini kurduktan ve gerekli ayarlamaları yaptıktan sonra ilk uygulamamızı gercekleyelim.

Bir Resmin Görüntülenmesi

//PROGRAM 1#include <highgui.h>int main()
{
IplImage* img;
img = cvLoadImage(“C:\\Lenna.jpg”);
cvNamedWindow(“LENNA”, 1);
cvShowImage(“LENNA”, img );
cvWaitKey(0);
cvReleaseImage(&img);
cvDestroyWindow(“LENNA”);
return 0;
}

tabi resminizin yolunu değiştirmeniz gerekecek…

İlk once Basit işlemlerden devam edelim ve resimler uzerinde biraz oynamalar yapalım…Eger imge işlemeyle ilgileniyorsanız bu terimlere aşina olmalısınız.Filtreleme ,kenar bulma  gibi…hadi bakalım nasıl oluyor…

Resimlere Filtre Uygulama

//PROGRAM 2
#include “cv.h”
#include “highgui.h”
int main()
{
IplImage* img;
img = cvLoadImage(“C:\\Lenna.jpg”);
cvNamedWindow(“Filtre_Oncesi”,1);
cvShowImage( “Filtre_Oncesi”,img);
cvNamedWindow(“Filtre_Sonrasi”,1);
IplImage* img2;
CvSize boyut;
boyut=cvGetSize(img);
img2 = cvCreateImage(boyut,8,3);
cvSmooth(img,img2,CV_GAUSSIAN,5,5);
cvSmooth(img2,img2,CV_GAUSSIAN,5,5);
//Filtre Seçenekleri
//0 CV_BLUR_NO_SCALE
//1 CV_BLUR
//2 CV_GAUSSIAN
//3 CV_MEDIAN
//4 CV_BILATERAL
cvShowImage(“Filtre_Sonrasi”,img2);
cvWaitKey(0);
cvReleaseImage(&img);
cvReleaseImage(&img2);
cvDestroyWindow(“Filtre_Oncesi”);
cvDestroyWindow(“Filtre_Sonrasi”);
return 0;
}

Resme iki kere cvSmooth komutuyla Gaussian Filtresi uyguladık.Bu Gaussian Filtresi de neyin nesi derseniz kısaca acıklayalım.Daha sonra zaten komutları acıklarken tekrar değinecegiz.Ön bilgi olması acısından biraz baksak fena olmaz sanırım.
Verilen bir resim üzerinde düzleştirme işlemi uygulamak için kullanılır. Diğer bir tabirle resim üzerindeki gürültüyü kaldırır.

Kenar Bulma Uygulamaları

//PROGRAM 3
#include <cv.h>
#include <highgui.h>
#include <stdio.h>
int main( )
{
int sec;
IplImage *rgb, *gry;
rgb=cvLoadImage( “C:\\Lenna.jpg”);
cvNamedWindow(“Kaynak Resim”,1);
cvShowImage(“Kaynak Resim”,rgb);
CvSize boyut=cvGetSize(rgb);
gry = cvCreateImage(boyut,8,1);
cvCvtColor(rgb,gry,CV_RGB2GRAY);
cvNamedWindow(“Gri-Tonlu Resim”,1);
cvShowImage(“Gri-Tonlu Resim”,gry);
cvWaitKey(0);
printf(“1-Canny,2-Sobel,3-Laplace”);
printf(“\nYontem Seciniz…\n”);
scanf(“%d”,&sec);         
if (sec==1){ //Canny
IplImage* cny;
cny = cvCreateImage(boyut,8,1);
cvNamedWindow(“Canny Uygula”,1);
cvCanny(gry,cny,45,120,3);
cvShowImage(“Canny Uygula”,cny );
cvWaitKey(0);
cvReleaseImage(&cny);
cvDestroyWindow(“Canny Uygula”);}
else if (sec==2){ //Sobel
IplImage* sbl;
rgb=cvCloneImage(gry);
sbl =
cvCreateImage(boyut,IPL_DEPTH_16S,1);
cvSobel (rgb, sbl, 1, 0, -1);
cvConvertScaleAbs (sbl, gry);
cvNamedWindow(“Sobel Uygula”,1);
cvShowImage(“Sobel Uygula”,gry);
cvWaitKey(0);
cvReleaseImage(&sbl);
cvDestroyWindow(“Sobel Uygula”);}
else if (sec==3){ //Laplace
IplImage* lplc;
lplc = cvCreateImage(boyut,IPL_DEPTH_16S,1);
cvLaplace (gry, lplc, 3);
cvConvertScaleAbs (lplc, gry);
cvNamedWindow(“Laplace Uygula”,1);
cvShowImage(“Laplace Uygula”,gry);
cvWaitKey(0);
cvReleaseImage(&lplc);
cvDestroyWindow(“Laplace Uygula”);}
else printf(“Yanlis Girdiniz.”);
cvWaitKey(0);
cvReleaseImage(&rgb);
cvReleaseImage(&gry);
cvDestroyWindow(“Kaynak Resim”);
cvDestroyWindow(“Gri-Tonlu Resim”);
return 0;
}

Bu uygulamada farklı resim işleme metodlarını bir arada kullandık.(Gri ye cevirme ,Sobel uygulama,Laplace uygulama Canny uygulama gibi )….

 Kamera ile Gerçek Zamanlı Görüntü Yakalama

İşte en eglenceli kısma geldik … OpenCV kütüphanesi ile USB ya da dahili web kamerasından görüntü yakalayarak gerçek-zamanlı uygulamalar geliştirilebilir.Sistemde birden fazla kamera kullanılması durumunda gerekli kamera ID’si belirlenip ilgili metoda parametre olarak girilmelidir.Hadi yazalım bi tane.Tabi bu uygulamayı caliştirabilmeniz için kameraya ihtiyacınız var …:)

//PROGRAM 4 
#include “highgui.h”
#include “stdio.h”
int main( )
{
cvNamedWindow( “GORUNTU”,1);
CvCapture* video=cvCaptureFromCAM(0);
if (video==NULL)
{
 printf(“Dosya okunamadi..\n”);
 return 0;
}
IplImage* frame;
while(1)
{     
 frame=cvQueryFrame(video);
 if ( !(frame)  ) break;
 cvShowImage( “GORUNTU”, frame);    
 char c = cvWaitKey(30);
 if ( c == 27 ) break;
}
printf(“Okuma islemi bitmistir.\n”);
cvReleaseCapture( &video );
cvDestroyWindow( “GORUNTU” );
cvWaitKey(0);
return 0;
}

“cvCaptureFromCAM” metodu kullanılan kameranın ID’sini parametre olarak alır. Sistemde tek bir USB kamera kullanılıyorsa parametre olarak 0 (CV_CAP_ANY), birden fazla kamera kullanılıyorsa 100 (CV_CAP_MIL), 200 (CV_CAP_VFW) ya da 300 (CV_CAP_FIREWIRE, CV_CAP_IEEE1394, ..vs) değerlerinden biri parametre olarak kullanılır. Sistemde kullanılan kameranın çeşidine ve sayısına göre, deneme yanılma yöntemiyle gereken parametre seçilir.

Yukarıda “cvCaptureFromCAM” metodu ile “CvCapture” tipinden bir değişkene görüntü gelmesi sağlandıktan sonra sonsuz bir döngü yardımıyla yakalanan görüntünün içerisindeki çerçeveler/resimler (frame) “cvQueryFrame” metodu ile tek tek sorgulanıp okutularak ekranda gösterilir. ESC’a basıldığında görüntü yakalama işlemi sona erer.

Bu kodlar ile bir TV kartı aracılığıyla elde edilen görüntü de yakalanabilir.

Bir Video Dosyasının Oynatılması

//PROGRAM 5
#include “highgui.h”
#include “stdio.h”
int main( )
{
 cvNamedWindow(“Avi Dosyası”,1);
 CvCapture* video;
 video=cvCaptureFromFile(“A.avi” );
//video=cvCaptureFromAVI(“A.avi” );
 int zaman, fps;
 fps=cvGetCaptureProperty(video,5);
 zaman=1000/fps;
 if (video==NULL)
   printf(“Dosya okunamadı..\n”);
 IplImage* frame;
 while(1)
 {
  frame=cvQueryFrame(video);
  if (!(frame)) break;
  cvShowImage(“Avi Dosyası”,frame);    
  char c = cvWaitKey(zaman);
  if ( c == 27 ) break;
 }
 cvWaitKey(0);
 cvReleaseCapture(&video);
 cvDestroyWindow(“Avi Dosyası”);
  return 0;
}