Cià, popoliamo un pò sto blog!
L’altro giorno “sfogliando” Hack A Day mi sono imbattuto in questo articolo. Quindi ho cominciato a documentarmi un pò sulla libreria OpenCV (che fortunatamente è disponibile anche per Python).
Girando di qua e di là e prendendo ispirazione soprattutto da questo post ho messo insieme (di fatto modificando un pò il codice del post linkato) uno scriptino in Python che acquisice l’immagine della webcam e rimpiazza la faccia (o le facce) con un’immagine che gli va passata come argomento. Questo è il risultato usando trollface.png:
Come vedete supporta anche più di una faccia alla volta. Un’altra cosa che si nota dal video è che purtroppo non sono ancora riuscito a capire come funziona la trasparenza, ci ho sbattuto la testa per tutta ieri notte e stanotte fino ad adesso ma niente; se passa qualche anima pia che ha idea di come fare lasci un commento, io ho provato maschere e mica maschere invano, se no se un giorno dovessi scoprirlo aggiornerò il post.
Quindi, appurato che per ora la trasparenza non va, è meglio usare immagini quadrate. Ergo, Creeper:
Lo script regge bene anche le mie agilissime finte e il face detection tiene anche il profilo a tre quarti, finchè non sparisce un occhio.
Ovviamente usandolo in real-time c’è un minimo di lag, direi intorno al mezzo secondo, ma io lo ritengo accettabile. Quando e se imparerò il C++ farò un confronto di prestazioni riscrivendolo in C++.
Veniamo al codice vero e proprio:
#!/usr/bin/python #---------------------------------------------------------------------------- # Face Replacement Test (OpenCV) # # Mainly inspired (and copypasted) by this post by Luca Amore # http://www.lucaamore.com/?p=638 # with some modifications to make it display an image # instead of drawing a rectangle around the face # # Modified by rbino # https://quelblogli.wordpress.com # # import cv import sys import time import Image def DetectFace(image, faceCascade): min_size = (20,20) image_scale = 2 haar_scale = 1.1 min_neighbors = 3 haar_flags = 0 # Allocate the temporary images grayscale = cv.CreateImage((image.width, image.height), 8, 1) smallImage = cv.CreateImage( ( cv.Round(image.width / image_scale), cv.Round(image.height / image_scale) ), 8 ,1) # Convert color input image to grayscale cv.CvtColor(image, grayscale, cv.CV_BGR2GRAY) # Scale input image for faster processing cv.Resize(grayscale, smallImage, cv.CV_INTER_LINEAR) # Equalize the histogram cv.EqualizeHist(smallImage, smallImage) # Detect the faces faces = cv.HaarDetectObjects( smallImage, faceCascade, cv.CreateMemStorage(0), haar_scale, min_neighbors, haar_flags, min_size ) # If faces are found if faces: for ((x, y, w, h), n) in faces: # the input to cv.HaarDetectObjects was resized, so scale the # bounding box of each face and convert it to two CvPoints pt1 = (int(x * image_scale), int(y * image_scale)) pt2 = (int((x + w) * image_scale), int((y + h) * image_scale)) largh = pt2[0]-pt1[0] lungh = pt2[1]-pt1[1] roi = (pt1[0], pt1[1], largh, lungh) cv.SetImageROI(image, roi) cv.Resize(overlay, image) cv.ResetImageROI(image) return image #---------- # M A I N #---------- if len(sys.argv) != 2: print "Argument: the image you want to swap your face with" sys.exit(-1) overlay = cv.LoadImage(sys.argv[1]) capture = cv.CaptureFromCAM(0) #capture = cv.CaptureFromFile("test.avi") # I adapted the path to the one I've found on Debian Wheezy # Uncomment the xml that you want to use #faceCascade = cv.Load("/usr/share/opencv/haarcascades/haarcascade_frontalface_default.xml") #faceCascade = cv.Load("/usr/share/opencv/haarcascades/haarcascade_frontalface_alt2.xml") faceCascade = cv.Load("/usr/share/opencv/haarcascades/haarcascade_frontalface_alt2.xml") #faceCascade = cv.Load("/usr/share/opencv/haarcascades/haarcascade_frontalface_alt_tree.xml") while (cv.WaitKey(15)==-1): img = cv.QueryFrame(capture) image = DetectFace(img, faceCascade) cv.ShowImage("Face replacement test", image) del(capture)(Dite che è il caso che il codice lo alleghi a parte? Boh per ora faccio così, poi vedo).
Leggendo il codice noterete che commentando la riga che cattura dalla webcam e decommentando quella sotto si può far funzionare lo script anche con un video. Ho provato ad usarlo ma è molto lento, quindi ho lasciato il nome del file hardcodato nello script, se volete fare delle prove modificatelo. Comunque, copiate tutto l’ambaradam sopra, salvatelo in un bel facereplace.py, dategli i diritti di esecuzione e avviate con
./facereplace.py nomeimmagine
Vi servirà ovviamente la libreria OpenCV per Python, che se siete su una distro Linux Debian based (Ubuntu compresa) installate con un bel
sudo apt-get install python-opencv
se no date un’occhiata qui. Controllate anche che gli XML delle Haarcascades siano nel percorso segnato dopo faceCascade, altrimenti modificate il percorso in base alle vostre esigenze.
Bon, credo che sia tutto per questo primo post, almeno ho rotto il ghiaccio e gli altri due non hanno più l’ansia da prestazione 😀
Alla prossima!
Bino