質問編集履歴

5

動作確認済みソースコード編集

2018/08/03 10:58

投稿

nobu09
nobu09

スコア34

test CHANGED
File without changes
test CHANGED
@@ -26,19 +26,187 @@
26
26
 
27
27
  ```swift
28
28
 
29
+ class ViewController: UIViewController, AVCaptureVideoDataOutputSampleBufferDelegate {
30
+
31
+
32
+
33
+ @IBOutlet var previewView: UIImageView!
34
+
35
+
36
+
37
+ var session = AVCaptureSession()
38
+
39
+ var videoOutput = AVCaptureVideoDataOutput()
40
+
41
+
42
+
43
+ var images:[UIImage] = []
44
+
45
+
46
+
47
+ var count: Int = 0
48
+
49
+
50
+
51
+ override func viewDidLoad() {
52
+
53
+ super.viewDidLoad()
54
+
55
+
56
+
57
+ if session.isRunning {
58
+
59
+ return
60
+
61
+ }
62
+
63
+
64
+
65
+ images.removeAll()
66
+
67
+
68
+
69
+ setupInputOutput()
70
+
71
+
72
+
73
+ self.session.startRunning()
74
+
75
+ }
76
+
77
+
78
+
79
+ override func didReceiveMemoryWarning() {
80
+
81
+ super.didReceiveMemoryWarning()
82
+
83
+ }
84
+
85
+
86
+
87
+ func setupInputOutput() {
88
+
89
+
90
+
91
+ session.sessionPreset = AVCaptureSession.Preset.medium
92
+
93
+
94
+
95
+ do {
96
+
97
+ let device = AVCaptureDevice.default(
98
+
99
+ AVCaptureDevice.DeviceType.builtInWideAngleCamera,
100
+
101
+ for: AVMediaType.video,
102
+
103
+ position: AVCaptureDevice.Position.back
104
+
105
+ )
106
+
107
+ device?.activeVideoMinFrameDuration = CMTimeMake(1, 30)
108
+
109
+
110
+
111
+ let input = try! AVCaptureDeviceInput(device: device!)
112
+
113
+ if session.canAddInput(input) {
114
+
115
+ session.addInput(input)
116
+
117
+ } else {
118
+
119
+ print("Can't add input to session")
120
+
121
+ return
122
+
123
+ }
124
+
125
+ } catch let error as NSError {
126
+
127
+ print("no camera (error)")
128
+
129
+ return
130
+
131
+ }
132
+
133
+
134
+
135
+ videoOutput.videoSettings = [kCVPixelBufferPixelFormatTypeKey as AnyHashable : Int(kCVPixelFormatType_32BGRA)] as! [String : Any]
136
+
137
+ videoOutput.alwaysDiscardsLateVideoFrames = true
138
+
139
+ videoOutput.setSampleBufferDelegate(self, queue: DispatchQueue.main)
140
+
141
+ if session.canAddOutput(videoOutput) {
142
+
143
+ session.addOutput(videoOutput)
144
+
145
+ } else {
146
+
147
+ print("Can't add output to session")
148
+
149
+ return
150
+
151
+ }
152
+
153
+ }
154
+
155
+
156
+
157
+ func setPreviewLayer() {
158
+
159
+ let previewLayer = AVCaptureVideoPreviewLayer(session: session)
160
+
161
+ guard let videoLayer: AVCaptureVideoPreviewLayer = previewLayer else {
162
+
163
+ print("Can't create preview layer.")
164
+
165
+ return
166
+
167
+ }
168
+
169
+
170
+
171
+ videoLayer.frame = previewView.bounds
172
+
173
+ videoLayer.masksToBounds = true
174
+
175
+ videoLayer.videoGravity = AVLayerVideoGravity.resizeAspectFill
176
+
177
+ previewView.layer.addSublayer(videoLayer)
178
+
179
+ }
180
+
181
+
182
+
29
183
  func captureOutput(_ captureOutput: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) {
30
184
 
185
+ let imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer)!
186
+
187
+ // イメージバッファのロック
188
+
189
+ CVPixelBufferLockBaseAddress(imageBuffer, CVPixelBufferLockFlags(rawValue: 0))
190
+
191
+
192
+
31
- let image = self.imageFromSampleBuffer(sampleBuffer: sampleBuffer)
193
+ self.imageFromSampleBuffer(sampleBuffer: sampleBuffer)
32
-
194
+
195
+
196
+
33
- // addImage(image: image)
197
+ CVPixelBufferUnlockBaseAddress(imageBuffer, CVPixelBufferLockFlags(rawValue: 0))
198
+
199
+
200
+
34
-
201
+ DispatchQueue.main.async {
35
-
36
-
202
+
37
- previewView.image = image
203
+ self.previewView.image = image
38
-
204
+
39
- }
205
+ }
206
+
40
-
207
+ }
41
-
208
+
209
+
42
210
 
43
211
  func imageFromSampleBuffer(sampleBuffer :CMSampleBuffer) -> UIImage {
44
212
 
@@ -46,12 +214,6 @@
46
214
 
47
215
 
48
216
 
49
- // イメージバッファのロック
50
-
51
- CVPixelBufferLockBaseAddress(imageBuffer, CVPixelBufferLockFlags(rawValue: 0))
52
-
53
-
54
-
55
217
  // 画像情報を取得
56
218
 
57
219
  let base = CVPixelBufferGetBaseAddressOfPlane(imageBuffer, 0)!
@@ -80,31 +242,13 @@
80
242
 
81
243
  let imageRef = newContext.makeImage()!
82
244
 
245
+
246
+
83
- // ここのreturnUIImageを返すと画像がちゃんと表示される (1)
247
+ // (1)ここでimgを返すとキャプチャした画像が正常に表示される
84
-
248
+
85
- //return UIImage(cgImage: imageRef, scale: 1.0, orientation: UIImageOrientation.right)
249
+ //let img = UIImage(cgImage: imageRef, scale: 1.0, orientation: UIImageOrientation.right)
86
-
87
-
88
-
89
- CVPixelBufferUnlockBaseAddress(imageBuffer, CVPixelBufferLockFlags(rawValue: 0))
250
+
90
-
91
- var img = getByteArrayFromImage(imageRef: imageRef)
92
-
93
- return img
251
+ //return img
94
-
95
- }
96
-
97
-
98
-
99
- func getByteArrayFromImage(imageRef: CGImage) -> UIImage {
100
-
101
- let editedimage:UIImage
102
-
103
-
104
-
105
- let width_n :Int = Int((imageRef.width))
106
-
107
- let height_n :Int = Int((imageRef.height))
108
252
 
109
253
 
110
254
 
@@ -114,45 +258,31 @@
114
258
 
115
259
  var rawData = [UInt8](repeating: 0, count: length)
116
260
 
117
-
118
-
119
261
  CFDataGetBytes(data, CFRange(location: 0, length: length), &rawData)
120
262
 
121
- //for (index, _) in rawData.enumerated() {
263
+
122
-
123
- // rawData[index] = 255
264
+
124
-
125
- //}
126
-
127
-
128
-
129
- let provider = CGDataProvider(dataInfo: nil,data: rawData, size: length,releaseData: releaseData)
265
+ let provider = CGDataProvider(dataInfo: nil,data: &rawData, size: length,releaseData: releaseData)
130
-
131
- let colorSpaceRef = imageRef.colorSpace
132
-
133
- let bitmapInfo_n = imageRef.bitmapInfo
134
-
135
- let bitsPerComponent:Int = imageRef.bitsPerComponent
136
266
 
137
267
  let bitsPerPixel = imageRef.bitsPerPixel
138
268
 
139
- let bytesPerRow_n = imageRef.bytesPerRow
140
-
141
- let cgImage = CGImage(width: width_n, height: height_n, bitsPerComponent: bitsPerComponent, bitsPerPixel: bitsPerPixel, bytesPerRow:bytesPerRow_n, space: colorSpaceRef!, bitmapInfo: bitmapInfo_n, provider: provider!, decode: nil, shouldInterpolate: false, intent: .defaultIntent)
142
-
143
-
144
-
145
- editedimage = UIImage(cgImage:cgImage!, scale:1.0, orientation:UIImageOrientation.right)
146
-
147
-
148
-
149
- // (2) editedimageには画像データが正常に入っている
269
+ let cgImage = CGImage(width: Int(width), height: Int(height), bitsPerComponent: bitsPerCompornent, bitsPerPixel: bitsPerPixel, bytesPerRow:Int(bytesPerRow), space: colorSpace, bitmapInfo: bitmapInfo, provider: provider!, decode: nil, shouldInterpolate: false, intent: .defaultIntent)
270
+
271
+
272
+
273
+ let editedimage = UIImage(cgImage:cgImage!, scale:1.0, orientation:UIImageOrientation.right)
274
+
275
+
276
+
277
+ // (2)ここで返すと画像が異常になる。
150
278
 
151
279
  return editedimage
152
280
 
153
-
154
-
155
- }
281
+ }
282
+
283
+ }
284
+
285
+
156
286
 
157
287
  ```
158
288
 

4

コメントアウト

2018/08/03 10:58

投稿

nobu09
nobu09

スコア34

test CHANGED
File without changes
test CHANGED
@@ -118,11 +118,11 @@
118
118
 
119
119
  CFDataGetBytes(data, CFRange(location: 0, length: length), &rawData)
120
120
 
121
- for (index, _) in rawData.enumerated() {
121
+ //for (index, _) in rawData.enumerated() {
122
122
 
123
- rawData[index] = 255
123
+ // rawData[index] = 255
124
124
 
125
- }
125
+ //}
126
126
 
127
127
 
128
128
 

3

発生した現象を編集

2018/08/03 05:58

投稿

nobu09
nobu09

スコア34

test CHANGED
File without changes
test CHANGED
@@ -8,7 +8,15 @@
8
8
 
9
9
  キャプチャ画像→ピクセルデータ配列→何かしらの処理→UIImageという処理をしたいのですが、
10
10
 
11
- メソッド内で作成したUIImagを返り値で別の変数に代入するとの画像が壊れています。
11
+ メソッド内で作成したUIImagを返り値で別の変数に代入した際タイミングによって代入先の画像が壊れています。
12
+
13
+
14
+
15
+ 具体的には、以下のソースコード内の
16
+
17
+ (1)の部分でreturnした場合は、正常に画像が渡され表示できます。
18
+
19
+ (2)の部分でreturnした場合は、異常な画像データが渡されてしまいます。
12
20
 
13
21
 
14
22
 
@@ -72,6 +80,12 @@
72
80
 
73
81
  let imageRef = newContext.makeImage()!
74
82
 
83
+ // ここのreturnでUIImageを返すと、画像がちゃんと表示される (1)
84
+
85
+ //return UIImage(cgImage: imageRef, scale: 1.0, orientation: UIImageOrientation.right)
86
+
87
+
88
+
75
89
  CVPixelBufferUnlockBaseAddress(imageBuffer, CVPixelBufferLockFlags(rawValue: 0))
76
90
 
77
91
  var img = getByteArrayFromImage(imageRef: imageRef)
@@ -130,7 +144,9 @@
130
144
 
131
145
  editedimage = UIImage(cgImage:cgImage!, scale:1.0, orientation:UIImageOrientation.right)
132
146
 
147
+
148
+
133
-
149
+ // (2) editedimageには画像データが正常に入っている
134
150
 
135
151
  return editedimage
136
152
 

2

swiftのバージョンの修正

2018/08/02 05:51

投稿

nobu09
nobu09

スコア34

test CHANGED
File without changes
test CHANGED
@@ -148,4 +148,4 @@
148
148
 
149
149
  xcode Version 9.4.1
150
150
 
151
- Swift3.0
151
+ Swift4.0

1

ソースコードの編集

2018/08/02 03:30

投稿

nobu09
nobu09

スコア34

test CHANGED
@@ -1 +1 @@
1
- [Swift3]カメラ画像→ピクセルデータ配列→UIImageと順番に変換したい
1
+ [Swift3]カメラ画像→ピクセルデータ配列→UIImageと順番に変換したい[編集]
test CHANGED
@@ -4,25 +4,27 @@
4
4
 
5
5
 
6
6
 
7
- ### 発生している問題・エラーメッセージ
7
+ ### 発生している問題・エラーメッセージ[編集]
8
8
 
9
9
  キャプチャ画像→ピクセルデータ配列→何かしらの処理→UIImageという処理をしたいのですが、
10
10
 
11
- 何か処理が実施されない状態でキャプチャした画像がそのまま表示されてう状態です。
11
+ メソッド内で作成たUIImagを返り値で別変数に代入するとその画像がれてます。
12
12
 
13
13
 
14
14
 
15
- ### 該当のソースコード
15
+ ### 該当のソースコード[編集]
16
16
 
17
17
 
18
18
 
19
19
  ```swift
20
20
 
21
- func captureOutput(_ captureOutput: AVCaptureOutput!, didOutputSampleBuffer sampleBuffer: CMSampleBuffer!, from connection: AVCaptureConnection!) {
21
+ func captureOutput(_ captureOutput: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) {
22
22
 
23
- let image = imageFromSampleBuffer(sampleBuffer: sampleBuffer)
23
+ let image = self.imageFromSampleBuffer(sampleBuffer: sampleBuffer)
24
24
 
25
-
25
+ // addImage(image: image)
26
+
27
+
26
28
 
27
29
  previewView.image = image
28
30
 
@@ -30,7 +32,7 @@
30
32
 
31
33
 
32
34
 
33
- func imageFromSampleBuffer(sampleBuffer :CMSampleBuffer) -> UIImage {
35
+ func imageFromSampleBuffer(sampleBuffer :CMSampleBuffer) -> UIImage {
34
36
 
35
37
  let imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer)!
36
38
 
@@ -70,11 +72,29 @@
70
72
 
71
73
  let imageRef = newContext.makeImage()!
72
74
 
75
+ CVPixelBufferUnlockBaseAddress(imageBuffer, CVPixelBufferLockFlags(rawValue: 0))
76
+
77
+ var img = getByteArrayFromImage(imageRef: imageRef)
78
+
79
+ return img
80
+
81
+ }
82
+
83
+
84
+
73
- let image = UIImage(cgImage: imageRef, scale: 1.0, orientation: UIImageOrientation.right)
85
+ func getByteArrayFromImage(imageRef: CGImage) -> UIImage {
86
+
87
+ let editedimage:UIImage
74
88
 
75
89
 
76
90
 
91
+ let width_n :Int = Int((imageRef.width))
92
+
93
+ let height_n :Int = Int((imageRef.height))
94
+
95
+
96
+
77
- let data = image.cgImage?.dataProvider?.data
97
+ let data = imageRef.dataProvider!.data
78
98
 
79
99
  let length = CFDataGetLength(data)
80
100
 
@@ -84,55 +104,35 @@
84
104
 
85
105
  CFDataGetBytes(data, CFRange(location: 0, length: length), &rawData)
86
106
 
87
-
88
-
89
- // ピクセルデータrawDataの値操作
90
-
91
-      // ここで画素データを使用して何かしらの処理をしたい
92
-
93
-      // テストとして全値を0にする
94
-
95
107
  for (index, _) in rawData.enumerated() {
96
108
 
97
- rawData[index] = 0
109
+ rawData[index] = 255
98
110
 
99
111
  }
100
112
 
101
113
 
102
114
 
103
- let data = CGDataProvider(dataInfo: nil, data: rawData, size: length) { _,_,_ in }
115
+ let provider = CGDataProvider(dataInfo: nil,data: rawData, size: length,releaseData: releaseData)
104
116
 
105
- .flatMap {
117
+ let colorSpaceRef = imageRef.colorSpace
106
118
 
107
- CGImage(width: Int(width),
119
+ let bitmapInfo_n = imageRef.bitmapInfo
108
120
 
109
- height: Int(height),
121
+ let bitsPerComponent:Int = imageRef.bitsPerComponent
110
122
 
111
- bitsPerComponent: 32,
123
+ let bitsPerPixel = imageRef.bitsPerPixel
112
124
 
113
- bitsPerPixel: Int(bytesPerRow / 32),
125
+ let bytesPerRow_n = imageRef.bytesPerRow
114
126
 
115
- bytesPerRow: Int(width * bytesPerRow),
116
-
117
- space: CGColorSpaceCreateDeviceRGB(),
118
-
119
- bitmapInfo: [],
120
-
121
- provider: $0,
122
-
123
- decode: nil,
124
-
125
- shouldInterpolate: false,
126
-
127
- intent: .defaultIntent)
128
-
129
- }
130
-
131
- CVPixelBufferUnlockBaseAddress(imageBuffer, CVPixelBufferLockFlags(rawValue: 0))
127
+ let cgImage = CGImage(width: width_n, height: height_n, bitsPerComponent: bitsPerComponent, bitsPerPixel: bitsPerPixel, bytesPerRow:bytesPerRow_n, space: colorSpaceRef!, bitmapInfo: bitmapInfo_n, provider: provider!, decode: nil, shouldInterpolate: false, intent: .defaultIntent)
132
128
 
133
129
 
134
130
 
131
+ editedimage = UIImage(cgImage:cgImage!, scale:1.0, orientation:UIImageOrientation.right)
132
+
133
+
134
+
135
- return UIImage(cgImage: d!)
135
+ return editedimage
136
136
 
137
137
 
138
138