Swift - 人臉檢測,以及人臉打碼

1,人臉檢測的實現
(1)人臉檢測是指在圖像中尋找符合人臉特徵的區域,找到後會返回該特徵的信息(比如人臉的範圍、眼睛和嘴巴的位置等)。不是指人臉識別,識別出是誰的臉。
(2)Core Image框架中的的CIDetector對象提供了對圖像檢測的功能。創建CIDetector對象時使用CIDetectorTypeFace表示檢測人臉。
(3)下面通過樣例演示如何進行人臉檢測,同時檢測完成後會用方框把人臉給標註出來。
(注意:由於方框是一個個UIView添加到imageView中,而人臉檢測出來的位置是相對於原圖的。所以方框放置的位置要考慮圖片在imageView裏的縮放大小,x軸,y軸的偏移量)

2,給人臉打上馬賽克的功能實現
(1)使用用CIPixellate濾鏡對原圖先做個完全馬賽克
(2)檢測人臉,以人臉爲中心,臉的寬度或高度爲半徑。做一個包含一個一個圓形區域的蒙板。
(3)CIBlendWithMask濾鏡把馬賽克圖、原圖、蒙版圖混合起來,輸出即可。

3,效果圖如下
原文:Swift - 人臉檢測,以及人臉打碼的功能實現(附樣例)


4,代碼如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
import UIKit
import ImageIO
 
class ViewControllerUIViewController {
     
    @IBOutlet weak var imageView: UIImageView!
     
    //原圖
    lazy var originalImage: UIImage = {
        return UIImage(named: "d1.jpg")
        }()!
     
    lazy var context: CIContext = {
        return CIContext(options: nil)
        }()
 
    override func viewDidLoad() {
        super.viewDidLoad()
    }
     
    //恢復原圖
    @IBAction func resetImg(sender: AnyObject) {
        imageView.image = originalImage
    }
     
    //檢測人臉並框出
    @IBAction func detectFace(sender: AnyObject) {
        imageView.image = originalImage
        let inputImage = CIImage(image: originalImage)!
        //人臉檢測器
        //CIDetectorAccuracyHigh:檢測的精度高,但速度更慢些
        let detector = CIDetector(ofType: CIDetectorTypeFace,
            context: context,
            options: [CIDetectorAccuracyCIDetectorAccuracyHigh])
        var faceFeatures: [CIFaceFeature]!
        //人臉檢測需要圖片方向(有元數據的話使用元數據,沒有就調用featuresInImage)
        if let orientation: AnyObject = inputImage
            .properties[kCGImagePropertyOrientation as String] {
            faceFeatures = detector.featuresInImage(inputImage,
                options: [CIDetectorImageOrientation: orientation]) as! [CIFaceFeature]
        else {
            faceFeatures = detector.featuresInImage(inputImage) as! [CIFaceFeature]
        }
         
        //打印所有的面部特徵
        print(faceFeatures)
         
        let inputImageSize = inputImage.extent.size
        var transform = CGAffineTransformIdentity
        transform = CGAffineTransformScale(transform, 1, -1)
        transform = CGAffineTransformTranslate(transform, 0, -inputImageSize.height)
         
        //遍歷所有的面部,並框出
        for faceFeature in faceFeatures {
            var faceViewBounds = CGRectApplyAffineTransform(faceFeature.bounds, transform)
             
            // 由於檢測的原圖放在imageView中縮放的原因,我們還要考慮縮放比例和x,y軸偏移
            let scale = min(imageView.bounds.size.width / inputImageSize.width,
                imageView.bounds.size.height / inputImageSize.height)
            let offsetX = (imageView.bounds.size.width - inputImageSize.width * scale) / 2
            let offsetY = (imageView.bounds.size.height - inputImageSize.height * scale) / 2
             
            faceViewBounds = CGRectApplyAffineTransform(faceViewBounds,
                CGAffineTransformMakeScale(scale, scale))
            faceViewBounds.origin.x += offsetX
            faceViewBounds.origin.y += offsetY
             
            //每個人臉對應一個UIView方框
            let faceView = UIView(frame: faceViewBounds)
            faceView.layer.borderColor = UIColor.orangeColor().CGColor
            faceView.layer.borderWidth = 2
             
            imageView.addSubview(faceView)
        }
    }
     
    //檢測人臉並打馬賽克
    @IBAction func detectAndPixFace(sender: AnyObject) {
        // 用CIPixellate濾鏡對原圖先做個完全馬賽克
        let filter CIFilter(name: "CIPixellate")!
        print(filter.attributes)
        let inputImage = CIImage(image: originalImage)!
        filter.setValue(inputImage, forKey: kCIInputImageKey)
        let inputScale = max(inputImage.extent.size.width, inputImage.extent.size.height) / 80
        filter.setValue(inputScale, forKey: kCIInputScaleKey)
        let fullPixellatedImage = filter.outputImage
 
        // 檢測人臉,並保存在faceFeatures中
        let detector = CIDetector(ofType: CIDetectorTypeFace,
            context: context,
            options: nil)
        let faceFeatures = detector.featuresInImage(inputImage)
        // 初始化蒙版圖,並開始遍歷檢測到的所有人臉
        var maskImage: CIImage!
        for faceFeature in faceFeatures {
            print(faceFeature.bounds)
            // 基於人臉的位置,爲每一張臉都單獨創建一個蒙版,所以要先計算出臉的中心點,對應爲x、y軸座標,
            // 再基於臉的寬度或高度給一個半徑,最後用這些計算結果初始化一個CIRadialGradient濾鏡
            let centerX = faceFeature.bounds.origin.x + faceFeature.bounds.size.width / 2
            let centerY = faceFeature.bounds.origin.y + faceFeature.bounds.size.height / 2
            let radius = min(faceFeature.bounds.size.width, faceFeature.bounds.size.height)
            let radialGradient = CIFilter(name: "CIRadialGradient",
                withInputParameters: [
                    "inputRadius0" : radius,
                    "inputRadius1" : radius + 1,
                    "inputColor0" CIColor(red: 0, green: 1, blue: 0, alpha: 1),
                    "inputColor1" CIColor(red: 0, green: 0, blue: 0, alpha: 0),
                    kCIInputCenterKey : CIVector(x: centerX, y: centerY)
                ])!
            print(radialGradient.attributes)
            // 由於CIRadialGradient濾鏡創建的是一張無限大小的圖,所以在使用之前先對它進行裁剪
            let radialGradientOutputImage = radialGradient.outputImage!
                .imageByCroppingToRect(inputImage.extent)
            if maskImage == nil {
                maskImage = radialGradientOutputImage
            else {
                print(radialGradientOutputImage)
                maskImage = CIFilter(name: "CISourceOverCompositing",
                    withInputParameters: [
                        kCIInputImageKey : radialGradientOutputImage,
                        kCIInputBackgroundImageKey : maskImage
                    ])!.outputImage
            }
        }
        // 用CIBlendWithMask濾鏡把馬賽克圖、原圖、蒙版圖混合起來
        let blendFilter = CIFilter(name: "CIBlendWithMask")!
        blendFilter.setValue(fullPixellatedImage, forKey: kCIInputImageKey)
        blendFilter.setValue(inputImage, forKey: kCIInputBackgroundImageKey)
        blendFilter.setValue(maskImage, forKey: kCIInputMaskImageKey)
        // 輸出,在界面上顯示
        let blendOutputImage = blendFilter.outputImage
        let blendCGImage = context.createCGImage(blendOutputImage!,
            fromRect: blendOutputImage!.extent)
        imageView.image = UIImage(CGImage: blendCGImage)
 
    }
     
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }
}

原文出自:www.hangge.com  轉載請保留原文鏈接:http://www.hangge.com/blog/cache/detail_907.html
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章