質問編集履歴
3
問題点の訂正.
test
CHANGED
File without changes
|
test
CHANGED
@@ -10,7 +10,9 @@
|
|
10
10
|
|
11
11
|
問題は, 検出された座標を取得して服の画像が表示することが出来ないという点で躓いています.
|
12
12
|
|
13
|
-
1つ目のソースコードの下部, 米印(*)の部分で服の画像を出力させようとしています.
|
13
|
+
1つ目のソースコードの下部, **米印(*)**の部分で服の画像を出力させようとしています.
|
14
|
+
|
15
|
+
動作としては, 上半身の認識が確認できた時にボタンを押し, Upper bodyの座標に服の画像を出力する。
|
14
16
|
|
15
17
|
また, 2つ目のソースコードでは基本的に物体検出させる詳細が書かれています.
|
16
18
|
|
2
服の画像を出力するタイミングを、Buttonが押された時に動くように変更しました。それに伴い、Buttonの追加とソースコードの1部を変更しました。
test
CHANGED
File without changes
|
test
CHANGED
@@ -78,342 +78,350 @@
|
|
78
78
|
|
79
79
|
**********************
|
80
80
|
|
81
|
-
|
81
|
+
@IBOutlet weak var UIImageView: UIImageView!
|
82
|
+
|
82
|
-
|
83
|
+
@IBAction func tapBtn(_ sender: Any) {
|
84
|
+
|
83
|
-
func imageset(_ bounds: CGRect, identifier: String) -> UIImageView {
|
85
|
+
func imageset(_ bounds: CGRect, identifier: String) -> UIImageView {
|
86
|
+
|
87
|
+
let textLayer = CATextLayer()
|
88
|
+
|
89
|
+
let images = UIKit.UIImageView()
|
90
|
+
|
91
|
+
images.bounds = bounds
|
92
|
+
|
93
|
+
if textLayer.name == "Upper body"{
|
94
|
+
|
95
|
+
images.image = UIImage(named: "Upper body")
|
96
|
+
|
97
|
+
images.frame = CGRect(x: bounds.midX, y: bounds.midY, width: bounds.size.height, height: bounds.size.width)
|
98
|
+
|
99
|
+
images.center = CGPoint(x: bounds.midX, y: bounds.minY)
|
100
|
+
|
101
|
+
self.view.addSubview(images)
|
102
|
+
|
103
|
+
}else{
|
104
|
+
|
105
|
+
print("error")
|
106
|
+
|
107
|
+
}
|
108
|
+
|
109
|
+
return images
|
110
|
+
|
111
|
+
}
|
112
|
+
|
113
|
+
}
|
114
|
+
|
115
|
+
***********************
|
116
|
+
|
117
|
+
```
|
118
|
+
|
119
|
+
```Swift
|
120
|
+
|
121
|
+
import UIKit
|
122
|
+
|
123
|
+
import AVFoundation
|
124
|
+
|
125
|
+
import Vision
|
126
|
+
|
127
|
+
|
128
|
+
|
129
|
+
class VisionObjectRecognitionViewController: ViewController {
|
130
|
+
|
131
|
+
|
132
|
+
|
133
|
+
private var detectionOverlay: CALayer! = nil
|
134
|
+
|
135
|
+
|
136
|
+
|
137
|
+
// Visionパーツ
|
138
|
+
|
139
|
+
private var requests = [VNRequest]()
|
140
|
+
|
141
|
+
|
142
|
+
|
143
|
+
@discardableResult
|
144
|
+
|
145
|
+
func setupVision() -> NSError? {
|
146
|
+
|
147
|
+
// Visionパーツのセットアップ
|
148
|
+
|
149
|
+
let error: NSError! = nil
|
150
|
+
|
151
|
+
|
152
|
+
|
153
|
+
// MLモデルの指定, Visionモデルの指定
|
154
|
+
|
155
|
+
guard let modelURL = Bundle.main.url(forResource: "MyObjectDetector7", withExtension: "mlmodelc") else {
|
156
|
+
|
157
|
+
return NSError(domain: "VisionObjectRecognitionViewController", code: -1, userInfo: [NSLocalizedDescriptionKey: "Modelファイルがありません."])
|
158
|
+
|
159
|
+
}
|
160
|
+
|
161
|
+
do {
|
162
|
+
|
163
|
+
let visionModel = try VNCoreMLModel(for: MLModel(contentsOf: modelURL))
|
164
|
+
|
165
|
+
let objectRecognition = VNCoreMLRequest(model: visionModel, completionHandler: { (request, error) in
|
166
|
+
|
167
|
+
DispatchQueue.main.async(execute: {
|
168
|
+
|
169
|
+
// メインキューで全てのUI更新を実行
|
170
|
+
|
171
|
+
if let results = request.results {
|
172
|
+
|
173
|
+
self.drawVisionRequestResults(results)
|
174
|
+
|
175
|
+
}
|
176
|
+
|
177
|
+
})
|
178
|
+
|
179
|
+
})
|
180
|
+
|
181
|
+
self.requests = [objectRecognition]
|
182
|
+
|
183
|
+
} catch let error as NSError {
|
184
|
+
|
185
|
+
print("Modelが読み込めませんでした. (error)")
|
186
|
+
|
187
|
+
}
|
188
|
+
|
189
|
+
|
190
|
+
|
191
|
+
return error
|
192
|
+
|
193
|
+
}
|
194
|
+
|
195
|
+
|
196
|
+
|
197
|
+
func drawVisionRequestResults(_ results: [Any]) {
|
198
|
+
|
199
|
+
CATransaction.begin()
|
200
|
+
|
201
|
+
CATransaction.setValue(kCFBooleanTrue, forKey: kCATransactionDisableActions)
|
202
|
+
|
203
|
+
detectionOverlay.sublayers = nil // 古い認識したオブジェクトの値を削除
|
204
|
+
|
205
|
+
for observation in results where observation is VNRecognizedObjectObservation {
|
206
|
+
|
207
|
+
guard let objectObservation = observation as? VNRecognizedObjectObservation else {
|
208
|
+
|
209
|
+
continue
|
210
|
+
|
211
|
+
}
|
212
|
+
|
213
|
+
// 最も信頼性の高いラベルのみを選択
|
214
|
+
|
215
|
+
let topLabelObservation = objectObservation.labels[0] //最も信頼度の高い値を選ぶ
|
216
|
+
|
217
|
+
let objectBounds = VNImageRectForNormalizedRect(objectObservation.boundingBox, Int(bufferSize.width), Int(bufferSize.height))
|
218
|
+
|
219
|
+
|
220
|
+
|
221
|
+
let shapeLayer = self.createRoundedRectLayerWithBounds(objectBounds)
|
222
|
+
|
223
|
+
|
224
|
+
|
225
|
+
let textLayer = self.createTextSubLayerInBounds(objectBounds,
|
226
|
+
|
227
|
+
identifier: topLabelObservation.identifier,
|
228
|
+
|
229
|
+
confidence: topLabelObservation.confidence)
|
230
|
+
|
231
|
+
shapeLayer.addSublayer(textLayer)
|
232
|
+
|
233
|
+
detectionOverlay.addSublayer(shapeLayer)
|
234
|
+
|
235
|
+
}
|
236
|
+
|
237
|
+
self.updateLayerGeometry()
|
238
|
+
|
239
|
+
CATransaction.commit()
|
240
|
+
|
241
|
+
}
|
242
|
+
|
243
|
+
|
244
|
+
|
245
|
+
override func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) {
|
246
|
+
|
247
|
+
guard let pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer) else {
|
248
|
+
|
249
|
+
return
|
250
|
+
|
251
|
+
}
|
252
|
+
|
253
|
+
|
254
|
+
|
255
|
+
let exifOrientation = exifOrientationFromDeviceOrientation()
|
256
|
+
|
257
|
+
|
258
|
+
|
259
|
+
let imageRequestHandler = VNImageRequestHandler(cvPixelBuffer: pixelBuffer, orientation: exifOrientation, options: [:])
|
260
|
+
|
261
|
+
do {
|
262
|
+
|
263
|
+
try imageRequestHandler.perform(self.requests)
|
264
|
+
|
265
|
+
} catch {
|
266
|
+
|
267
|
+
print(error)
|
268
|
+
|
269
|
+
}
|
270
|
+
|
271
|
+
}
|
272
|
+
|
273
|
+
|
274
|
+
|
275
|
+
override func setupAVCapture() {
|
276
|
+
|
277
|
+
super.setupAVCapture()
|
278
|
+
|
279
|
+
|
280
|
+
|
281
|
+
// セットアップVisionパーツ
|
282
|
+
|
283
|
+
setupLayers()
|
284
|
+
|
285
|
+
updateLayerGeometry()
|
286
|
+
|
287
|
+
setupVision()
|
288
|
+
|
289
|
+
|
290
|
+
|
291
|
+
// キャプチャセッションをスタート
|
292
|
+
|
293
|
+
startCaptureSession()
|
294
|
+
|
295
|
+
}
|
296
|
+
|
297
|
+
|
298
|
+
|
299
|
+
func setupLayers() {
|
300
|
+
|
301
|
+
detectionOverlay = CALayer() // 観測された全てのコンテナレイヤー(レンダリングを含む)
|
302
|
+
|
303
|
+
detectionOverlay.name = "DetectionOverlay"
|
304
|
+
|
305
|
+
detectionOverlay.bounds = CGRect(x: 0.0,
|
306
|
+
|
307
|
+
y: 0.0,
|
308
|
+
|
309
|
+
width: bufferSize.width,
|
310
|
+
|
311
|
+
height: bufferSize.height)
|
312
|
+
|
313
|
+
detectionOverlay.position = CGPoint(x: rootLayer.bounds.midX, y: rootLayer.bounds.midY)
|
314
|
+
|
315
|
+
rootLayer.addSublayer(detectionOverlay)
|
316
|
+
|
317
|
+
}
|
318
|
+
|
319
|
+
|
320
|
+
|
321
|
+
func updateLayerGeometry() {
|
322
|
+
|
323
|
+
let bounds = rootLayer.bounds
|
324
|
+
|
325
|
+
var scale: CGFloat
|
326
|
+
|
327
|
+
|
328
|
+
|
329
|
+
let xScale: CGFloat = bounds.size.width / bufferSize.height
|
330
|
+
|
331
|
+
let yScale: CGFloat = bounds.size.height / bufferSize.width
|
332
|
+
|
333
|
+
|
334
|
+
|
335
|
+
scale = fmax(xScale, yScale)
|
336
|
+
|
337
|
+
if scale.isInfinite {
|
338
|
+
|
339
|
+
scale = 1.0
|
340
|
+
|
341
|
+
}
|
342
|
+
|
343
|
+
CATransaction.begin()
|
344
|
+
|
345
|
+
CATransaction.setValue(kCFBooleanTrue, forKey: kCATransactionDisableActions)
|
346
|
+
|
347
|
+
|
348
|
+
|
349
|
+
//レイヤーを画面の向きにし, スケールとミラーリング
|
350
|
+
|
351
|
+
detectionOverlay.setAffineTransform(CGAffineTransform(rotationAngle: CGFloat(.pi / 2.0)).scaledBy(x: scale, y: -scale))
|
352
|
+
|
353
|
+
//レーヤーを中央に配置
|
354
|
+
|
355
|
+
detectionOverlay.position = CGPoint(x: bounds.midX, y: bounds.midY)
|
356
|
+
|
357
|
+
|
358
|
+
|
359
|
+
CATransaction.commit()
|
360
|
+
|
361
|
+
|
362
|
+
|
363
|
+
}
|
364
|
+
|
365
|
+
|
366
|
+
|
367
|
+
func createTextSubLayerInBounds(_ bounds: CGRect, identifier: String, confidence: VNConfidence) -> CATextLayer {
|
84
368
|
|
85
369
|
let textLayer = CATextLayer()
|
86
370
|
|
87
|
-
let images = UIKit.UIImageView()
|
88
|
-
|
89
|
-
images.bounds = bounds
|
90
|
-
|
91
|
-
|
371
|
+
textLayer.name = "Object Label"
|
372
|
+
|
92
|
-
|
373
|
+
let formattedString = NSMutableAttributedString(string: String(format: "(identifier)\nConfidence: %.2f", confidence))
|
374
|
+
|
93
|
-
|
375
|
+
let largeFont = UIFont(name: "Helvetica", size: 24.0)!
|
376
|
+
|
94
|
-
|
377
|
+
formattedString.addAttributes([NSAttributedString.Key.font: largeFont], range: NSRange(location: 0, length: identifier.count))
|
378
|
+
|
379
|
+
textLayer.string = formattedString
|
380
|
+
|
95
|
-
|
381
|
+
textLayer.bounds = CGRect(x: 0, y: 0, width: bounds.size.height - 10, height: bounds.size.width - 10)
|
96
|
-
|
382
|
+
|
97
|
-
|
383
|
+
textLayer.position = CGPoint(x: bounds.midX, y: bounds.midY)
|
98
|
-
|
384
|
+
|
99
|
-
|
385
|
+
textLayer.shadowOpacity = 0.7
|
386
|
+
|
100
|
-
|
387
|
+
textLayer.shadowOffset = CGSize(width: 2, height: 2)
|
388
|
+
|
389
|
+
textLayer.foregroundColor = CGColor(colorSpace: CGColorSpaceCreateDeviceRGB(), components: [0.0, 0.0, 0.0, 1.0])
|
390
|
+
|
391
|
+
textLayer.contentsScale = 2.0 // retina rendering
|
392
|
+
|
393
|
+
//レイヤーを画面の向きに回転させ, 拡大縮小してミラーリングする
|
394
|
+
|
395
|
+
textLayer.setAffineTransform(CGAffineTransform(rotationAngle: CGFloat(.pi / 2.0)).scaledBy(x: 1.0, y: -1.0))
|
396
|
+
|
397
|
+
return textLayer
|
398
|
+
|
101
|
-
|
399
|
+
}
|
400
|
+
|
401
|
+
|
402
|
+
|
102
|
-
|
403
|
+
//認識した座標に矩形を表示
|
404
|
+
|
405
|
+
func createRoundedRectLayerWithBounds(_ bounds: CGRect) -> CALayer {
|
406
|
+
|
407
|
+
let shapeLayer = CALayer()
|
408
|
+
|
409
|
+
shapeLayer.bounds = bounds
|
410
|
+
|
411
|
+
shapeLayer.position = CGPoint(x: bounds.midX, y: bounds.midY)
|
412
|
+
|
413
|
+
shapeLayer.name = "Found Object"
|
414
|
+
|
415
|
+
shapeLayer.backgroundColor = CGColor(colorSpace: CGColorSpaceCreateDeviceRGB(), components: [1.0, 1.0, 1.0, 0.4])
|
416
|
+
|
417
|
+
shapeLayer.cornerRadius = 7
|
418
|
+
|
103
|
-
return
|
419
|
+
return shapeLayer
|
104
|
-
|
420
|
+
|
105
|
-
}
|
421
|
+
}
|
106
|
-
|
422
|
+
|
107
|
-
|
423
|
+
}
|
424
|
+
|
425
|
+
|
108
426
|
|
109
427
|
```
|
110
|
-
|
111
|
-
```Swift
|
112
|
-
|
113
|
-
import UIKit
|
114
|
-
|
115
|
-
import AVFoundation
|
116
|
-
|
117
|
-
import Vision
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
class VisionObjectRecognitionViewController: ViewController {
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
private var detectionOverlay: CALayer! = nil
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
// Visionパーツ
|
130
|
-
|
131
|
-
private var requests = [VNRequest]()
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
@discardableResult
|
136
|
-
|
137
|
-
func setupVision() -> NSError? {
|
138
|
-
|
139
|
-
// Visionパーツのセットアップ
|
140
|
-
|
141
|
-
let error: NSError! = nil
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
// MLモデルの指定, Visionモデルの指定
|
146
|
-
|
147
|
-
guard let modelURL = Bundle.main.url(forResource: "MyObjectDetector7", withExtension: "mlmodelc") else {
|
148
|
-
|
149
|
-
return NSError(domain: "VisionObjectRecognitionViewController", code: -1, userInfo: [NSLocalizedDescriptionKey: "Modelファイルがありません."])
|
150
|
-
|
151
|
-
}
|
152
|
-
|
153
|
-
do {
|
154
|
-
|
155
|
-
let visionModel = try VNCoreMLModel(for: MLModel(contentsOf: modelURL))
|
156
|
-
|
157
|
-
let objectRecognition = VNCoreMLRequest(model: visionModel, completionHandler: { (request, error) in
|
158
|
-
|
159
|
-
DispatchQueue.main.async(execute: {
|
160
|
-
|
161
|
-
// メインキューで全てのUI更新を実行
|
162
|
-
|
163
|
-
if let results = request.results {
|
164
|
-
|
165
|
-
self.drawVisionRequestResults(results)
|
166
|
-
|
167
|
-
}
|
168
|
-
|
169
|
-
})
|
170
|
-
|
171
|
-
})
|
172
|
-
|
173
|
-
self.requests = [objectRecognition]
|
174
|
-
|
175
|
-
} catch let error as NSError {
|
176
|
-
|
177
|
-
print("Modelが読み込めませんでした. (error)")
|
178
|
-
|
179
|
-
}
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
return error
|
184
|
-
|
185
|
-
}
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
func drawVisionRequestResults(_ results: [Any]) {
|
190
|
-
|
191
|
-
CATransaction.begin()
|
192
|
-
|
193
|
-
CATransaction.setValue(kCFBooleanTrue, forKey: kCATransactionDisableActions)
|
194
|
-
|
195
|
-
detectionOverlay.sublayers = nil // 古い認識したオブジェクトの値を削除
|
196
|
-
|
197
|
-
for observation in results where observation is VNRecognizedObjectObservation {
|
198
|
-
|
199
|
-
guard let objectObservation = observation as? VNRecognizedObjectObservation else {
|
200
|
-
|
201
|
-
continue
|
202
|
-
|
203
|
-
}
|
204
|
-
|
205
|
-
// 最も信頼性の高いラベルのみを選択
|
206
|
-
|
207
|
-
let topLabelObservation = objectObservation.labels[0] //最も信頼度の高い値を選ぶ
|
208
|
-
|
209
|
-
let objectBounds = VNImageRectForNormalizedRect(objectObservation.boundingBox, Int(bufferSize.width), Int(bufferSize.height))
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
let shapeLayer = self.createRoundedRectLayerWithBounds(objectBounds)
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
let textLayer = self.createTextSubLayerInBounds(objectBounds,
|
218
|
-
|
219
|
-
identifier: topLabelObservation.identifier,
|
220
|
-
|
221
|
-
confidence: topLabelObservation.confidence)
|
222
|
-
|
223
|
-
shapeLayer.addSublayer(textLayer)
|
224
|
-
|
225
|
-
detectionOverlay.addSublayer(shapeLayer)
|
226
|
-
|
227
|
-
}
|
228
|
-
|
229
|
-
self.updateLayerGeometry()
|
230
|
-
|
231
|
-
CATransaction.commit()
|
232
|
-
|
233
|
-
}
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
override func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) {
|
238
|
-
|
239
|
-
guard let pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer) else {
|
240
|
-
|
241
|
-
return
|
242
|
-
|
243
|
-
}
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
let exifOrientation = exifOrientationFromDeviceOrientation()
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
let imageRequestHandler = VNImageRequestHandler(cvPixelBuffer: pixelBuffer, orientation: exifOrientation, options: [:])
|
252
|
-
|
253
|
-
do {
|
254
|
-
|
255
|
-
try imageRequestHandler.perform(self.requests)
|
256
|
-
|
257
|
-
} catch {
|
258
|
-
|
259
|
-
print(error)
|
260
|
-
|
261
|
-
}
|
262
|
-
|
263
|
-
}
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
override func setupAVCapture() {
|
268
|
-
|
269
|
-
super.setupAVCapture()
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
// セットアップVisionパーツ
|
274
|
-
|
275
|
-
setupLayers()
|
276
|
-
|
277
|
-
updateLayerGeometry()
|
278
|
-
|
279
|
-
setupVision()
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
// キャプチャセッションをスタート
|
284
|
-
|
285
|
-
startCaptureSession()
|
286
|
-
|
287
|
-
}
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
func setupLayers() {
|
292
|
-
|
293
|
-
detectionOverlay = CALayer() // 観測された全てのコンテナレイヤー(レンダリングを含む)
|
294
|
-
|
295
|
-
detectionOverlay.name = "DetectionOverlay"
|
296
|
-
|
297
|
-
detectionOverlay.bounds = CGRect(x: 0.0,
|
298
|
-
|
299
|
-
y: 0.0,
|
300
|
-
|
301
|
-
width: bufferSize.width,
|
302
|
-
|
303
|
-
height: bufferSize.height)
|
304
|
-
|
305
|
-
detectionOverlay.position = CGPoint(x: rootLayer.bounds.midX, y: rootLayer.bounds.midY)
|
306
|
-
|
307
|
-
rootLayer.addSublayer(detectionOverlay)
|
308
|
-
|
309
|
-
}
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
func updateLayerGeometry() {
|
314
|
-
|
315
|
-
let bounds = rootLayer.bounds
|
316
|
-
|
317
|
-
var scale: CGFloat
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
let xScale: CGFloat = bounds.size.width / bufferSize.height
|
322
|
-
|
323
|
-
let yScale: CGFloat = bounds.size.height / bufferSize.width
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
scale = fmax(xScale, yScale)
|
328
|
-
|
329
|
-
if scale.isInfinite {
|
330
|
-
|
331
|
-
scale = 1.0
|
332
|
-
|
333
|
-
}
|
334
|
-
|
335
|
-
CATransaction.begin()
|
336
|
-
|
337
|
-
CATransaction.setValue(kCFBooleanTrue, forKey: kCATransactionDisableActions)
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
//レイヤーを画面の向きにし, スケールとミラーリング
|
342
|
-
|
343
|
-
detectionOverlay.setAffineTransform(CGAffineTransform(rotationAngle: CGFloat(.pi / 2.0)).scaledBy(x: scale, y: -scale))
|
344
|
-
|
345
|
-
//レーヤーを中央に配置
|
346
|
-
|
347
|
-
detectionOverlay.position = CGPoint(x: bounds.midX, y: bounds.midY)
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
CATransaction.commit()
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
}
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
func createTextSubLayerInBounds(_ bounds: CGRect, identifier: String, confidence: VNConfidence) -> CATextLayer {
|
360
|
-
|
361
|
-
let textLayer = CATextLayer()
|
362
|
-
|
363
|
-
textLayer.name = "Object Label"
|
364
|
-
|
365
|
-
let formattedString = NSMutableAttributedString(string: String(format: "(identifier)\nConfidence: %.2f", confidence))
|
366
|
-
|
367
|
-
let largeFont = UIFont(name: "Helvetica", size: 24.0)!
|
368
|
-
|
369
|
-
formattedString.addAttributes([NSAttributedString.Key.font: largeFont], range: NSRange(location: 0, length: identifier.count))
|
370
|
-
|
371
|
-
textLayer.string = formattedString
|
372
|
-
|
373
|
-
textLayer.bounds = CGRect(x: 0, y: 0, width: bounds.size.height - 10, height: bounds.size.width - 10)
|
374
|
-
|
375
|
-
textLayer.position = CGPoint(x: bounds.midX, y: bounds.midY)
|
376
|
-
|
377
|
-
textLayer.shadowOpacity = 0.7
|
378
|
-
|
379
|
-
textLayer.shadowOffset = CGSize(width: 2, height: 2)
|
380
|
-
|
381
|
-
textLayer.foregroundColor = CGColor(colorSpace: CGColorSpaceCreateDeviceRGB(), components: [0.0, 0.0, 0.0, 1.0])
|
382
|
-
|
383
|
-
textLayer.contentsScale = 2.0 // retina rendering
|
384
|
-
|
385
|
-
//レイヤーを画面の向きに回転させ, 拡大縮小してミラーリングする
|
386
|
-
|
387
|
-
textLayer.setAffineTransform(CGAffineTransform(rotationAngle: CGFloat(.pi / 2.0)).scaledBy(x: 1.0, y: -1.0))
|
388
|
-
|
389
|
-
return textLayer
|
390
|
-
|
391
|
-
}
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
//認識した座標に矩形を表示
|
396
|
-
|
397
|
-
func createRoundedRectLayerWithBounds(_ bounds: CGRect) -> CALayer {
|
398
|
-
|
399
|
-
let shapeLayer = CALayer()
|
400
|
-
|
401
|
-
shapeLayer.bounds = bounds
|
402
|
-
|
403
|
-
shapeLayer.position = CGPoint(x: bounds.midX, y: bounds.midY)
|
404
|
-
|
405
|
-
shapeLayer.name = "Found Object"
|
406
|
-
|
407
|
-
shapeLayer.backgroundColor = CGColor(colorSpace: CGColorSpaceCreateDeviceRGB(), components: [1.0, 1.0, 1.0, 0.4])
|
408
|
-
|
409
|
-
shapeLayer.cornerRadius = 7
|
410
|
-
|
411
|
-
return shapeLayer
|
412
|
-
|
413
|
-
}
|
414
|
-
|
415
|
-
}
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
```
|
1
使用しているサンプルプログラムのリンクを追記しました.
test
CHANGED
File without changes
|
test
CHANGED
@@ -16,6 +16,10 @@
|
|
16
16
|
|
17
17
|
カメラセッションなどは省力します。
|
18
18
|
|
19
|
+
**以下のサンプルに手を加えて, 画像を出力出来るように考えています.**
|
20
|
+
|
21
|
+
【https://developer.apple.com/documentation/vision/recognizing_objects_in_live_capture】
|
22
|
+
|
19
23
|
### 該当のソースコード
|
20
24
|
|
21
25
|
```Swift
|