Last active
May 14, 2022 19:02
-
-
Save eilonkr/c26f5c1a6f37e49b912a3c3f0fd6561f to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
func blurFaces(in image: UIImage) -> UIImage? { | |
guard let ciImage = CIImage(image: image)? | |
.oriented(.init(image.imageOrientation)) else { | |
return nil | |
} | |
// this image will use as the "mask map" | |
var maskCanvasImage = CIImage.empty() | |
.cropped(to: ciImage.extent) | |
// request the features from `CIDetector` | |
for faceFeature in ciDetector.features(in: ciImage) { | |
let faceRect = faceFeature.bounds | |
// position the mask in the center of the face rect, relative to the image extent. | |
let maskCenter = CIVector(x: faceRect.maxX - (faceRect.width/2), | |
y: faceRect.maxY - (faceRect.height/2)) | |
let radialGradientFilter = CIFilter(name: "CIRadialGradient", parameters: [ | |
"inputCenter": maskCenter, | |
"inputRadius0": faceRect.height/2, | |
"inputRadius1": faceRect.height, | |
"inputColor0": CIColor.white, | |
"inputColor1": CIColor(red: 1.0, green: 1.0, blue: 1.0, alpha: 0.0) | |
]) | |
if let gradientOutput = radialGradientFilter?.outputImage? | |
.cropped(to: faceRect.insetBy(dx: -faceRect.width/2, dy: -faceRect.height/2)) { | |
// "append" the new mask to our mask map | |
maskCanvasImage = gradientOutput.composited(over: maskCanvasImage) | |
} | |
} | |
// create the blurred copy of the image | |
let blurRadius: Double = 30.0 | |
let blurredImage = ciImage | |
.clampedToExtent() | |
.applyingGaussianBlur(sigma: blurRadius) | |
.cropped(to: ciImage.extent) | |
// this is where the magic happens - | |
// mask the blurred image with our mask map, over the original image | |
let resultImage = blurredImage.applyingFilter("CIBlendWithMask", parameters: [ | |
kCIInputBackgroundImageKey: ciImage, | |
kCIInputMaskImageKey: maskCanvasImage | |
]) | |
// create the final image and return it. | |
if let cgImage = ciContext.createCGImage(resultImage, from: resultImage.extent) { | |
return UIImage(cgImage: cgImage) | |
} | |
return nil | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment