Yazılım Mimarileri ve Tasarım Desenleri Üzerine

EmguCV – Multiple Face Recognition(Çoklu Yüz Tanıma)

EmguCV

Merhaba,

Görüntü işleme teknolojilerinde nesnelerin tanımlanması, hareketlerin algılanması yahut tüm bunların yanında psikolojik testler veya geleceğe dönük tahminsel oranların elde edilmesi mümkündür. Amma velakin nitelik olarak kompleks ihtiyaçlara giden bu süreç daha da kompleks çalışmalar gerektirmektedir. İşte bu bilinçle yola çıkarak bu içeriğimizde Çoklu Yüz Tanıma diye nitelendirdiğimiz Multiple Face Recognition teknolojisi üzerine konuşuyor, istişare ediyor ve teknik olarak ele alıyor olacağız.

Evet… Şimdi sizlerin eşliğinde bu makalede yazılımsal olarak yüz tanıma üzerine bir süreç geçireceğiz. Herşeyden önce yüz tanıma kavramı üzerinde biraz durup yapacağımız işi daha da netleştirecek, ardından nasıl bir yaklaşım ve algoritma sergileyeceğimiz üzerine istişare ederek son adımda konuyu teknik boyutta ele alıp makalemizi sonlandıracağız.

Öncelikle yüz tanımlama/algılama/bulma ile yüz tanıma arasındaki farkı çizmekte fayda var.

Yüz tanımlama, elimizdeki kaynak görüntü üzerinde yaptığımız tarama sonucu bir yüz ya da yüze benzer tüm ifadeleri algılayarak üzerinde işlem yapmaktır. Yani o yüzün kim olduğu, kime ait olduğu o anlık mevzu bahis değildir. Bu konu üzerinde yapmış olduğumuz önceki şu ve şu çalışmalarıma göz atabilirsiniz.

Yüz tanıma ise, kaynak üzerinde tespit edilen yüzün kime ait olduğunu bulabilmek yani adı üzerinde tanımaktır. Bu yüz, “Hilmi mi?”, “Rıfkı mı?”, “Ayşe mi?” yoksa “Muiddin abi mi?” vs. sorularının cevabını verebilmektir. Bu işlem için yüzün tanımlanması/algılanması/bulunması gereken ilk öncülken, ardından ikinci öncül bu yüzün kime ait olduğu üzerine yapılan çalışma gerçekleşerek tanıma aşaması söz konusu olmakla süreç işlemektedir.

Yüz tanımlama ile tanıma arasındaki farka değindikten sonra heyecanlı bir şekilde sorduğunuz Peki Nasıl Bir Algoritma İzleyeceğiz? sorunuzu duyar gibiyim…

Oo halde hadi gelin şimdide yaklaşımımız üzerine konuşuyor olalalım…

Nasıl Bir Yaklaşım? Nasıl Bir Algoritma?

İster yazılım olsun ister herhangi bir canlı farketmeksizin gördüğü birşeyi tanıması için o şeyi önceden tanımlamış olması gerekmektedir. Yani önceden o şeye bir isim, sıfat, değer yahut sembolik bir ifade vermiş olması gerekmektedir ki sonradan gördüğünde hafızasında o şeyle ilişkili ifade canlansın ve o ifadeyle o şeyi nitelendirebilsin…

Bir insan gördüğü herhangi bir masanın beynindeki masa şeması ile eşleşmesi ve o şemaya “masa” değerini vermesi sonucu ilgili nesneyi gördüğünde onu çok rahat bir şekilde tanımlayabilmesi ve tanıyabilmesi ve hatta tarif edebilmesi işte önceden o nesneyi hafızasına bir şekilde kaydetmesinden kaynaklanmaktadır. Aynı mantıkla bu başka bir insan içinde geçerlidir. Eğer ki ben müneccim değilsem eğer Muhiddin abiyi gördüğüm anda onun o iğrenç suratının beynimdeki şemayla uyması ve onun “Muhiddin” ismiyle tanımlanması neticesinde onu tanıyabiliyor ve gördüğüm zaman ondan kaçabiliyorum…

Her neyse…

İşte bir yazılımda söz konusu olduğunda tanıyacağı nesneyi mukayese edebilecek bir hafızaya sahip olması gerekmektedir. Yani yazılımın beni görüp, algılayıp, ‘aaAa bu Gençay değil mi layhn’ diyerek tanıyabilmesi için önceden hafızasında benimle ilgili verileri tutuyor olması gerekmektedir ki o verilerle mukayese sonucunda gördüğü şeyin ben olup olmama ihtimalini değerlendirebilsin.

Bu demek oluyor ki, yazılımın ha deyince Allah vergisi bir şekilde kişiyi görür görmez kimin Kamil kimin Coni, kimin Abdülrezak olduğunu bilmesi bir hayalden ibaretmiş.

Burada kişileri bizim yazılıma, onun anlayacağı bir dilde, uygun bir formatta tanıtmamız gerekmektedir. Aslında makalemizin ileriki satırlarında teknik olarak ele alacağız ama şimdiden bu konuya kısaca değinmekte fayda var. Yapacağımız işlem, yazılımın tanımasını istediğimiz kişilerin yüz profillerinden en az iki adet olmak üzere farklı açılardan alınmış görüntülerini bir xml formatında uygun şablonda tutmaktan ibarettir. Yazılım tanımladığı yüzleri bu xml veri kaynağındaki değerlerle kıyaslayarak o yüzün kime ait olduğunu %80’lik bir doğruluk payıyla bulabilecektir. Tabi burada ne kadar farklı açıdan resim olursa kişi üzerinde tahmin oranı artacak ve doğruluk payı yükselecektir.

Yüz tanıma işlemi için EmguCV’de(OpenCV’de de) Eigenfaces, Fisherfaces ve LBPH olmak üzere üç adet algoritma mevcuttur. Bu algoritmalar yukarıdaki paragrafta da bahsettiğim gibi hafızadaki görüntülerle o anki tanımlanan yüz arasındaki korelasyona bakarak tahmin işlevini gerçekleştirmektedirler. Ama burada terminolojik bir tezata düşmemek için düzeltmemiz gereken bir tarif vardır. Bu algoritmaların mukayese amaçlı kullanacağı yüz resimlerini bizler manuel olarak oluşturabilir ve xml formatına yazabiliriz. Ama bu işlem binlerce veri söz konusu olduğunda zahmetli olacağı için yazılıma yaptıracağız. İşte yazılımın kişilerin yüzlerini alıp, arka planda belirli bir hafızada depolamasına ve xml formatında bu resimleri organize etmesine “eğitim” denmektedir. Yani yazılımın yüzlere özel kendini eğitmesi söz konusu olacaktır.

Yukarıda bahsettiğimiz üç algoritmayı kısaca özetlemek gerekirse eğer;

Şimdi sıra teknik olarak EmguCV ile yüz tanıma işlemini ele almaya geldi. Bu güne kadar bu konuda yapmış olduğum çalışmalar neticesinde Business Recognition ve Classifier Train olmak üzere iki sınıf inşa etmiş bulunmaktayım. Bunlardan Classifier Train isimli olan sınıfımız yüz eğitiminden ve yüz tanıma algoritmasından sorumlu bir sınıftır. Business Recognition sınıfı ise Classifiew Train sınıfını refere etmekte ve eğitim süreciyle birlikte diğer tüm durumları kontrol ettiğimiz sınıftır. Bu iki sınıfın benzerlerini internette görebilirsiniz. Lakin ben sınıfları dahada geliştirerek dizin ve dosya koordinasyonu yapabilir hale getirmiş bulunmaktayım.

Haliyle bir örnek proje üzerinde seyredeceğimiz için gerekli tüm EmguCV entegrasyonu ve alt yapı çalışmasını önceki makalelerimize istinaden sizlere bırakmakla beraber yukarıda paylaştığım sınıfları projenize import etmeyi unutmayınız. Ayriyetten yapmış olduğum çalışmayı makalenin sonunda paylaşacağımıda bildirmek isterim.

1. Adım

Yüzlere Yazılımın Eğitilmesi

Bu işlem için “Business Recognition” sınıfındaki “SaveTrainingData” metodunu kullanmaktayız.

public bool SaveTrainingData(Image face_data, string FaceName)
        {
            try
            {
                string NAME_PERSON = FaceName;
                Random rand = new Random();
                bool file_create = true;
                string facename = "face_" + NAME_PERSON + "_" + rand.Next().ToString() + ".jpg";
                while (file_create)
                {
                    if (!File.Exists(Dizin + facename))
                        file_create = false;
                    else
                        facename = "face_" + NAME_PERSON + "_" + rand.Next().ToString() + ".jpg";
                }
                if (Directory.Exists(Dizin))
                    face_data.Save(Dizin + facename, ImageFormat.Jpeg);
                else
                {
                    Directory.CreateDirectory(Dizin);
                    face_data.Save(Dizin + facename, ImageFormat.Jpeg);
                }
                if (File.Exists(Dizin + XmlVeriDosyasi))
                {
                    bool loading = true;
                    while (loading)
                    {
                        try
                        {
                            docu.Load(Dizin + XmlVeriDosyasi);
                            loading = false;
                        }
                        catch
                        {
                            docu = null;
                            docu = new XmlDocument();
                            Thread.Sleep(10);
                        }
                    }
                    XmlElement root = docu.DocumentElement;
                    XmlElement face_D = docu.CreateElement("FACE");
                    XmlElement name_D = docu.CreateElement("NAME");
                    XmlElement file_D = docu.CreateElement("FILE");
                    name_D.InnerText = NAME_PERSON;
                    file_D.InnerText = facename;
                    face_D.AppendChild(name_D);
                    face_D.AppendChild(file_D);
                    root.AppendChild(face_D);
                    docu.Save(Dizin + XmlVeriDosyasi);
                }
                else
                {
                    FileStream FS_Face = File.OpenWrite(Dizin + XmlVeriDosyasi);
                    using (XmlWriter writer = XmlWriter.Create(FS_Face))
                    {
                        writer.WriteStartDocument();
                        writer.WriteStartElement("Faces_For_Training");
                        writer.WriteStartElement("FACE");
                        writer.WriteElementString("NAME", NAME_PERSON);
                        writer.WriteElementString("FILE", facename);
                        writer.WriteEndElement();
                        writer.WriteEndElement();
                        writer.WriteEndDocument();
                    }
                    FS_Face.Close();
                }
                return true;
            }
            catch (Exception ex)
            {
                return false;
            }

Bu metot tanımlanan yüzleri belirtilen kaynağa aktarma ve bunların yanında gerekli xml formatındaki veri setine ekleme görevinden sorumludur. Formumuzda bu işi yapmakla görevli olan olayımız ise aşağıdaki gibidir.

        private async void btnEgit_Click(object sender, EventArgs e)
        {
            await Task.Run(() =>
            {
                for (int i = 0; i < 10; i++)
                {
                    if (!recognition.SaveTrainingData(pictureBox2.Image, txtFaceName.Text)) MessageBox.Show("Hata", "Profil alınırken beklenmeyen bir hata oluştu.", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    Thread.Sleep(100);
                    lblEgitilenAdet.Text = (i + 1) + " adet profil.";
                }
            });
            recognition = null;
            train = null;
            recognition = new BusinessRecognition("D:\\", "Faces", "yuz.xml");
            train = new Classifier_Train("D:\\", "Faces", "yuz.xml");
        }

Görüldüğü üzere tanımlanan yüzler pictureBox2 nesnesine atanmaktadır. Haliyle yakalanan bu yüz resimleri SaveTrainingData metoduna gönderilmekte ve program yüzlere özel eğitilmektedirler. Ayrıca, recognition ve train referansları global tanımlandıkları için yeri gelince paylaşılacaktır.

2. Adım

Eğitilen Yüzlerle Tanımlanan Yüzü Kıyaslama

Bu adımda devreye Classifier_Train sınıfının Recognise metodu girecektir.

        public string Recognise(Image<Gray, byte> Input_image, int Eigen_Thresh = -1)
        {
            if (_IsTrained)
            {
                EigenObjectRecognizer.RecognitionResult ER = recognizer.Recognize(Input_image);
                if (ER == null)
                {
                    Eigen_label = "Unknown";
                    Eigen_Distance = 0;
                    return Eigen_label;
                }
                else
                {
                    Eigen_label = ER.Label;
                    Eigen_Distance = ER.Distance;
                    if (Eigen_Thresh > -1) Eigen_threshold = Eigen_Thresh;
                    if (Eigen_Distance > Eigen_threshold) return Eigen_label;
                    else return "Unknown";
                }

            }
            else return "";
        }

Bu metot, gönderilen image nesnesini hafızadakilerle kıyaslayarak eşleşen kaydın bilgilerini dönmektedir.

3. Adım

Tanımlanan ve Tanınan Yüzün Vurgulanıp İsminin Yazılması

Artık sıra formun load eventında çalışmaya geldi. Burada kamera görüntüsü alma, yüz tanımlama ve vurgulama işlemlerinin yanında yüz tanıma algoritmalarını devreye sokacak tetiklemeler yapılmaktadır.

        BusinessRecognition recognition = new BusinessRecognition("D:\\", "Faces", "yuz.xml");
        Classifier_Train train = new Classifier_Train("D:\\", "Faces", "yuz.xml");
        private void Form1_Load(object sender, EventArgs e)
        {
            Capture capture = new Capture();
            capture.Start();
            capture.ImageGrabbed += (a, b) =>
            {
                var image = capture.RetrieveBgrFrame();
                var grayimage = image.Convert<Gray, byte>();
                HaarCascade haaryuz = new HaarCascade("haarcascade_frontalface_alt2.xml");
                MCvAvgComp[][] Yuzler = grayimage.DetectHaarCascade(haaryuz, 1.2, 5, HAAR_DETECTION_TYPE.DO_CANNY_PRUNING, new Size(15, 15));
                MCvFont font = new MCvFont(FONT.CV_FONT_HERSHEY_COMPLEX, 0.5, 0.5);
                foreach (MCvAvgComp yuz in Yuzler[0])
                {
                    var sadeyuz = grayimage.Copy(yuz.rect).Convert<Gray, byte>().Resize(100, 100, INTER.CV_INTER_CUBIC);
                    //Resimler aynı boyutta olmalıdır. O yüzden Resize ile yeniden boyutlandırma yapılmıştır. Aksi taktirde Classifier_Train sınıfının 245. satırında hata alınacaktır.
                    pictureBox2.Image = sadeyuz.ToBitmap();
                    if (train.IsTrained)
                    {
                        string name = train.Recognise(sadeyuz);
                        int match_value = (int)train.Get_Eigen_Distance;
                        image.Draw(name + " ", ref font, new Point(yuz.rect.X - 2, yuz.rect.Y - 2), new Bgr(Color.LightGreen));
                    }
                    image.Draw(yuz.rect, new Bgr(Color.Red), 2);
                }
                pictureBox1.Image = image.ToBitmap();
            };
        }

Şimdi projemizi derleyip nasıl çalıştığına göz atalım.

Peder Beyle deneme yaperken 🙂

Peder Beyle ikinci denememiz 🙂

Örnek projeyi indirmek için buraya tıklayınız.

Okuduğunuz için teşekkür ederim…
Hepinize iyi çalışmalar, sonraki yazılarımda görüşmek dileğiyle…

Exit mobile version