/** * Estimate the affine transform required to warp a set of facial keypoints * to their canonical coordinates. * <p> * Affine transform is from a flat, vertically oriented (canonical) face to * located face space. You'll need to invert this if you want to use it to * extract the face from the image. * * @param face * the face * @return the affine transform matrix */ public static Matrix estimateAffineTransform(KEDetectedFace face) { return estimateAffineTransform(face.getKeypoints()); }
protected void extractFeatures(KEDetectedFace face) { final Matrix T0 = AffineAligner.estimateAffineTransform(face); final Matrix T = T0.copy(); final FImage J = FKEFaceDetector.pyramidResize(face.getFacePatch(), T);
@Override public FImage align(KEDetectedFace descriptor) { final int facePatchSize = Math.max(facePatchWidth, facePatchHeight); final double size = facePatchSize + 2.0 * facePatchSize * facePatchBorderPercentage; final double sc = CANONICAL_SIZE / size; // do the scaling to everything but the translation!!! final Matrix T = estimateAffineTransform(descriptor); T.set(0, 0, T.get(0, 0) * sc); T.set(1, 1, T.get(1, 1) * sc); T.set(0, 1, T.get(0, 1) * sc); T.set(1, 0, T.get(1, 0) * sc); final FImage J = FKEFaceDetector.pyramidResize(descriptor.getFacePatch(), T); final FImage bigPatch = FKEFaceDetector.extractPatch(J, T, (int) size, (int) (facePatchSize * facePatchBorderPercentage)); return bigPatch.extractCenter(facePatchWidth, facePatchHeight).extractROI(0, 0, facePatchWidth, facePatchHeight) .multiplyInplace(mask); }
/** * Detect faces in the image and render mustaches. * * @param image * @return image with rendered mustaches */ public MBFImage addMustaches(MBFImage image) { MBFImage cimg; if (image.getWidth() > image.getHeight() && image.getWidth() > 640) { cimg = image.process(new ResizeProcessor(640, 480)); } else if (image.getHeight() > image.getWidth() && image.getHeight() > 640) { cimg = image.process(new ResizeProcessor(480, 640)); } else { cimg = image.clone(); } final FImage img = Transforms.calculateIntensityNTSC(cimg); final List<KEDetectedFace> faces = detector.detectFaces(img); final MBFImageRenderer renderer = cimg.createRenderer(); for (final KEDetectedFace face : faces) { final Matrix tf = AffineAligner.estimateAffineTransform(face); final Shape bounds = face.getBounds(); final MBFImage m = mustache.transform(tf.times(TransformUtilities.scaleMatrix(1f / 4f, 1f / 4f))); renderer.drawImage(m, (int) bounds.minX(), (int) bounds.minY()); } return cimg; }
/** * Detect faces in the image and render mustaches. * * @param image * @return image with rendered mustaches */ public MBFImage addMustaches(MBFImage image) { MBFImage cimg; if (image.getWidth() > image.getHeight() && image.getWidth() > 640) { cimg = image.process(new ResizeProcessor(640, 480)); } else if (image.getHeight() > image.getWidth() && image.getHeight() > 640) { cimg = image.process(new ResizeProcessor(480, 640)); } else { cimg = image.clone(); } final FImage img = Transforms.calculateIntensityNTSC(cimg); final List<KEDetectedFace> faces = detector.detectFaces(img); final MBFImageRenderer renderer = cimg.createRenderer(); for (final KEDetectedFace face : faces) { final Matrix tf = AffineAligner.estimateAffineTransform(face); final Shape bounds = face.getBounds(); final MBFImage m = mustache.transform(tf.times(TransformUtilities.scaleMatrix(1f / 4f, 1f / 4f))); renderer.drawImage(m, (int) bounds.minX(), (int) bounds.minY()); } return cimg; }