首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用CIDetector和CIFaceFeature的脸切割圆形图像

用CIDetector和CIFaceFeature的脸切割圆形图像
EN

Stack Overflow用户
提问于 2017-04-20 12:37:01
回答 2查看 2.6K关注 0票数 14

如何剪下作为faceViewBounds的框架,使我的脸围成一个大圆圈?就像一个人的脸的徽章。

也许我应该得到faceViewBounds的中心,然后我必须在theImageView.image中找到这个中心,画一个大直径的圆圈,然后用逻辑将其余的部分切出这个圆圈,但是用代码我不知道怎么做。有什么建议吗?

代码语言:javascript
复制
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上看到一个广告,上面写着我想要完成的同样的事情:

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-05-26 12:34:23

问题是您应该使用image.size而不是theImageView.bounds.size。您还应该处理特性选项CIDetectorImageOrientation。

代码语言:javascript
复制
extension UIImage{
    var faces: [UIImage] {
        guard let ciimage = CIImage(image: self) else { return [] }
        var orientation: NSNumber {
            switch 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])
            .compactMap {
                let rect = $0.bounds.insetBy(dx: -10, dy: -10)
                UIGraphicsBeginImageContextWithOptions(rect.size, false, scale)
                defer { UIGraphicsEndImageContext() }
                UIImage(ciImage: ciimage.cropped(to: rect)).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, scale)
                defer { UIGraphicsEndImageContext() }
                guard let cgImage = face.cgImage?.cropping(to: CGRect(origin: CGPoint(x: size.width > size.height ? (size.width-size.height).rounded(.down)/2 : 0, y: size.height > size.width ? (size.height-size.width).rounded(.down)/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()
            } ?? []
    }
}
代码语言:javascript
复制
let profilePicture = UIImage(data: try! Data(contentsOf: URL(string:"http://i.stack.imgur.com/Xs4RX.jpg")!))!
if let face =  profilePicture.faces.first {
    print(face.size)
}
票数 11
EN

Stack Overflow用户

发布于 2017-04-20 13:29:32

如果你只想把注意力集中在图像里面的脸上。您应该首先设置一个图像视图,并将其隐藏为一个圆圈:

代码语言:javascript
复制
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

代码语言:javascript
复制
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's 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

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/43519752

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档