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
UIKit
import
ImageIO
class
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