1 Mart 2014 Cumartesi

OpenCVsharp'a Giriş - Yüz Algılama

    Merhaba arkadaşlar, bu yazımızda OpenCV adlı  görüntü işleme kütüphanesinden ve bu kütüphanenin C# wrapper'ı OpenCVSharp'tan bahsedeceğiz. Sonrasında ise yüz algılama ile ilgili basit bir örnek yapacağız.

    Öncelikle OpenCV kütüphanesinden bahsedelim. OpenCV ilk versiyonu 1999 yılında İntel'in araştırma ekibi tarafından yayımlanmış açık kaynak kodlu ve BSD lisanslı bir görüntü işleme kütüphanesidir.İçinde birçok ileri düzey algoritmayı bulundurur ve çok kolay bir kullanımı vardır. (yapılan işlemlerin aslında ne kadar karmaşık olduğunu göz önüne alırsak.) OpenCV kullanarak C++ ve C dillerinde kolayca Haar cascade'leri kullanarak yüz tanıma, SURF-FAST gibi algoritma kullanarak nesne tanıma gerçekleştirebilirsiniz.

   Dediğimiz gibi C++ ve C dillerinde kullanıma hazır olan bu kütüphaneyi C# ve Python gibi dillerde kullanmak için wrapper denen, kütüphanenin fonksiyonlarını farklı diller kullanarak çağırmamıza yarayan ara kütüphanelere ihtiyacımız var. Bu noktada yardımımıza Emgu CV ve OpenCVSharp gibi wrapperlar koşuyor.

   Kütüphaneden bahsettiğimize göre örnek programımıza geçebiliriz. Öncelikle Visual Studio'da yeni bir C# projesi açalım. Projemizde opencvsharp kullanabilmek için ilk önce gerekli dllleri projemize eklememiz gerekiyor. Bunu bu adresten indirerek elle de yapabilirsiniz fakat biz bu makalede NuGet kullanarak otomatik olarak projemize gerekli dosyaları ekleyeceğiz.

   Projenizi oluşturduktan sonra araç çubuğundan Project > Manage NuGet Packages seçeneklerini seçerek NuGet paket ekleme penceresini açın. Online seçeneğini seçip arama kutusuna "opencvsharp" yazdığınızda karşınıza gelen sonuç aşağı yukarı böyle bir şey olacak. İşletim sisteminize göre 64 bit ve 32 bit sürümleri arasından seçim yapın ve "Install" a basın. (x86 32 bit anlamına gelmektedir.)




Kısa bir süre sonra projenizin Solution Explorer penceresinde eklenen dllleri görebililiyor olacaksınız.


Bu aşamada herhangi bir sorunla karşılaştıysanız yorumlarda belirtebilirsiniz. Wrapperımızı yükledik ve artık kod yazmaya geçebiliriz.


Her şeyden önce kodumuza kullanacağımız kütüphaneleri ekleyelim;
using OpenCvSharp;
using OpenCvSharp.MachineLearning;
using OpenCvSharp.Blob;
using OpenCvSharp.UserInterface;
using OpenCvSharp.CPlusPlus;
Kodumuzun en üstüne bu satırları ekliyoruz.



Formumuza resmi göstermek için kullanacağımız bir pictureBox ve kodu çalıştırmak için kullanacağımız bir buton ekleyelim.

Butonumuza çift tıklayarak click eventini oluşturalım. Buttonumuzun click eventi içinde:

Bitmap resim = (Bitmap)Bitmap.FromFile(@"C:\resim\resim1.jpg");

şeklinde bir bitmap nesnesi oluşturalım. Eğer parantez içine neden (Bitmap) yazdığımı merak ediyorsanız internetten C# Implicit Type Conversion şeklinde araştırabilirsiniz. Bu nesne yüz algılama yapacağımız resmi tutacak. O yüzden parametrelere işlem yapmak istediğiniz resmi yazın.

OpenCv kütüphanesi resimleri saklarken görüntü işleme ile ilgili fonksiyonları olan iplimage adlı bir nesne kullanır. Resmimizi bitmap olarak aldık ama işlem yapmak için ilk önce iplimage'e çevirmeliyiz. Bunun için;

IplImage resimipl = BitmapConverter.ToIplImage(resim);

diyerek resmimizi iplimage'e çevirelim. Resmi aldığımıza göre artık algılamaya geçebiliriz.



Yüz algılama yapacağımız, iplimage türünden değer geri döndüren ve parametrelerinde bir adet iplimage alan bir fonksiyon oluşturalım;


private IplImage yuzAlgila(IplImage resim) {}


Bu fonksiyonun içine suratların etrafına çizeceğimiz çemberin rengini belirleyen bir CvColor nesnesi oluşturalım.


CvColor surat = new CvColor(0, 0, 255); //mavi

Parametrelere yazdığımız (0,0,255) değerleri mavi renktir. R - G - B değerlerini değiştirerek rengi değiştirebilirsiniz.

Fonksiyonumuz içerisinde aşağıdaki değerleri tanımlayalım.


const double olcek = 3.0;   //hizli islem icin resmin kac kat kucultulecegi
const double ScaleFactor = 2.5;
const int MinNeighbors = 1;
Buradaki ölçek değişkeni resmin kaç kat küçültüleceğini belirtiyor. İşlem yapmadan önce resmi küçülterek tanıma için gerekli süreyi azaltıyoruz. Bu gerçek zamanlı çalışan uygulamalar için kritik önem taşıyor.

ScaleFactor ve MinNeighbors değişkenleri ise Haar yöntemi için gerekli bazı değişkenler. Bu makalede açıklamaya çalışırsak gereksiz uzar ve konumuzun dışına çıkmış oluruz. Burada sadece basit bir örnek ile başlangıç yapmaya çalışıyoruz :)

using (IplImage kucukresim = new IplImage(new CvSize(Cv.Round(resim.Width / olcek), Cv.Round(resim.Height / olcek)), BitDepth.U8, 1))


            {


                using (IplImage gri = new IplImage(resim.Size, BitDepth.U8, 1))   //renksizlestir


                {


                    Cv.CvtColor(resim, gri, ColorConversion.BgrToGray);


                    Cv.Resize(gri, kucukresim, Interpolation.Linear);


                    Cv.EqualizeHist(kucukresim, kucukresim);


                }




                IplImage outImage = Cv.Clone(resim);




                //asil tespit kismina geldik


                using (CvHaarClassifierCascade cascade = CvHaarClassifierCascade.FromFile(Environment.CurrentDirectory + "\\haarcascades\\haarcascade_frontalface_alt2.xml"))


                using (CvMemStorage storage = new CvMemStorage())


                {


                    storage.Clear();




                    Stopwatch watch = Stopwatch.StartNew();


                    CvSeq<CvAvgComp> faces = Cv.HaarDetectObjects(kucukresim, cascade, storage, ScaleFactor, MinNeighbors, 0, new CvSize(30, 30));


                    watch.Stop();


                    Console.WriteLine("tespit suresi = {0} milisaniye", watch.ElapsedMilliseconds);


                    tespitsuresi = (watch.ElapsedMilliseconds).ToString();






                    for (int i = 0; i < faces.Total; i++)


                    {


                        CvRect r = faces[i].Value.Rect;


                        CvPoint center = new CvPoint


                        {


                            X = Cv.Round((r.X + r.Width * 0.5) * olcek),


                            Y = Cv.Round((r.Y + r.Height * 0.5) * olcek)


                        };


                        int radius = Cv.Round((r.Width + r.Height) * 0.25 * olcek);


                        resim.Circle(center, radius, surat, 3, LineType.AntiAlias, 0);


                    }


                }




                return resim;


            }
Kodumuzu açıklayalım: başta using içerisinde kullanacağımız şeyleri belirtiyoruz,çünkü wrapperımızın otomatik çöp toplama özelliği yok, yani nesnelerle işimiz bittiğinde nesneler otomatik olarak silinmiyor, bellekte kalmaya devam ediyor. Bu OutOfMemory hatalarına yol açabilir. using bloğunun  bittiği yerde using parantezlerinin içine yazılan değişkenler otomatik olarak dispose edilir (bellekten silinir).

İkinci using bloğunun içinde resmi küçültüyor ve gri tonlamaya çeviriyoruz. EqualizeHist() fonksiyonu resmin histogramını düzenleyerek ışıklandırmanın etkilerini azaltıyor. Bu sayede daha iyi sonuçlar elde ediyoruz.

Bir alt kısımda ise yüz tanıma işlemi gerçekleşiyor ve yüzlerin bulunduğu koordinatlar daha sonra işaretleyip kullanıcıya göstermek için alınıyor. Bu örnekte kullandığımız haar cascade'ini google aracılığıyla bulup programınızın exe'sinin bulunduğu konuma atmalısınız.


Kodun en sonundaki for döngüsünde küçük resim üzerinde tespit edilen suratların koordinatları ile büyük resim üzerinde suratların etrafına çember çiziliyor. Butonumuza bu fonksiyonu çağırmak için kodu ekleyerek programımızı bitirelim.

pictureBox1.Image = BitmapConverter.ToBitmap(yuzAlgila(resimipl));


Kodumuzun son hali şöyle olmalı;

Çalıştırmayı deneyelim;


Kodumuz çalışıyor! Bu aşamaya kadar gelebildiyseniz tebrikler! 

Bir sonraki yazımda SURF algoritmasını kullanarak nesne tespit etmeyi anlatacağım. Okuduğunuz için teşekkürler.

22 yorum:

  1. Dostum anlatım için ağzına sağlık nesne tanımayı ne zaman anlatacan

    YanıtlaSil
    Yanıtlar
    1. Cevat bey nesne tanima ile bir gelisma yakalayabildiniz eger okeyse paylasirsaniz sevinirim
      Saygilarimla

      Sil
  2. Merhabalar hocam ben bu örneği yazdım fakat .xml satırında haarcascade ile ilgili satırdasarı renkli bir hata veriyor tam olarak ne yapmalıyım yardımcı olursanız çok sevinirim..

    YanıtlaSil
  3. using OpenCvSharp.MachineLearning; bu kısımda hata veriyor neden acaba yardımcı olur musunuz ?

    YanıtlaSil
  4. Bu yorum yazar tarafından silindi.

    YanıtlaSil
    Yanıtlar
    1. using OpenCvSharp.Extensions;
      bunu kullanıp çözüme ulaştım. sen de dene istersen.

      Sil
    2. Bu yorum yazar tarafından silindi.

      Sil
    3. Bu yorum yazar tarafından silindi.

      Sil
  5. Opencv kutuphanesini tam yuklememissin

    YanıtlaSil
  6. CvSeq faces = Cv.HaarDetectObjects(kucukresim, cascade, storage, ScaleFactor, MinNeighbors, 0, new CvSize(30, 30));
    Satırında HaarDetectObjects'de hata gösteriyor.

    YanıtlaSil
    Yanıtlar
    1. aynı hata bendede var düzletebildinmi acaba ?

      Sil
    2. CvSeq faces = Cv.HaarDetectObjects(kucukresim, cascade, storage, ScaleFactor, MinNeighbors, 0, new CvSize(30, 30), new CvSize(80, 80));

      Sil
  7. Ben sizler gibi ileri seviyede degilim sizlerin geldigi asamaya gelmem icin sanirim bu calisma icin uzun sure ugrasmam gerekecek,Rica etsem gelmis oldugunuz sondurmu exe sorce codlariyla benimle paylasabilirmisiniz paylasirsaniz inanin cok sevinirim

    Saygilarim

    YanıtlaSil
  8. CvSeq faces = Cv.HaarDetectObjects(kucukresim, cascade, storage, ScaleFactor, MinNeighbors, 0, new CvSize(30, 30));
    HaarDetectObjects objesinde hata alıyorum hatanın nedenini çözemedim kodlar tamamen aynı

    YanıtlaSil
    Yanıtlar
    1. CvSeq faces = Cv.HaarDetectObjects(kucukresim, cascade, storage, ScaleFactor, MinNeighbors, 0, new CvSize(30, 30), new CvSize(80, 80));

      Sil
  9. Merhabalar bende Project > Manage NuGet Packages secenegi yok nasıl yapabılırım ?vs 2010 ultımate kullanıyorum

    YanıtlaSil
  10. kütüphaneyi indirmemize rağmen machine learning de hata veriyor ve haarcascade kodunu google aracılığı ile bulup exe ye ekleyin deniyor ama binlerce satırlık bir code nasıl olacak

    YanıtlaSil
  11. Bu yorum bir blog yöneticisi tarafından silindi.

    YanıtlaSil
  12. Bu yorum yazar tarafından silindi.

    YanıtlaSil
  13. OpenCvSharp Error hatası ile opencv_core240 yüklenemedi hatası alıyorum. ne yapmalıyım. lütfen yardım... :(

    YanıtlaSil
    Yanıtlar
    1. bu hatayı ben de alıyorum, çözüme ulaşabildiniz mi?

      Sil
  14. editör içinde de
    Additional information: 'OpenCvSharp.CvInvoke' tür başlatıcısı özel durum döndürdü.
    hatası alıyorum aynı problem için.

    YanıtlaSil