Вырезать закругленное изображение с помощью лица из CIDetector и CIFaceFeature
Как отрезать рамку, которую я получаю как faceViewBounds, чтобы сделать большой круг вокруг лица? Это как значок с лицом человека.
Может быть, я должен получить центр faceViewBounds, тогда мне нужно найти этот центр в файлеImageView.image и нарисовать круг с большим диаметром, а затем вырезать остальные за пределами круга логикой, но с кодом я не знаю, как сделать это.. Любые предложения?
func detectFaceFrom(ImageView theImageView: UIImageView) {
guard let personImage = CIImage(image: theImageView.image!) else {
return
}
let accuracy = [CIDetectorAccuracy: CIDetectorAccuracyLow]
let faceDetector = CIDetector(ofType: CIDetectorTypeFace, context: nil, options: accuracy)
let faces = faceDetector?.features(in: personImage)
let ciImageSize = personImage.extent.size
var transform = CGAffineTransform(scaleX: 1, y: -1)
transform = transform.translatedBy(x: 0, y: -ciImageSize.height)
if(faces?.count==1){
for face in faces as! [CIFaceFeature] {
var faceViewBounds = face.bounds.applying(transform)
let viewSize = theImageView.bounds.size
let scale = min(viewSize.width / ciImageSize.width,
viewSize.height / ciImageSize.height)
let offsetX = (viewSize.width - ciImageSize.width * scale) / 2
let offsetY = (viewSize.height - ciImageSize.height * scale) / 2
faceViewBounds = faceViewBounds.applying(CGAffineTransform(scaleX: scale, y: scale))
faceViewBounds.origin.x += offsetX
faceViewBounds.origin.y += offsetY
let faceBox = UIView(frame: faceViewBounds)
faceBox.layer.borderWidth = 3
faceBox.layer.borderColor = UIColor.green.cgColor
faceBox.backgroundColor = UIColor.clear
drawCircleFromCenter(faceViewBounds.center ???
}
return cuttedCircleWithFace
}else{
return theImageView.image
}
}
Я только что увидел рекламу в Facebook с той же самой вещью, которую хочу выполнить:
![значки]()
Ответы
Ответ 1
Проблема заключается в том, что вы должны использовать image.size
вместо использования theImageView.bounds.size
. Вы также должны обращаться к функциям функций CIDetectorImageOrientation.
func detectFaces(from image: UIImage) -> [UIImage] {
guard let ciimage = CIImage(image: image) else { return [] }
var orientation: NSNumber {
switch image.imageOrientation {
case .up: return 1
case .upMirrored: return 2
case .down: return 3
case .downMirrored: return 4
case .leftMirrored: return 5
case .right: return 6
case .rightMirrored: return 7
case .left: return 8
}
}
return CIDetector(ofType: CIDetectorTypeFace, context: nil, options: [CIDetectorAccuracy: CIDetectorAccuracyLow])?
.features(in: ciimage, options: [CIDetectorImageOrientation: orientation])
.flatMap {
let rect = $0.bounds.insetBy(dx: -10, dy: -10)
let ciimage = ciimage.cropping(to: rect)
UIGraphicsBeginImageContextWithOptions(rect.size, false, image.scale)
defer { UIGraphicsEndImageContext() }
UIImage(ciImage: ciimage).draw(in: CGRect(origin: .zero, size: rect.size))
guard let face = UIGraphicsGetImageFromCurrentImageContext() else { return nil }
// now that you have your face image you need to properly apply a circle mask to it
let size = face.size
let breadth = min(size.width, size.height)
let breadthSize = CGSize(width: breadth, height: breadth)
UIGraphicsBeginImageContextWithOptions(breadthSize, false, image.scale)
defer { UIGraphicsEndImageContext() }
guard let cgImage = face.cgImage?.cropping(to: CGRect(origin:
CGPoint(x: size.width > size.height ? (size.width-size.height).rounded(.down).divided(by: 2) : 0,
y: size.height > size.width ? (size.height-size.width).rounded(.down).divided(by: 2) : 0),
size: breadthSize)) else { return nil }
let faceRect = CGRect(origin: .zero, size: CGSize(width: min(size.width, size.height), height: min(size.width, size.height)))
UIBezierPath(ovalIn: faceRect).addClip()
UIImage(cgImage: cgImage).draw(in: faceRect)
return UIGraphicsGetImageFromCurrentImageContext()
} ?? []
}
let profilePicture = UIImage(data: try! Data(contentsOf: URL(string:"http://i.stack.imgur.com/Xs4RX.jpg")!))!
let faces = detectFaces(from: profilePicture)
![введите описание изображения здесь]()
Ответ 2
Если вы просто хотите сосредоточиться на лице внутри изображения. Сначала вы должны создать представление изображения и замаскировать его в круг:
let image = UIImage(named: "face.jpg")
let imageView = UIImageView(frame: CGRect(x: 0, y: 0, width: 50.0, height: 50.0))
imageView.image = image
imageView.contentMode = .scaleAspectFill
imageView.layer.cornerRadius = imageView.bounds.height * 0.5
imageView.layer.masksToBounds = true
Затем вы запустите CIDetector
func focusOnFace(in imageView: UIImageView)
{
guard let image = imageView.image,
var personImage = CIImage(image: image) else { return }
let accuracy = [CIDetectorAccuracy: CIDetectorAccuracyLow]
let faceDetector = CIDetector(ofType: CIDetectorTypeFace, context: nil, options: accuracy)
// This will just take the first detected face but you can do something more sophisticated
guard let face = faceDetector?.features(in: personImage).first as? CIFaceFeature else { return }
// Make the facial rect a square so it will mask nicely to a circle (may not be strictly necessary as `CIFaceFeature` bounds is typically a square)
var rect = face.bounds
rect.size.height = max(face.bounds.height, face.bounds.width)
rect.size.width = max(face.bounds.height, face.bounds.width)
rect = rect.insetBy(dx: -30, dy: -30) // Adds padding around the face so it not so tightly cropped
// Crop to the face detected
personImage = personImage.cropping(to: rect)
// Set the new cropped image as the image view image
imageView.image = UIImage(ciImage: personImage)
}
Пример
Перед запуском focusOnFace
:
![введите описание изображения здесь]()
После запуска focusOnFace
:
![введите описание изображения здесь]()
Обновленный пример
Перед запуском focusOnFace
:
![введите описание изображения здесь]()
После запуска focusOnFace
:
![введите описание изображения здесь]()