Python Face Identifier Yapımı

Hacknology

Kıdemli Üye
25 Eki 2015
2,712
11
rm -rf /
Merhaba, bugünkü yazımızda python ile yüz okumayı ve tanımayı anlatmaya çalışacağım. Bunun için bir takım kütüphanelere ihtiyacımız olacak. Önce bu kütüphaneleri tanıyalım.
opencv-python-windows.jpg

numpy:
NumPy, numerical python, oldukça büyük bir bilimsel işlem kütüphanesidir. Mantıktan cebire, dizilerden istatiki işlemlere kadar birçok işlemi yapmanızı sağlar.
opencv:
OpenCV bildiğiniz üzere görselleri işlememize yarayan oldukça güçlü bir kütüphane
pickle:
Oluşturacağımız çıktıyı dosyaya yazdırmamızı sağlayan bir araç.

Kütüphanelerimizi import edelim
Kod:
import numpy as np
import cv2
import pickle

Şimdi bir sınıf oluşturup kodlamaya geçmeden önce yapacaklarımdan bahsedeyim; Öncelikle kameradan bir video kaydı alacağım, sonra bu video kaydındaki yüzleri tanımlayacağım. Sonra kendi yüzümü ve bir takım ünlülerin yüzünü train edip bir dataset oluşturacağım, hemen ardından video kaydındaki yüzün oradaki herhangi bir yüzle eşleşip eşleşmediğini kontrol edeceğim. Eşleşme varsa bu yüzün sahibinin adını ekrana yazdıracağız.

Buraya kadar her şey tamam ise sınıfımızı oluşturup kodlamaya başlayalım.

Kod:
class faceID(object):
	def __init__(self):
	self.cap = cv2.VideoCapture(0)
	
	def video_capture(self):
		while 1:
			ret, frame = self.cap.read()
			cv2.imshow('video', frame)
			if cv2.waitKey(20) & 0xFF == ord('q'):
				break
		self.cap.release()
		cv2.destroyAllWindows()

Bu sınıfı çağırdığımızda video kaydının başladığını göreceğiz. Şimdi videodaki yüzleri tespit edelim, bunun için opencv nin bize sunduğu classifier'ları kullanacağız. Kameraya direkt bakacağımdan "haarcascade_frontalface_alt2.xml" benim için uygun bir tercih olacaktır. Üstteki sınıfımıza dönelim ve bazı değişiklikler ekleyelim.
Kod:
self.face_cascade = cv2.CascadeClassifier('cascades\\data\\haarcascade_frontalface_alt2.xml')
Bu parçacığı init kısmına ekledikten sonra alttaki fonksiyonuma geçiyorum. Şimdi daha kolay okuyabilmek için video kaydını siyah-beyaza dönüştüreceğim, ardından tespit ettiğim yüzün koordinatlarını bulup etrafına bir kare çizeceğim. Tüm bunları yaparken bana openCV kütüphanesi yardımcı olacak.
Kod:
self.gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)#siyah beyaza çevirir.
self.faces= self.face_cascade.detectMultiScale(self.gray, scaleFactor=1.5, minNeighbors=5)#yüzleri tespit eder
for (x,y,w,h) in self.faces:#yüzlerin koordinatlarını alıyorum
				
	self.roi_gray = self.gray[y:y+h, x:w+w]
	color=(95,234,249)
	stroke=2
	end_cord_x = x + w
	end_cord_y = y + h
	cv2.rectangle(frame, (x, y), (end_cord_x, end_cord_y), color, stroke)#bu koordinatlara bir kare çiziyorum

Bu değişikliklerden sonra yüzümüzün etrafında bir kare oluşacaktır, mantıken ne yaptığımız zaten üst koddaki yorum satırlarında yazılı.

Şimdi, bu yüzü diğer yüzlerden ayırmaya çalışacağım. Bu yüzden birkaç ünlünün fotoğrafını kullanacağım.
mikhail tal:
main-qimg-cdc26f7e5b8ba70bece2c42a17c1ed27.webp

rock:
the-rock-dwayne-johnson-ring-retour-sur_06f4f57e-ee0a-11e6-b62a-376882c41036.jpg

bonnie tyler:
51RHC5ZQ7CL._SX425_.jpg

Atatürk -kalbimizde...-:
ataturk-un-olumu-2038.png

Tüm bu üstteki isimlere dair 5 er tane fotoğraf indirdikten sonra "images" adı altında bir klasör açıyorum ve bu klasörün içine hepsinin isminde 5 klasör daha açıyorum. Her klasöre ilgili ünlüye ait 5 fotoğraf atıyorum ve klasör yapımız şu şekilde oluyor.
Kod:
-images
|
|
|
|___>rock
	|
	|
	|__>fotoğraflar
|
|
|
|___>mikhail tal
		|
		|
		|___>fotoğraflar
|
|
|
|___>Atatürk
.
.
.
Şeklinde bir dosya yapımız olacaktır. Şimdi bu dosya yapısından fotoğrafları ve isimleri işleyelim. Yeni bir script yazacağım bu işlem için, tekrardan en başta kütüphanelerimizi içe aktaralım.
Kod:
import os
Şimdilik bu yeterli, lazım oldukça ekleme yapacağım. Bir sınıf oluşturalım ve kodumuzu yazmaya başlayalım.
Kod:
import os
class train_image(object):
	def __init__(self):
		self.base_directory = os.path.dirname(os.path.abspath(__file__))#dizine ilerle
		self.image_directory = os.path.join(self.base_directory, "images")
	def train(self):
		for root, dirs, files in os.walk(self.image_directory, "images"):#dosyadaki diğer dosyaları bulalım. Arka planda bu;
			#C:\Users\Hackno\Desktop\eye_final>py -3 konu_.py
			#C:\Users\Hackno\Desktop\eye_final\images ['atatürk', 'mikhail tal',...] []
			#C:\Users\Hackno\Desktop\eye_final\images\atatürk [] ['a..]
			#şeklinde bir çıktı döndürür			
			for self.file in files:
				if self.file.endswith("png") or self.file.endswith("jpg"):#png ilee jpg ile biten, yani resim dosyalarını bulalım
					self.path = os.path.join(root, self.file)#
					self.label = os.path.basename(os.path.dirname(self.path)).replace(" ", "-").lower()
					print(self.path, self.label)#Fotoğraf adını ve o fotoğrafın bulunduğu klasörü (yani şahsın ismini) yazdırdım.
train = train_image()#sınıfı çağırıyoruz...
train.train()




Kodu çalıştırdığımıda aldığımız çıktı bu;

Kod:
C:\Users\Hackno\Desktop\eye_final\images\michael tal\Mikhail-Tal-300x168.jpg mikha
il-tal
C:\Users\Hackno\Desktop\eye_final\images\michael tal\tal1.png mikhail-tal
C:\Users\Hackno\Desktop\eye_final\images\rock\WHDQ-512469260.png rock
C:\Users\Hackno\Desktop\eye_final\images\rock\WHDQ-512469283.jpg rock
C:\Users\Hackno\Desktop\eye_final\images\rock\WHDQ-512469299.jpg rock
C:\Users\Hackno\Desktop\eye_final\images\rock\WHDQ-512469316.jpg rock
C:\Users\Hackno\Desktop\eye_final\images\rock\WHDQ-512469340.png rock
C:\Users\Hackno\Desktop\eye_final\images\Hackno\my-image.png utku
C:\Users\Hackno\Desktop\eye_final\images\Hackno\0xhacknology.png utku
C:\Users\Hackno\Desktop\eye_final\images\Hackno\0xhacknology.png utku
C:\Users\Hackno\Desktop\eye_final\images\Hackno\0xhacknology.png utku
C:\Users\Hackno\Desktop\eye_final\images\Hackno\0xhacknology.png utku

Şimdi bu yüzleri işlememiz gerekiyor. Neyse ki ekstra bir machine learning kütüphanesi kullanmama gerek yok, şimdiki kütüphaneler işe yarayacaktır. init fonksiyonuma son kez dönüyorum ve editliyorum
Kod:
class train_image(object):
	def __init__(self, c_path): #c_path = classifier path 
		self.base_directory = os.path.dirname(os.path.abspath(__file__))
		self.image_directory = os.path.join(self.image_directory, "images")

		self.face_cascade = cv2.CascadeClassifier(c_path)
		self.recognizer = cv2.face.LBPHFaceRecognizer_create()
		self.current_id = 0
		self.label_ids = {}
		self.y_labels = []
		self.x_train = []

Gerekli değişkenlerimizi tanımladık, zamanı geldikçe tek tek ne işe yaradığından bahsedeceğim. Öncelikle dosya adlarını isim olarak kullanacağımızdan bahsetmiştik, bir nevi bu klasör adları bizim "label" ımız olacak. current_id isimli değişkenimiz ise onun kaçıncı label olduğunu söyleyecek.

Kod:
if not self.label in label_ids:
                		self.label_ids[self.label] = self.current_id
                		self.current_id += 1
            		self.id_ = self.label_ids[self.label]
Bu kod işimize yarayacaktır. Label'ları belirlediysek elimizdeki yüzleri birer array'e dönüştürüp bunu uygun bir dataset olarak kaydetmeliyiz. array işlemlerini "numpy" adlı kütüphane ile yapacağımızı zaten söylemiştim. Basitçe elimizdeki resmi "L" yada "RGB" moda çevirip diğer resimlerle olan benzerliğini kıyaslayacağım. Bunu da yüzdeye vuracağım, eğer beni ikna edecekte bir yüzdeye sahipse bunu label olarak yazdıracağım. Hemen ardından bunu kaydedeceğim ki ilk scriptim'de bu dataseti kullanabileyim.
Kod:
self.pimage = Image.open(self.path).convert("L")
            		self.image_array = np.array(self.pimage, "uint8")
            		
            		self.faces= self.face_cascade.detectMultiScale(self.image_array, scaleFactor=1.5, minNeighbors=5)
            		for (x, y, w, h) in self.faces:
                		self.roi = image_array[y:y+h, x:x+w]
                		self.x_train.append(self.roi)
                		self.y_labels.append(self.id_)
    def pickle(self):
    	self.train_it()
    	with open("labels.pickle", "wb") as f:
    		pickle.dump(self.label_ids, f)
		self.recognizer.train(self.x_train, np.array(self.y_labels))
		self.recognizer.save("trainner.yml")


Gördüğünüz üzere resmi rgb olarak array'e dönüştürdüm. Pickle kütüphanesini kullanarak bu dataset'i kaydettim.Bu sınıfı bir defa çalıştırdıktan sonra ilk
Şimdi asıl kodumuza dönelim.
Kaydettiğim trainer'ı asıl scriptte okuyacağım. Ardından üstte bahsettiğim gibi beni ikna edecek bir yüzdeyse ise bu label'ı ekranda yazdıracağım. Daha teknik olmayan bir dille anlatırsam, kameranın gördüğü kişiyi tanıyorsanız yanında ismi yazacak. İlk script'teki init fonksiyonumu tekrar editlemem gerekiyor.
Kod:
class faceID(object):
	def __init__(self):
		self.cap = cv2.VideoCapture(0)
		self.face_cascade = cv2.CascadeClassifier('cascades\\data\\haarcascade_frontalface_alt2.xml')
		self.recognizer = cv2.face.LBPHFaceRecognizer_create()
		self.recognizer.read("trainner.yml")
	def get_label_names(self):
		self.labels = {"person_name": 1}
		with open("labels.pickle", "rb") as f:
			self.labels = pickle.load(f)
			self.labels = {v: k for k,v in self.labels.items()}

Gördüğünüz gibi hem datasetimi hem de label'ları çektim diğer scriptten. Elimde zaten yüzü işaretleyen kod vardı, geldik sonuna...

Kod:
for (x,y,w,h) in self.faces:
				
				self.roi_gray = self.gray[y:y+h, x:w+w]#siyah beyaz versiyon
				roi_color = frame[y:y+h, x:x+w]#renkli versiyon
				id_, conf = self.recognizer.predict(self.roi_gray)#yüzdeye vuracak
				if conf >= 4 and  conf <= 85:#yüzde 4 ten büyük 85 ten küçük ise
			
					font = cv2.FONT_HERSHEY_COMPLEX#yazının fontunu seçtim
					name = self.labels[id_]#id_ = isim
					color = ()
					stroke = 2
					cv2.putText(frame, name, (x,y), font, 1, color, stroke, cv2.LINE_AA)#Yüzün yanına ismi yazıyorum
				else:
					pass
Bu kod parçacığını ana fonksiyonuma yazıyorum, ve işlem tamam. Tüm kod şu şekilde oldu
Kod:
face_identifier.py:
import numpy as np
import cv2
import pickle
class faceID(object):
	def __init__(self):
		self.cap = cv2.VideoCapture(0)
		self.face_cascade = cv2.CascadeClassifier('cascades\\data\\haarcascade_frontalface_alt2.xml')
		self.recognizer = cv2.face.LBPHFaceRecognizer_create()
		self.recognizer.read("trainner.yml")
	def get_label_names(self):
		self.labels = {"person_name": 1}
		with open("labels.pickle", "rb") as f:
			self.labels = pickle.load(f)
			self.labels = {v: k for k,v in self.labels.items()}
	def video_capture(self):
		self.get_label_names()
		while 1:
			ret, frame = self.cap.read()
			self.gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
			self.faces= self.face_cascade.detectMultiScale(self.gray, scaleFactor=1.5, minNeighbors=5)
			for (x,y,w,h) in self.faces:
				
				self.roi_gray = self.gray[y:y+h, x:w+w]
				roi_color = frame[y:y+h, x:x+w]
				id_, conf = self.recognizer.predict(self.roi_gray)
				if conf >= 4 and  conf <= 85:
			
					font = cv2.FONT_HERSHEY_COMPLEX
					name = self.labels[id_]
					color = ()
					stroke = 2
					cv2.putText(frame, name, (x,y), font, 1, color, stroke, cv2.LINE_AA)
				else:
					pass
				self.img_item = 'my-image.png'
				cv2.imwrite(self.img_item, self.roi_gray)
				color=(95,234,249)
				stroke=2
				end_cord_x = x + w
				end_cord_y = y + h
				cv2.rectangle(frame, (x, y), (end_cord_x, end_cord_y), color, stroke)
			cv2.imshow('video_rec', frame)

			if cv2.waitKey(20) & 0xFF == ord('q'):
				break
		cap.release()
		cv2.destroyAllWindows()
ID = faceID()
ID.video_capture()

face_trainer.py:

Kod:
import cv2
import os
import numpy as np
from PIL import Image
import pickle
import sys
class trainer(object):
	def __init__(self, c_path): #c_path = classifier path 
		self.BASE_DIR = os.path.dirname(os.path.abspath(__file__))
		self.image_dir = os.path.join(self.BASE_DIR, "images")

		self.face_cascade = cv2.CascadeClassifier(c_path)
		self.recognizer = cv2.face.LBPHFaceRecognizer_create()
		self.current_id = 0
		self.label_ids = {}
		self.y_labels = []
		self.x_train = []
	def train_it(self):
		for root, dirs, files in os.walk(self.image_dir, "images"):
    
    		for self.file in files:
        		if self.file.endswith("png") or file.endswith("jpg"):
            		self.path = os.path.join(root, file)
            		self.label = os.path.basename(os.path.dirname(self.path)).replace(" ", "-").lower()
            		
            		if not self.label in label_ids:
                		self.label_ids[self.label] = self.current_id
                		self.current_id += 1
            		self.id_ = self.label_ids[self.label]
            
            		self.pimage = Image.open(self.path).convert("L")
            		self.image_array = np.array(self.pimage, "uint8")
            		
            		self.faces= self.face_cascade.detectMultiScale(self.image_array, scaleFactor=1.5, minNeighbors=5)
            		for (x, y, w, h) in self.faces:
                		self.roi = image_array[y:y+h, x:x+w]
                		self.x_train.append(self.roi)
                		self.y_labels.append(self.id_)
    def pickle(self):
    	self.train_it()
    	with open("labels.pickle", "wb") as f:
    		pickle.dump(self.label_ids, f)
		self.recognizer.train(self.x_train, np.array(self.y_labels))
		self.recognizer.save("trainner.yml")

Bugünkü yazımın sonuna geldim, umarım projelerinizde işinize yarar. Sağlıcakla kalın
 
Son düzenleme:

siberdrone15

Kıdemli Üye
20 Ağu 2016
4,446
3
Eline sağlık harika
Bir sorum olacak cv2 yüklerken sadece import yazıp çağırmamız yeterli mi yoksa pip olarak bir kurulum vs var mı
 

Hacknology

Kıdemli Üye
25 Eki 2015
2,712
11
rm -rf /
Ellerine sağlık teşekkür ederim.

Buram buram emek kokuyor :)
Eline sağlık hocam

Eline sağlık harika
Bir sorum olacak cv2 yüklerken sadece import yazıp çağırmamız yeterli mi yoksa pip olarak bir kurulum vs var mı
Öncelikle size ve üstte tüm yorum atanlara teşekkürlerimi sunarım. Önce kurmanız gerekiyor, 3rd lib'dir kendileri.
 
Üst

Turkhackteam.org internet sitesi 5651 sayılı kanun’un 2. maddesinin 1. fıkrasının m) bendi ile aynı kanunun 5. maddesi kapsamında "Yer Sağlayıcı" konumundadır. İçerikler ön onay olmaksızın tamamen kullanıcılar tarafından oluşturulmaktadır. Turkhackteam.org; Yer sağlayıcı olarak, kullanıcılar tarafından oluşturulan içeriği ya da hukuka aykırı paylaşımı kontrol etmekle ya da araştırmakla yükümlü değildir. Türkhackteam saldırı timleri Türk sitelerine hiçbir zararlı faaliyette bulunmaz. Türkhackteam üyelerinin yaptığı bireysel hack faaliyetlerinden Türkhackteam sorumlu değildir. Sitelerinize Türkhackteam ismi kullanılarak hack faaliyetinde bulunulursa, site-sunucu erişim loglarından bu faaliyeti gerçekleştiren ip adresini tespit edip diğer kanıtlarla birlikte savcılığa suç duyurusunda bulununuz.