0

MISE À JOUR: here est un exemple opencv C++ et montre exactement ce que je veux faire. La seule chose est que j'en ai besoin avec Java.Détecter le visage et appliquer un masque dessus avec openCV

Je travaille sur une application Android en temps réel qui détecte le visage avec la caméra frontale et ajoute un masque sur un visage détecté. Jusqu'à présent, la détection des visages fonctionne bien avec le classificateur en cascade.

Je dessine des rectangles autour du visage et des cercles pour les yeux:

Rect[] facesArray = faces.toArray(); 
    for (int i = 0; i < facesArray.length; i++) 
    { 
     Imgproc.rectangle(mRgba, facesArray[i].tl(), facesArray[i].br(), FACE_RECT_COLOR, 3); 

     xCenter = (facesArray[i].x + facesArray[i].width + facesArray[i].x)/2; 
     yCenter = (facesArray[i].y + facesArray[i].y + facesArray[i].height)/2; 
     Point center = new Point(xCenter, yCenter); 
     Imgproc.circle(mRgba, center, 10, new Scalar(255, 0, 0, 255), 3); 

    } 

Ma question est, comment appliquer une image sur le visage détecté et montrer en temps réel. (par exemple lunettes de soleil, chapeau, moustache, et une drôle de tête d'animal)

Si quelqu'un pourrait donner un pourboire ou me dire quelques points clés, je serais tellement reconnaissant.

This est un bon exemple de ce que j'attend de mon application. J'ai examiné le code mais je ne pouvais pas comprendre.

Merci!

+0

Voulez-vous « appliquer » une image sur l'image capturée ou sur la face en temps réel? –

+1

Cette [réponse] (https://stackoverflow.com/a/43964740/5799975) peut vous aider à démarrer (code C++). –

+0

Je veux appliquer une image sur le visage en temps réel comme les effets snapchat. @RickM. – wlrs

Répondre

1

Vous devez extraire les points de repère du visage (une bonne bibliothèque est http://dlib.net/).

enter image description here

Pour cette tâche, il est pas vraiment nécessaire d'utiliser la Haar Cascade Classifier pour détecter le visage.

Mais cela peut être utile si vous passez juste une partie de votre image (la section avec seulement le visage) à l'algorithme qui calcule les points de repère. Dans ce cas, avec moins de données à calculer, l'algorithme devrait être plus rapide. Mais n'oubliez pas de recadrer les points dans le système de référence de coordonnées original de l'image complète.

Une fois que vous avez obtenu ces points, vous pouvez facilement superposer l'image dont vous avez besoin sur les différentes images capturées à partir de votre appareil photo.

+0

Je veux juste attacher un masque simple (pas besoin de couvrir toute la région du visage). Par exemple, attacher un lunettes de soleil à la même position avec les points de vue que j'ai déjà. Est-il possible de le faire sans trouver de repères? – wlrs

+0

Oui. Par exemple, le Haar Cascade Classifier d'openCV renvoie un Rect. Vous pouvez utiliser les coordonnées Rect pour dessiner ce que vous voulez sur l'image originale. C'est moins précis (par exemple, pour les yeux, vous connaissez simplement une région qui les contient, puis calculez plus ou moins le centre) que les repères de visage. Pour vous, l'objectif peut être suffisant. – luke88

+0

@wlrs si vous avez implémenté ce code, merci de me guider. Coz j'ai la même exigence que la vôtre. –

0

[RESOLU]

Here est un code de travail pour moi de mettre un masque.

Merci à @paul_poveda et @hariprasad

c'est la méthode:

Mat putMask(Mat src, Point center, Size face_size){ 

//mask : masque chargé depuis l'image 
Mat mask_resized = new Mat(); //masque resizé 
src_roi = new Mat(); //ROI du visage croppé depuis la preview 
roi_gray = new Mat(); 


Imgproc.resize(mask ,mask_resized,face_size); 

// ROI selection 
roi = new Rect((int) (center.x - face_size.width/2), (int) (center.y - face_size.height/2),(int) face_size.width, (int) face_size.height); 
//Rect roi = new Rect(10, 10, (int) face_size.width, (int) face_size.height); 

src.submat(roi).copyTo(src_roi); 

Log.e(TAG, "MASK SRC1 :"+ src_roi.size()); 

// to make the white region transparent 
Mat mask_grey = new Mat(); //greymask 
roi_rgb = new Mat(); 
Imgproc.cvtColor(mask_resized,mask_grey, Imgproc.COLOR_BGRA2GRAY); 
Imgproc.threshold(mask_grey,mask_grey,230,255, Imgproc.THRESH_BINARY_INV); 

ArrayList<Mat> maskChannels = new ArrayList<>(4); 
ArrayList<Mat> result_mask = new ArrayList<>(4); 
result_mask.add(new Mat()); 
result_mask.add(new Mat()); 
result_mask.add(new Mat()); 
result_mask.add(new Mat()); 

Core.split(mask_resized, maskChannels); 

Core.bitwise_and(maskChannels.get(0),mask_grey, result_mask.get(0)); 
Core.bitwise_and(maskChannels.get(1),mask_grey, result_mask.get(1)); 
Core.bitwise_and(maskChannels.get(2),mask_grey, result_mask.get(2)); 
Core.bitwise_and(maskChannels.get(3),mask_grey, result_mask.get(3)); 

Core.merge(result_mask, roi_gray);   

Core.bitwise_not(mask_grey,mask_grey); 

ArrayList<Mat> srcChannels = new ArrayList<>(4); 
Core.split(src_roi, srcChannels); 
Core.bitwise_and(srcChannels.get(0),mask_grey, result_mask.get(0)); 
Core.bitwise_and(srcChannels.get(1),mask_grey, result_mask.get(1)); 
Core.bitwise_and(srcChannels.get(2),mask_grey, result_mask.get(2)); 
Core.bitwise_and(srcChannels.get(3),mask_grey, result_mask.get(3)); 

Core.merge(result_mask, roi_rgb);   

Core.addWeighted(roi_gray,1, roi_rgb,1,0, roi_rgb); 

roi_rgb.copyTo(new Mat(src,roi)); 

return src;}