776 kez okundu 776 kez okundu
Ara 092018
 
777 kez okundu

OpenCV ile Yüz Tanıma Bölüm 2

OpenCV Yüz Tanıma 2

Bu bölümde 3 ayrı betik kullanıyoruz:
1- veri toplama: 01_face_dataset.py
2- eğitim: 02_face_training.py
3- uygulama: 03_face_recognition.py

Orijinal kodlara https://www.hackster.io/mjrobot/real-time-face-recognition-an-end-to-end-project-a10826 adresinden ulaşabilirsiniz.

Ben veri kümesini yeniden oluşturdum. Türkçe karakterlerin görüntülenebilmesi için gerekli düzenlemeyi yaptım ve bazı mesajları Türkçeleştirdim.

İlk betikte input() komutunu # ile devre dışı bıraktım. Yeni bir yüz tanıtırken face_id sayısını doğrudan tanımladım. Örneğimizde 4 yüz tanımlı. Her yüz için 30 kare dataset klasörüne kaydedildi. Siz de kendi verilerinizi kaydetmeli ve eğitmelisiniz.

İlk betiğimizde cv2 ve os kütüphanelerini kullanıyoruz.

Görüntüleri webcam üzerinden elde edeceğiz. Görüntülerimizin eni 640, yüksekliği 480 piksel olarak tanımlandı (satır 5 ve 6).

7 nolu satırda cepheden yüz sınıflandırıcısını tanımlıyoruz.

face_id yüz görüntülerini eğiteceğimiz kullanıcı numarasını belirtiyoruz. Eğer input() satırını kullanmak isterseniz 9.satırın başındaki # işaretini silip, 10. satırın başına # eklemelisiniz.

count değişkenini görüntü sayısını takip etmek için kullanacağız.

Kayıt işlemlerimiz 15. satırdaki sonsuz while döngüsüyle başlıyor.

16. satırda kamera görüntüsünü alıyoruz. ret değişkeni işlevsizdir. Bu değişken video dosyasından okuma yaparken işimize yarıyor.

Görüntü karesini griye çevirip içindeki yüzleri saptıyoruz. (Satır 18 ve 19.)

Aslında her karede sadece 1 kişiye ait tek bir yüz bulunmalı. Yine de burada bir döngü kullanıyoruz. Aslında döngüdeki enbüyük dikdörtgeni seçsek daha doğru olurdu. Ama kodu gereksiz yere uzatmamak için bu tür ayrıntılara girmiyoruz.

Yakalanan her yüz için count değerini 1 arttırıyor (satır 22) ve yüz görüntüsünü dataset klasörüne kaydediyoruz. Kaydedilen görüntünün boyutları yüzün boyutları ile aynı. Yani webcam tarafından yakalanan görüntünün tümünü kullanmıyoruz. (Satır 24)

25.satırda kamera görüntüsünü (tamamını) ekrana yansıtıyoruz.

k değişkeni ile 100 milisaniye içinde bir tuşa basılıp basılmadığını kontrol ediyoruz.

Eğer ‘Esc’ tuşuna basıldıysa (sayısal karşılığı 27 olan tuş) döngüyü kırıyor, basılmadıysa bu kez count değerinin 30’u aşıp aşmadığını denetliyoruz. Sayı 30’u aştıysa döngüyü yine kırıyoruz. Çünkü her kişi için 30 görüntü kaydediyoruz.

Son iki satırda kamerayı serbest bırakıyor ve belleği temizliyoruz.

“dataset” klasörünün içine bakarsanız, verdiğiniz kullanıcı numarasına karşılık gelen 30 adet resim göreceksiniz.

Kullanıcı sayısını (yüz görüntülerini kaydedeceğiniz kişi sayısını) istediğiniz kadar arttırabilirsiniz. (Elbette en az bir kişi olmalı!)

Verilerimizi tamamladığımızda işimiz bitmiyor. Şimdi bu veri kümesini eğitmemiz lazım. İkinci betiğimizin işlevi bu!

İkinci -eğitim- betiğimizde opencv ve os yanısıra numpy ve pillow kütüphanelerini kullanıyoruz.

Veri klasörümüzün adı ‘dataset’. Bu bilgiyi path değişkeninde tutuyoruz.

Veri kümemizin eğitimini cv2.face.LBPHFaceRecognizer_create() komutuyla oluşturduğumuz recognizer (satır 7) üzerinden yapacağız.

Görüntülerdeki yüz alanlarını ayırmak için yine ‘haarcascade_frontalface_default.xml’ filtresinden yararlanacağız. Filtre değişkenimizin adı: detector. (satır 8)

Görüntü etiketlerimizi almak için getImagesAndLabels() fonksiyonunu kullanıyoruz.

ImagePaths listesi, path klasörü içinde yer alan dosyaların listesidir.

faceSamples listesi yüz görüntülerini, ids listesi ise her bir görüntünün etiketini tutacak.

imagePaths listesindeki her bir elemanı (dosya adını) kullanarak ilgili resmi okuyup griye dönüştürüyor ve PIL_img değişkenine atıyoruz (satır 15). Sonra bu görüntüleri 8 bitlik pozitif tamsayılardan oluşan bir numpy dizisi (array) haline dönüştürüyoruz (satır 16).

17 numaralı satırda, dosya adından kişi numarasını ayırıp, bir tam sayı olarak id değişkenine atıyoruz.

img_numpy görüntü numpy dizisinde bulunan yüz alanlarını bulup faces listesine atıyoruz. Yüzleri içeren listeyi döngüye sokup her bir görüntüyü faceSamples, ona karşılık gelen etiketi ise ids listesine ekliyoruz.

Fonksiyonumuz faceSamples ve ids listelerini döndürüyor.

24 numaralı satırda faces ve ids listeleri oluşturuluyor.

25 nolu satırda ise veri kümemizi eğitiyoruz.

Eğitilmiş veriseti bilgileri 27. satırda trainer klasörü içindeki trainer.yml dosyasına kaydediliyor. Bu dosyayı son betiğimizdeki görüntüleri sınıflandırırken kullanacağız.

Son betiğimiz şöyle:

Kamera görüntülerindeki yüzleri yakalayıp kime ait olduklarını belirten betiğimiz bu. Kullanacağımız kütüphaneler opencv, numpy ve pillow.

print_utf8_text() fonksiyonunu bir önceki yazımda anlatmıştım. Türkçe karakterleri bu fonksiyon aracılığıyla bastırıyoruz.

Yüz tanıma nesnemiz recognizer‘a trainer.yml dosyası aracılığıyla eğitilmiş verisetimizi yüklüyoruz (satır 18 ve 19).

Canlı kamera görüntülerindeki yüzleri de yine haarcascade_frontalface_default.xml filtresi aracılığıyla yakalayacağız. Filtre değişkenimiz faceCascade (satır 20 ve 21).

22 nolu satırda orijinal betikte kullanılan font tanımlanıyor. Biz bu fontu da kullanacağız.

Kişi numaraları id değikeninde tutulacak. (Satır 24)

Etiketleri (isimleri) ise names listesiyle tanımlıyoruz.

Web kamerasının görüntüsünü cam değişkenine aktarıyoruz ve görüntü boyutlarını 1000 ve 800 piksel olarak ayarlıyoruz. (Bu değerleri 640 ve 480 olarak da bırakabilirdik.)

minW ve minH değişkenleri yakalanan yüz dikdörtgenlerinin boyutu için alt sınır değerleridir (satır 33 ve 34). Bu değerleri kendi ortamınıza göre değiştirebilirsiniz.

35 nolu satırda sonsuz döngümüz başlıyor.

36. satırda kamera görüntüsünü okuyor, 38. satırda bu görüntüyü grileştiriyoruz.

40 nolu satırda görüntü karesindeki tüm yüzleri yakalıyor; 46. satırda ise bu yüz dikdörtgenlerini bir döngü içinde işleme sokuyoruz.

recognizer.predict() metodu id ve confidence değerlerini döndürüyor. id kişi numarası; confidence ise yapılan saptamanın tahmini doğruluk oranıdır (satır 48).

id ve confidence değişkenlerini print için uygun hale getiriyoruz (satır 50-55).

58 nolu satırda kişi ismini UTF-8 kullanarak (Türkçe karakterleri doğru şekilde yansıtarak), 60 nolu satırda ise belirtilen kişinin tahmini doğruluk oranını standart font ile görüntüye işliyoruz.

Görüntünün ekrana yansıtılması 62 nolu satırda.

Döngümüz yine Esc veya q tuşlarından birine basıldığında kırılıyor.

Döngü kırıldığında web kamerayı sonlandıyor ve belleği temizliyoruz (satır 68-69).

Bu betiğin çalışmasını gösteren örnek video aşağıda.

Bu yazı, açıklamaları olabildiğince kısa tutsam da biraz uzunca oldu. Umarım yeterince açıklayıcıdır. Sorularınız için yorum alanını kullanabilirsiniz.

Bir sonraki yazımda yine yüz tanıma olacak. Ancak veri kümemizi oluşturmak ve eğitmek için farklı yöntemler kullanacağız.

Beni izlemeye devam edin.

Ahmet Aksoy

  16 Yanıt - “OpenCV ile Yüz Tanıma Bölüm 2”

  1. Öncelikle güzel bilgileriniz için teşekkür ederim. Ben denedim 2 kişinin yüzü için. Ama 2 kişinin yüzünü alırken 2 kişinin yüzü toplam 30 tane resim oluyor. Sebebi ne olabilir acaba? Bu bilgilerden yararlanarak proje olarak öğrencilerin günlük yüzlerindeki duygu hislerini alıp veri tabanına atmak istiyorum. İnşallah yaparım.

    • Teşekkür ederim.
      30 resim sınırı betiğin içinde tanımlı. İsterseniz bu sayıyı değiştirebilirsiniz.
      Yüz ifadelerini veritabanına atmak için onları önceden klasifiye etmeniz lazım: gülüyor, ağlıyor, üzgün, kızgın, vb. Bu sınıflandırmayı tek tek resimlere uygulamanız lazım. Bu nedenle betiğin resim üretme yöntemi işinize pek fazla yaramayabilir.
      Bu konu için “sentiment analysis”-“duygu analizi” konusunu araştırmanızda yarar var.

  2. Bide kodda eğitirken kişileri tek tek mi alacağız acaba?

    • Hayır. Eğitim sırasında çalışma klasörünüzün altında açtığınız dataset isimli klasörün içinde yer alan tüm kullanıcı görüntüleri birlikte eğitilir.
      Her kullanıcıyı tanıtırken ayrı bir numara vermeniz lazım.
      dataset klasörü içindeki dosya sayısı (resim) kullanıcı sayısı * 30 kadar olmalı.
      2 kullanıcı içi 60, 3 kullanıcı için 90 vb.
      Sadece 60 dosya varsa, tek bir kullanıcı tanıtmışsınız demektir.

  3. Eğitme kodunda aşağıdaki hatayı alıyorum acaba ne olabilir ki?
    C:\ProgramData\Anaconda3\python.exe C:/Users/……../PycharmProjects/udemyegitim/yuz3.py

    [INFO] Training faces. It will take a few seconds. Wait …
    Traceback (most recent call last):
    File “C:/Users/resul-melike/PycharmProjects/udemyegitim/yuz3.py”, line 25, in
    faces,ids = getImagesAndLabels(path)
    File “C:/Users/resul-melike/PycharmProjects/udemyegitim/yuz3.py”, line 16, in getImagesAndLabels
    PIL_img = Image.open(imagePath).convert(‘L’) # convert it to grayscale
    File “C:\ProgramData\Anaconda3\lib\site-packages\PIL\Image.py”, line 2609, in open
    fp = builtins.open(filename, “rb”)
    PermissionError: [Errno 13] Permission denied: ‘dataset\\User’

    Process finished with exit code 1

    • Windows dataset klasörüne erişim hakkınız olmadığını söylüyor.
      1- dataset klasörünü çalışma klasörünüzün içinde açmanız lazım
      2- dataset klasörü doğru yerdeyse ve hala yetki sorununuz varsa, programı “super user” olarak kullanmayı deneyin.

  4. videodaki % li ifadeler nedir acaba ?

    • Tahmini doğruluk oranları.

      • bağışlayın anlıyamadım doğruluk derken neyi kastediyorsunuz ?

        • 48. satırda iki değer geri döndürülüyor:
          id, confidence = recognizer.predict(gray[y:y + h, x:x + w])

          id: tahmini olarak bulunan kişiye ait kimlik no
          confidence: Güvenilirlik oranı.
          Eğer bu oran %100 ise, hesaplara göre yanılma payı yok demektir. Ama %100 oranı tercih edilmez. Öğrenme değil, ezberleme olarak kabul edilir. Ezberleme durumunda, farklı veriyi değerlendirirken yanılma payı çok daha büyük olur.
          %95 üzerinde olan ama %100’den küçük olan doğruluk oranları tercih edilir.
          Diyelim ki kendine ve arkadaşlarına ait görüntülerle sistemini eğittin.
          Veri setinde yer almayan bir başka resmi verip kime ait olduğunu sorguladığında, %80 yanıtı aldıysan, sonuç %80 ihtimalle adı verilen kişiye aittir anlamı taşır.

  5. Traceback (most recent call last):
    File “C:/Users/asus/PycharmProjects/untitled/proje.py”, line 18, in
    faces = face_detector.detectMultiScale(gray, 1.3, 5)
    cv2.error: OpenCV(3.4.4) C:\projects\opencv-python\opencv\modules\objdetect\src\cascadedetect.cpp:1698: error: (-215:Assertion failed) !empty() in function ‘cv::CascadeClassifier::detectMultiScale’

    [ WARN:0] terminating async callback

    Böyle bir sorunla karşılaştım neden olabilir

    • “Cascades/haarcascade_frontalface_default.xml” dosyasına ulaşılamıyor. Bu dosyaları github üzerinden indirip bilgisayarınıza kopyalamış olmalısınız. İlgili linkler yazının ilk bölümünün sonunda yer almaktadır.

      • Son kısımda kodu çalıştırdığımda kamera açılıyor,bir şey görmediğinde kamera açık kalmaya devam ediyor ama kendi yüzümü ya da herhangi birinin yüzünü gösterdiğimde ;

        Traceback (most recent call last):
        File “C:/Users/asus/PycharmProjects/untitled/iremovic.py”, line 56, in
        img=print_utf8_text(img,(x + 5, y – 25),str(id),color)
        File “C:/Users/asus/PycharmProjects/untitled/iremovic.py”, line 8, in print_utf8_text
        font = ImageFont.truetype(fontName, 24) # select font
        File “C:\Users\asus\Anaconda3\lib\site-packages\PIL\ImageFont.py”, line 260, in truetype
        return FreeTypeFont(font, size, index, encoding, layout_engine)
        File “C:\Users\asus\Anaconda3\lib\site-packages\PIL\ImageFont.py”, line 143, in __init__
        self.font = core.getfont(font, size, index, encoding, layout_engine=layout_engine)
        OSError: cannot open resource

        Process finished with exit code 1

        hatası verip kamera direkt kapanıyor,ne yapabilirim

        • def print_utf8_text(image, xy, text, color): # utf-8 characters
          fontName = ‘FreeSerif.ttf’ # ‘FreeSansBold.ttf’ # ‘FreeMono.ttf’ ‘FreeSerifBold.ttf’
          ….
          Windows altında çalıştığınız için ‘FreeSerif.ttf’ dosyasını bulamıyor.
          Onun yerine Tahoma.ttf, Verdana.ttf, Times.ttf gibi Windows’a özgü dosyaları deneyebilirsiniz.

          • Öncelikle bu paylaşım ve cevaplarınız için çok teşekkür ederim.
            Şöyle bir sorunla karşılaştım,datasette fotoğrafı bulunan kişilere %50 oranında tahminlerde bulunuyor ancak datasette olmayan kişilere bilinmiyor demiyor onlara da tahminlerde bulunuyor.
            Datasete daha çok fotoğraf ekleyerek bunun önüne geçebilir miyim,ya da başka ne yapabilirim?

        • Merhaba İrem hanım,
          Tanıttığınız kişilere ait fotoğraf sayısını olabildiğince çoğaltıp, gerekirse parametrelerle de oynayarak tanıma oranlarını %90’lara çektikten sonra, düşük tanıma oranlarını “bilinmiyor” şeklinde etiketlemek mümkün olabilir.
          Örnekte kişilere ait sadece 30’ar görüntü kullandık. Bu sayı olağanüstü derecede küçük. Bu sayıların en azından binlerle ifade edilebilmesi ve “augmentation” kullanılarak çoğullanması gerekir.
          Elbette verisetini büyüterek yapılan eğitimden sonraki sorgulamalar da daha fazla işlem gücü gerektirecektir. Bunun da farkında olmak gerekir.

 Bir yanıt bırakın

Bu HTML tagleri ve özellikleri kullanabilirsiniz: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">

(gerekli)

(gerekli)

This site uses Akismet to reduce spam. Learn how your comment data is processed.

%d blogcu bunu beğendi:
Önceki yazıyı okuyun:
OpenCV ile Yüz Tanıma Bölüm 1

OpenCV ile Yüz Tanıma Bölüm 1 Yüz tanıma biraz geniş kapsamlı bir konu. Öncelikle incelediğimiz görselde bulunan olası "yüz"leri, daha...

Kapat