Обнаружение лица и нанесение на него маски с помощью openCV

ОБНОВЛЕНИЕ: здесь opencv c ++ образец и показывает, что именно я хочу делать. Единственное, что мне нужно с java.

Я работал над приложением для Android в реальном времени, которое обнаруживает лицо с помощью передней камеры и добавляет маску на обнаруженное лицо. Пока что обнаружение лиц хорошо работает с каскадным классификатором.

Рисую прямоугольники вокруг лица и круги вместо глаз:

 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);

    }

У меня вопрос, как применить изображение к обнаруженному лицу и показать его в реальном времени. (например, солнцезащитные очки, шляпа, усы и забавная мордашка животного)

Я был бы очень признателен, если бы кто-нибудь мог дать мне совет или подсказать некоторые ключевые моменты.

Это хороший пример того, чего я ожидаю от своего приложения. Я изучил код, но не понял.

Спасибо!


person wlrs    schedule 09.06.2017    source источник
comment
Вы хотите в реальном времени нанести изображение на захваченное изображение или на лицо?   -  person Rick M.    schedule 09.06.2017
comment
Этот ответ может помочь вам начать работу (код C ++).   -  person Elouarn Laine    schedule 09.06.2017
comment
Я хочу наложить изображение на лицо в режиме реального времени, как эффекты снэпчата. @RickM.   -  person wlrs    schedule 09.06.2017


Ответы (2)


Вам нужно извлечь ориентиры лица (хорошая библиотека - http://dlib.net/).

введите здесь описание изображения

Для этой задачи нет необходимости использовать каскадный классификатор Хаара для обнаружения лица.

Но это может помочь, если вы передадите только часть изображения (часть только с лицом) алгоритму, который вычисляет ориентиры. В этом случае с меньшим объемом данных для вычисления алгоритм должен быть быстрее. Но не забудьте заново сопоставить точки с исходной системой координат полного изображения.

После того, как вы получили эти точки, вы можете легко перекрыть нужное изображение на различных кадрах, снятых вашей камерой.

person luke88    schedule 09.06.2017
comment
Я просто хочу прикрепить простую маску (не нужно закрывать всю область лица). Например, прикрепить солнцезащитные очки в том же месте, что и точки зрения, которые у меня уже есть. Можно ли это сделать, не находя ориентиров? - person wlrs; 09.06.2017
comment
да. Например, каскадный классификатор Хаара openCV возвращает Rect. Вы можете использовать координаты Rect, чтобы нарисовать то, что вы хотите, на исходном изображении. Он менее точен (например, для глаз вы просто знаете область, которая их содержит, а затем вычисляете более или менее центр), чем ориентиры лица. Для вас может хватить цели. - person luke88; 12.06.2017
comment
@wlrs, если вы реализовали этот код, дайте мне ссылку. Потому что у меня такие же требования, как у вас. - person Puja Singh; 26.08.2017
comment
@PujaSingh, посмотри мой ответ. Если есть вопросы, я могу объяснить детали. - person wlrs; 15.11.2017

[Решено]

Вот для меня рабочий код для установки маски.

Спасибо @paul_poveda и @hariprasad

это метод:

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;}
person wlrs    schedule 15.11.2017