1,人脸检测的实现
(1)人脸检测是指在图像中寻找符合人脸特征的区域,找到后会返回该特征的信息(比如人脸的范围、眼睛和嘴巴的位置等)。不是指人脸识别,识别出是谁的脸。
(3) CIBlendWithMask滤镜把马赛克图、原图、蒙版图混合起来,输出即可。
3,效果图如下
4,代码如下
(1)人脸检测是指在图像中寻找符合人脸特征的区域,找到后会返回该特征的信息(比如人脸的范围、眼睛和嘴巴的位置等)。不是指人脸识别,识别出是谁的脸。
(2) Core Image框架中的的 CIDetector对象提供了对图像检测的功能。创建 CIDetector对象时使用 CIDetectorTypeFace表示检测人脸。
(3)下面通过样例演示如何进行人脸检测,同时检测完成后会用方框把人脸给标注出来。(注意:由于方框是一个个UIView添加到imageView中,而人脸检测出来的位置是相对于原图的。所以方框放置的位置要考虑图片在imageView里的缩放大小,x轴,y轴的偏移量)
2,给人脸打上马赛克的功能实现
(1)使用用 CIPixellate滤镜对原图先做个完全马赛克
(2)检测人脸,以人脸为中心,脸的宽度或高度为半径。做一个包含一个一个圆形区域的蒙板。 (3) CIBlendWithMask滤镜把马赛克图、原图、蒙版图混合起来,输出即可。
3,效果图如下
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 UIKitimport ImageIOclass ViewController : UIViewController { @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: [ CIDetectorAccuracy : CIDetectorAccuracyHigh ]) 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
