import
UIKit
ImageIO
class
ViewController
:
UIViewController
{
@IBOutlet
weak
var
imageView:
UIImageView
!
lazy
originalImage:
UIImage
= {
return
(named:
"d1.jpg"
)
}()!
context:
CIContext
= {
return
CIContext
(options:
nil
)
}()
override
func
viewDidLoad() {
super
.viewDidLoad()
}
//恢复原图
@IBAction
resetImg(sender:
AnyObject
) {
imageView.image = originalImage
}
//检测人脸并框出
detectFace(sender:
AnyObject
) {
imageView.image = originalImage
let
inputImage =
CIImage
(image: originalImage)!
//人脸检测器
//CIDetectorAccuracyHigh:检测的精度高,但速度更慢些
detector =
CIDetector
(ofType:
CIDetectorTypeFace
,
context: context,
options: [
CIDetectorAccuracy
:
CIDetectorAccuracyHigh
])
faceFeatures: [
CIFaceFeature
]!
//人脸检测需要图片方向(有元数据的话使用元数据,没有就调用featuresInImage)
if
orientation:
= inputImage
.properties[kCGImagePropertyOrientation
as
String
] {
faceFeatures = detector.featuresInImage(inputImage,
options: [
CIDetectorImageOrientation
: orientation])
as
! [
CIFaceFeature
]
}
else
{
faceFeatures = detector.featuresInImage(inputImage)
]
}
//打印所有的面部特征
print
(faceFeatures)
inputImageSize = inputImage.extent.size
transform =
CGAffineTransformIdentity
CGAffineTransformScale
(transform,1,-1)
transform =
CGAffineTransformTranslate
//遍历所有的面部,并框出
for
faceFeature
in
faceFeatures {
faceViewBounds =
CGRectApplyAffineTransform
(faceFeature.bounds,transform)
// 由于检测的原图放在imageView中缩放的原因,我们还要考虑缩放比例和x,y轴偏移
scale =
min
(imageView.bounds.size.width / inputImageSize.width,
imageView.bounds.size.height / inputImageSize.height)
offsetX = (imageView.bounds.size.width - inputImageSize.width * scale) / 2
offsetY = (imageView.bounds.size.height - inputImageSize.height * scale) / 2
faceViewBounds =
CGRectApplyAffineTransform
(faceViewBounds,
CGAffineTransformMakeScale
(scale,scale))
faceViewBounds.origin.x += offsetX
faceViewBounds.origin.y += offsetY
//每个人脸对应一个UIView方框
faceView =
UIView
(frame: faceViewBounds)
faceView.layer.borderColor =
UIColor
.orangeColor().
CGColor
faceView.layer.borderWidth = 2
imageView.addSubview(faceView)
}
}
//检测人脸并打马赛克
detectAndPixFace(sender:
) {
// 用CIPixellate滤镜对原图先做个完全马赛克
let
filter
=
CIFilter
(name:
"CIPixellate"
)!
(
.attributes)
(image: originalImage)!
.setValue(inputImage,forKey: kCIInputImageKey)
inputScale =
max
(inputImage.extent.size.width,inputImage.extent.size.height) / 80
.setValue(inputScale,forKey: kCIInputScaleKey)
fullPixellatedImage =
.outputImage
// 检测人脸,并保存在faceFeatures中
options:
)
faceFeatures = detector.featuresInImage(inputImage)
// 初始化蒙版图,并开始遍历检测到的所有人脸
maskImage:
!
faceFeatures {
(faceFeature.bounds)
// 基于人脸的位置,为每一张脸都单独创建一个蒙版,所以要先计算出脸的中心点,对应为x、y轴坐标,
// 再基于脸的宽度或高度给一个半径,最后用这些计算结果初始化一个CIRadialGradient滤镜
centerX = faceFeature.bounds.origin.x + faceFeature.bounds.size.width / 2
centerY = faceFeature.bounds.origin.y + faceFeature.bounds.size.height / 2
radius =
(faceFeature.bounds.size.width,faceFeature.bounds.size.height)
radialGradient =
CIFilter
"CIRadialGradient"
withInputParameters: [
"inputRadius0"
: radius,
"inputRadius1"
: radius + 1,
"inputColor0"
CIColor
(red: 0,green: 1,blue: 0,alpha: 1),
"inputColor1"
kCIInputCenterKey :
CIVector
(x: centerX,y: centerY)
])!
(radialGradient.attributes)
// 由于CIRadialGradient滤镜创建的是一张无限大小的图,所以在使用之前先对它进行裁剪
radialGradientOutputImage = radialGradient.outputImage!
.imageByCroppingToRect(inputImage.extent)
if
maskImage ==
{
maskImage = radialGradientOutputImage
{
(radialGradientOutputImage)
maskImage =
"CISourceOverCompositing"
withInputParameters: [
kCIInputImageKey : radialGradientOutputImage,
kCIInputBackgroundImageKey : maskImage
])!.outputImage
}
}
// 用CIBlendWithMask滤镜把马赛克图、原图、蒙版图混合起来
blendFilter =
"CIBlendWithMask"
)!
blendFilter.setValue(fullPixellatedImage,forKey: kCIInputImageKey)
blendFilter.setValue(inputImage,forKey: kCIInputBackgroundImageKey)
blendFilter.setValue(maskImage,forKey: kCIInputMaskImageKey)
// 输出,在界面上显示
blendOutputImage = blendFilter.outputImage
blendCGImage = context.createCGImage(blendOutputImage!,
fromRect: blendOutputImage!.extent)
imageView.image =
(
CGImage
: blendCGImage)
}
didReceiveMemoryWarning() {
.didReceiveMemoryWarning()
}
}