vision-camera-face-detection 2.2.0 → 2.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -16,243 +16,126 @@ let inputHeight = 112
16
16
  var interpreter: Interpreter? = nil
17
17
 
18
18
  class FaceHelper {
19
- // static func processContours(from face: Face) -> [String:[[String:CGFloat]]] {
20
- // let faceContoursTypes = [
21
- // FaceContourType.face,
22
- // FaceContourType.leftEyebrowTop,
23
- // FaceContourType.leftEyebrowBottom,
24
- // FaceContourType.rightEyebrowTop,
25
- // FaceContourType.rightEyebrowBottom,
26
- // FaceContourType.leftEye,
27
- // FaceContourType.rightEye,
28
- // FaceContourType.upperLipTop,
29
- // FaceContourType.upperLipBottom,
30
- // FaceContourType.lowerLipTop,
31
- // FaceContourType.lowerLipBottom,
32
- // FaceContourType.noseBridge,
33
- // FaceContourType.noseBottom,
34
- // FaceContourType.leftCheek,
35
- // FaceContourType.rightCheek,
36
- // ]
37
-
38
- // let faceContoursTypesStrings = [
39
- // "FACE",
40
- // "LEFT_EYEBROW_TOP",
41
- // "LEFT_EYEBROW_BOTTOM",
42
- // "RIGHT_EYEBROW_TOP",
43
- // "RIGHT_EYEBROW_BOTTOM",
44
- // "LEFT_EYE",
45
- // "RIGHT_EYE",
46
- // "UPPER_LIP_TOP",
47
- // "UPPER_LIP_BOTTOM",
48
- // "LOWER_LIP_TOP",
49
- // "LOWER_LIP_BOTTOM",
50
- // "NOSE_BRIDGE",
51
- // "NOSE_BOTTOM",
52
- // "LEFT_CHEEK",
53
- // "RIGHT_CHEEK",
54
- // ];
55
-
56
- // var faceContoursTypesMap: [String:[[String:CGFloat]]] = [:]
57
-
58
- // for i in 0..<faceContoursTypes.count {
59
- // let contour = face.contour(ofType: faceContoursTypes[i]);
60
-
61
- // var pointsArray: [[String:CGFloat]] = []
62
-
63
- // if let points = contour?.points {
64
- // for point in points {
65
- // let currentPointsMap = [
66
- // "x": point.x,
67
- // "y": point.y,
68
- // ]
69
-
70
- // pointsArray.append(currentPointsMap)
71
- // }
72
-
73
- // faceContoursTypesMap[faceContoursTypesStrings[i]] = pointsArray
74
- // }
75
- // }
76
-
77
- // return faceContoursTypesMap
78
- // }
79
-
80
- // static func processBoundingBox(from face: Face) -> [String:Any] {
81
- // let frameRect = face.frame
82
-
83
- // let offsetX = (frameRect.midX - ceil(frameRect.width)) / 2.0
84
- // let offsetY = (frameRect.midY - ceil(frameRect.height)) / 2.0
19
+
20
+ static func getImageFaceFromUIImage(from image: UIImage, rectImage: CGRect) -> UIImage? {
21
+ let imageRef: CGImage = (image.cgImage?.cropping(to: rectImage)!)!
22
+ let imageCrop: UIImage = UIImage(cgImage: imageRef, scale: 0.5, orientation: image.imageOrientation)
23
+ return imageCrop
24
+ }
25
+
26
+ static func convertImageToBase64(image: UIImage) -> String {
27
+ let imageData = image.pngData()!
28
+ return imageData.base64EncodedString()
29
+ }
30
+
31
+ static func rgbDataFromBuffer(_ buffer: CVPixelBuffer) -> Data? {
32
+ let byteCount = batchSize * inputWidth * inputHeight * inputChannels
33
+ CVPixelBufferLockBaseAddress(buffer, .readOnly)
34
+ defer {
35
+ CVPixelBufferUnlockBaseAddress(buffer, .readOnly)
36
+ }
37
+ guard let sourceData = CVPixelBufferGetBaseAddress(buffer) else {
38
+ return nil
39
+ }
85
40
 
86
- // let x = frameRect.maxX + offsetX
87
- // let y = frameRect.minY + offsetY
41
+ let width = CVPixelBufferGetWidth(buffer)
42
+ let height = CVPixelBufferGetHeight(buffer)
43
+ let sourceBytesPerRow = CVPixelBufferGetBytesPerRow(buffer)
44
+ let destinationChannelCount = 3
45
+ let destinationBytesPerRow = destinationChannelCount * width
88
46
 
89
- // return [
90
- // "x": frameRect.midX + (frameRect.midX - x),
91
- // "y": frameRect.midY + (y - frameRect.midY),
92
- // "width": frameRect.width,
93
- // "height": frameRect.height,
94
- // "boundingCenterX": frameRect.midX,
95
- // "boundingCenterY": frameRect.midY
96
- // ]
97
- // }
47
+ var sourceBuffer = vImage_Buffer(data: sourceData,
48
+ height: vImagePixelCount(height),
49
+ width: vImagePixelCount(width),
50
+ rowBytes: sourceBytesPerRow)
98
51
 
99
- static func getImageFaceFromUIImage(from image: UIImage, rectImage: CGRect) -> UIImage? {
100
- let imageRef: CGImage = (image.cgImage?.cropping(to: rectImage)!)!
101
- let imageCrop: UIImage = UIImage(cgImage: imageRef, scale: 0.5, orientation: image.imageOrientation)
102
- return imageCrop
52
+ guard let destinationData = malloc(height * destinationBytesPerRow) else {
53
+ print("Error: out of memory")
54
+ return nil
103
55
  }
104
56
 
105
- static func convertImageToBase64(image: UIImage) -> String {
106
- let imageData = image.pngData()!
107
- return imageData.base64EncodedString()
57
+ defer {
58
+ free(destinationData)
108
59
  }
109
60
 
110
- static func rgbDataFromBuffer(_ buffer: CVPixelBuffer) -> Data? {
111
- let byteCount = batchSize * inputWidth * inputHeight * inputChannels
112
- CVPixelBufferLockBaseAddress(buffer, .readOnly)
113
- defer {
114
- CVPixelBufferUnlockBaseAddress(buffer, .readOnly)
115
- }
116
- guard let sourceData = CVPixelBufferGetBaseAddress(buffer) else {
117
- return nil
118
- }
119
-
120
- let width = CVPixelBufferGetWidth(buffer)
121
- let height = CVPixelBufferGetHeight(buffer)
122
- let sourceBytesPerRow = CVPixelBufferGetBytesPerRow(buffer)
123
- let destinationChannelCount = 3
124
- let destinationBytesPerRow = destinationChannelCount * width
125
-
126
- var sourceBuffer = vImage_Buffer(data: sourceData,
127
- height: vImagePixelCount(height),
128
- width: vImagePixelCount(width),
129
- rowBytes: sourceBytesPerRow)
130
-
131
- guard let destinationData = malloc(height * destinationBytesPerRow) else {
132
- print("Error: out of memory")
133
- return nil
134
- }
135
-
136
- defer {
137
- free(destinationData)
138
- }
139
-
140
- var destinationBuffer = vImage_Buffer(data: destinationData,
141
- height: vImagePixelCount(height),
142
- width: vImagePixelCount(width),
143
- rowBytes: destinationBytesPerRow)
144
-
145
- let pixelBufferFormat = CVPixelBufferGetPixelFormatType(buffer)
146
-
147
- switch (pixelBufferFormat) {
148
- case kCVPixelFormatType_32BGRA:
149
- vImageConvert_BGRA8888toRGB888(&sourceBuffer, &destinationBuffer, UInt32(kvImageNoFlags))
150
- case kCVPixelFormatType_32ARGB:
151
- vImageConvert_ARGB8888toRGB888(&sourceBuffer, &destinationBuffer, UInt32(kvImageNoFlags))
152
- case kCVPixelFormatType_32RGBA:
153
- vImageConvert_RGBA8888toRGB888(&sourceBuffer, &destinationBuffer, UInt32(kvImageNoFlags))
154
- default:
155
- // Unknown pixel format.
156
- return nil
157
- }
158
-
159
- let byteData = Data(bytes: destinationBuffer.data, count: destinationBuffer.rowBytes * height)
160
- let bytes = Array<UInt8>(unsafeData: byteData)!
161
- var floats = [Float]()
162
- for i in 0..<bytes.count {
163
- floats.append(Float(bytes[i]) / 255.0)
164
- }
165
- return Data(copyingBufferOf: floats)
61
+ var destinationBuffer = vImage_Buffer(data: destinationData,
62
+ height: vImagePixelCount(height),
63
+ width: vImagePixelCount(width),
64
+ rowBytes: destinationBytesPerRow)
65
+
66
+ let pixelBufferFormat = CVPixelBufferGetPixelFormatType(buffer)
67
+
68
+ switch (pixelBufferFormat) {
69
+ case kCVPixelFormatType_32BGRA:
70
+ vImageConvert_BGRA8888toRGB888(&sourceBuffer, &destinationBuffer, UInt32(kvImageNoFlags))
71
+ case kCVPixelFormatType_32ARGB:
72
+ vImageConvert_ARGB8888toRGB888(&sourceBuffer, &destinationBuffer, UInt32(kvImageNoFlags))
73
+ case kCVPixelFormatType_32RGBA:
74
+ vImageConvert_RGBA8888toRGB888(&sourceBuffer, &destinationBuffer, UInt32(kvImageNoFlags))
75
+ default:
76
+ // Unknown pixel format.
77
+ return nil
166
78
  }
167
79
 
168
- static func uiImageToPixelBuffer(image: UIImage, size: Int) -> CVPixelBuffer? {
169
- let attrs = [kCVPixelBufferCGImageCompatibilityKey: kCFBooleanTrue, kCVPixelBufferCGBitmapContextCompatibilityKey: kCFBooleanTrue] as CFDictionary
170
- var pixelBuffer : CVPixelBuffer?
171
- let status = CVPixelBufferCreate(kCFAllocatorDefault, size, size, kCVPixelFormatType_32ARGB, attrs, &pixelBuffer)
172
- guard (status == kCVReturnSuccess) else {
173
- return nil
174
- }
175
-
176
- CVPixelBufferLockBaseAddress(pixelBuffer!, CVPixelBufferLockFlags(rawValue: 0))
177
- let pixelData = CVPixelBufferGetBaseAddress(pixelBuffer!)
178
-
179
- let rgbColorSpace = CGColorSpaceCreateDeviceRGB()
180
- let context = CGContext(data: pixelData, width: size, height: size, bitsPerComponent: 8, bytesPerRow: CVPixelBufferGetBytesPerRow(pixelBuffer!), space: rgbColorSpace, bitmapInfo: CGImageAlphaInfo.noneSkipFirst.rawValue)
181
-
182
- context?.translateBy(x: 0, y: CGFloat(size))
183
- context?.scaleBy(x: 1.0, y: -1.0)
184
-
185
- UIGraphicsPushContext(context!)
186
- image.draw(in: CGRect(x: 0, y: 0, width: size, height: size))
187
- UIGraphicsPopContext()
188
- CVPixelBufferUnlockBaseAddress(pixelBuffer!, CVPixelBufferLockFlags(rawValue: 0))
189
- return pixelBuffer
80
+ let byteData = Data(bytes: destinationBuffer.data, count: destinationBuffer.rowBytes * height)
81
+ let bytes = Array<UInt8>(unsafeData: byteData)!
82
+ var floats = [Float]()
83
+ for i in 0..<bytes.count {
84
+ floats.append(Float(bytes[i]) / 255.0)
190
85
  }
191
-
192
- static func getImageFaceFromBuffer(from sampleBuffer: CMSampleBuffer?, rectImage: CGRect, orientation: UIImage.Orientation) -> UIImage? {
193
- guard let sampleBuffer = sampleBuffer else {
194
- print("Sample buffer is NULL.")
195
- return nil
196
- }
197
- guard let imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer) else {
198
- print("Invalid sample buffer.")
199
- return nil
200
- }
201
- let ciimage = CIImage(cvPixelBuffer: imageBuffer)
202
- let context = CIContext(options: nil)
203
- let cgImage = context.createCGImage(ciimage, from: ciimage.extent)!
204
-
205
- if (!rectImage.isNull) {
206
- let imageRef: CGImage = cgImage.cropping(to: rectImage)!
207
- let imageCrop: UIImage = UIImage(cgImage: imageRef, scale: 0.5, orientation: orientation)
208
- return imageCrop
209
- } else {
210
- return nil
211
- }
86
+ return Data(copyingBufferOf: floats)
87
+ }
88
+
89
+ static func uiImageToPixelBuffer(image: UIImage, size: Int) -> CVPixelBuffer? {
90
+ let attrs = [kCVPixelBufferCGImageCompatibilityKey: kCFBooleanTrue, kCVPixelBufferCGBitmapContextCompatibilityKey: kCFBooleanTrue] as CFDictionary
91
+ var pixelBuffer : CVPixelBuffer?
92
+ let status = CVPixelBufferCreate(kCFAllocatorDefault, size, size, kCVPixelFormatType_32ARGB, attrs, &pixelBuffer)
93
+ guard (status == kCVReturnSuccess) else {
94
+ return nil
212
95
  }
213
96
 
214
- // static func getDataFromPixel(pixelBuffer: CVPixelBuffer) -> Data {
215
- // CVPixelBufferLockBaseAddress(pixelBuffer, [.readOnly])
216
- // defer { CVPixelBufferUnlockBaseAddress(pixelBuffer, [.readOnly]) }
217
- //
218
- // // Calculate sum of planes' size
219
- // var totalSize = 0
220
- // for plane in 0 ..< CVPixelBufferGetPlaneCount(pixelBuffer) {
221
- // let height = CVPixelBufferGetHeightOfPlane(pixelBuffer, plane)
222
- // let bytesPerRow = CVPixelBufferGetBytesPerRowOfPlane(pixelBuffer, plane)
223
- // let planeSize = height * bytesPerRow
224
- // totalSize += planeSize
225
- // }
226
- //
227
- // guard let rawFrame = malloc(totalSize) else { fatalError() }
228
- // var dest = rawFrame
229
- //
230
- // for plane in 0 ..< CVPixelBufferGetPlaneCount(pixelBuffer) {
231
- // let source = CVPixelBufferGetBaseAddressOfPlane(pixelBuffer, plane)
232
- // let height = CVPixelBufferGetHeightOfPlane(pixelBuffer, plane)
233
- // let bytesPerRow = CVPixelBufferGetBytesPerRowOfPlane(pixelBuffer, plane)
234
- // let planeSize = height * bytesPerRow
235
- //
236
- // memcpy(dest, source, planeSize)
237
- // dest += planeSize
238
- // }
239
- //
240
- // return Data(bytesNoCopy: rawFrame, count: totalSize, deallocator: .free)
241
- // }
97
+ CVPixelBufferLockBaseAddress(pixelBuffer!, CVPixelBufferLockFlags(rawValue: 0))
98
+ let pixelData = CVPixelBufferGetBaseAddress(pixelBuffer!)
99
+
100
+ let rgbColorSpace = CGColorSpaceCreateDeviceRGB()
101
+ let context = CGContext(data: pixelData, width: size, height: size, bitsPerComponent: 8, bytesPerRow: CVPixelBufferGetBytesPerRow(pixelBuffer!), space: rgbColorSpace, bitmapInfo: CGImageAlphaInfo.noneSkipFirst.rawValue)
102
+
103
+ context?.translateBy(x: 0, y: CGFloat(size))
104
+ context?.scaleBy(x: 1.0, y: -1.0)
105
+
106
+ UIGraphicsPushContext(context!)
107
+ image.draw(in: CGRect(x: 0, y: 0, width: size, height: size))
108
+ UIGraphicsPopContext()
109
+ CVPixelBufferUnlockBaseAddress(pixelBuffer!, CVPixelBufferLockFlags(rawValue: 0))
110
+ return pixelBuffer
111
+ }
112
+
113
+ static func getImageFaceFromBuffer(from sampleBuffer: CMSampleBuffer, rectImage: CGRect, orientation: UIImage.Orientation) -> CVPixelBuffer? {
114
+ autoreleasepool {
115
+ let imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer)
116
+ let ciimage = CIImage(cvPixelBuffer: imageBuffer!)
117
+ let context = CIContext(options: nil)
118
+ let cgImage = context.createCGImage(ciimage, from: ciimage.extent)!
119
+
120
+ let imageRef: CGImage = cgImage.cropping(to: rectImage)!
121
+ let imageCrop: UIImage = UIImage(cgImage: imageRef, scale: 0.5, orientation: orientation)
122
+ return uiImageToPixelBuffer(image: imageCrop, size: inputWidth)
123
+ }
124
+ }
242
125
  }
243
126
 
244
127
  // MARK: - Extensions
245
128
  extension Data {
246
- // Creates a new buffer by copying the buffer pointer of the given array.
247
- init<T>(copyingBufferOf array: [T]) {
248
- self = array.withUnsafeBufferPointer(Data.init)
249
- }
129
+ // Creates a new buffer by copying the buffer pointer of the given array.
130
+ init<T>(copyingBufferOf array: [T]) {
131
+ self = array.withUnsafeBufferPointer(Data.init)
132
+ }
250
133
  }
251
134
 
252
135
  extension Array {
253
- // Creates a new array from the bytes of the given unsafe data.
254
- init?(unsafeData: Data) {
255
- guard unsafeData.count % MemoryLayout<Element>.stride == 0 else { return nil }
256
- self = unsafeData.withUnsafeBytes { .init($0.bindMemory(to: Element.self)) }
257
- }
136
+ // Creates a new array from the bytes of the given unsafe data.
137
+ init?(unsafeData: Data) {
138
+ guard unsafeData.count % MemoryLayout<Element>.stride == 0 else { return nil }
139
+ self = unsafeData.withUnsafeBytes { .init($0.bindMemory(to: Element.self)) }
140
+ }
258
141
  }