質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

Q&A

解決済

1回答

5099閲覧

AVFoundationから取得した画像をciImageに変換するとサイズと角度が変わってしまいます。

TakumiOchiai

総合スコア10

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

0グッド

0クリップ

投稿2018/04/22 14:24

swift初心者(3ヶ月遊んでいる程度)のプログラマーでございます。
現在カメラアプリを作成しております。

sampleBufferから、UIImageを作成し、その画像に対して、CIImageに変換すると、
90度回転してしまっている状態になってしまいます。

原因がまったくわからず、困っております。。。

具体的なソースは以下の通りです。
みなさま、よろしくお願い致します。

Xcode:9.3
swift:4.1

swift

1 2import UIKit 3import AVFoundation 4 5class ViewController: UIViewController,AVCaptureVideoDataOutputSampleBufferDelegate,UIGestureRecognizerDelegate { 6 7 var input:AVCaptureDeviceInput! 8 var output:AVCaptureVideoDataOutput! 9 var session:AVCaptureSession! 10 var camera:AVCaptureDevice! 11 var imageView:UIImageView! 12 13 override func viewDidLoad() { 14 super.viewDidLoad() 15 } 16 17 // SafeAreaのサイズを取得するためviewDidAppearまで待つ 18 override func viewDidAppear(_ animated: Bool) { 19 // スクリーン設定 20 setupDisplay() 21 // カメラの設定 22 setupCamera() 23 } 24 25 func setupDisplay(){ 26 //スクリーンの幅 27 let screenWidth = UIScreen.main.bounds.size.width; 28 //スクリーンの高さ 29 let screenHeight = UIScreen.main.bounds.size.height; 30 31 // プレビュー用のビューを生成 32 imageView = UIImageView() 33 34 var topPadding:CGFloat = 0 35 //var bottomPadding:CGFloat = 0 36 var leftPadding:CGFloat = 0 37 var rightPadding:CGFloat = 0 38 39 // iPhone X , X以外は0となる 40 if #available(iOS 11.0, *) { 41 let window = UIApplication.shared.keyWindow 42 topPadding = window!.safeAreaInsets.top 43 //bottomPadding = window!.safeAreaInsets.bottom 44 leftPadding = window!.safeAreaInsets.left 45 rightPadding = window!.safeAreaInsets.right 46 } 47 48 // portrait 49 let safeAreaWidth = screenWidth - leftPadding - rightPadding 50 //let safeAreaHeight = (screenHeight) - topPadding - bottomPadding 51 52 // カメラ画像サイズはsessionPresetによって変わる 53 // とりあえず16:9のportraitとして設定 54 let rect = CGRect(x: leftPadding, y: topPadding, 55 width: safeAreaWidth, height: safeAreaWidth/9*16) 56 57 // frame をCGRectで作った矩形に合わせる 58 imageView.frame = rect 59 imageView.center = CGPoint(x: screenWidth/2, y: screenHeight/2) 60 } 61 62 func setupCamera(){ 63 // AVCaptureSession: キャプチャに関する入力と出力の管理 64 session = AVCaptureSession() 65 66 // sessionPreset: キャプチャ・クオリティの設定 67 session.sessionPreset = AVCaptureSession.Preset.high 68 69 // 背面・前面カメラの選択 iOS10での変更 70 camera = AVCaptureDevice.default( 71 AVCaptureDevice.DeviceType.builtInWideAngleCamera, 72 for: AVMediaType.video, 73 position: .back) // position: .front 74 75 // カメラからの入力データ 76 do { 77 input = try AVCaptureDeviceInput(device: camera) as AVCaptureDeviceInput 78 } catch let error as NSError { 79 print(error) 80 } 81 82 // 入力をセッションに追加 83 if(session.canAddInput(input)) { 84 session.addInput(input) 85 } 86 87 // AVCaptureVideoDataOutput:動画フレームデータを出力に設定 88 output = AVCaptureVideoDataOutput() 89 // 出力をセッションに追加 90 if(session.canAddOutput(output)) { 91 session.addOutput(output) 92 } 93 94 // ピクセルフォーマットを 32bit BGR + A とする 95 output.videoSettings = 96 [kCVPixelBufferPixelFormatTypeKey as AnyHashable as! 97 String : Int(kCVPixelFormatType_32BGRA)] 98 99 // フレームをキャプチャするためのサブスレッド用のシリアルキューを用意 100 output.setSampleBufferDelegate(self, queue: DispatchQueue.main) 101 102 output.alwaysDiscardsLateVideoFrames = true 103 104 // ビデオ出力に接続 105 //let connection = output.connection(with: AVMediaType.video) 106 107 session.startRunning() 108 109 // deviceをロックして設定 110 // swift 2.0 111 do { 112 try camera.lockForConfiguration() 113 // フレームレート 114 camera.activeVideoMinFrameDuration = CMTimeMake(1, 30) 115 116 camera.unlockForConfiguration() 117 } catch _ { 118 } 119 } 120 121 // 新しいキャプチャの追加で呼ばれる 122 func captureOutput(_ captureOutput: AVCaptureOutput, 123 didOutput sampleBuffer: CMSampleBuffer, 124 from connection: AVCaptureConnection) { 125 126 // キャプチャしたsampleBufferからUIImageを作成 127 let image:UIImage = self.captureImage(sampleBuffer) 128 129 let ciImage:CIImage = CIImage(image:image)!; 130 131 let ciFilter:CIFilter = CIFilter(name: "CISepiaTone")! 132 ciFilter.setValue(ciImage, forKey: kCIInputImageKey) 133 ciFilter.setValue(0.8, forKey: "inputIntensity") 134 let ciContext:CIContext = CIContext(options: nil) 135 136 let cgimg:CGImage = ciContext.createCGImage(ciFilter.outputImage!, from:ciFilter.outputImage!.extent)! 137 let outputImage = UIImage(cgImage: cgimg) 138 139 // 画像を画面に表示 140 DispatchQueue.main.async { 141 self.imageView.image = outputImage 142 143 // UIImageViewをビューに追加 144 self.view.addSubview(self.imageView) 145 } 146 } 147 148 // sampleBufferからUIImageを作成 149 func captureImage(_ sampleBuffer:CMSampleBuffer) -> UIImage{ 150 151 // Sampling Bufferから画像を取得 152 let imageBuffer:CVImageBuffer = 153 CMSampleBufferGetImageBuffer(sampleBuffer)! 154 155 // pixel buffer のベースアドレスをロック 156 CVPixelBufferLockBaseAddress(imageBuffer, 157 CVPixelBufferLockFlags(rawValue: CVOptionFlags(0))) 158 159 let baseAddress:UnsafeMutableRawPointer = 160 CVPixelBufferGetBaseAddressOfPlane(imageBuffer, 0)! 161 162 let bytesPerRow:Int = CVPixelBufferGetBytesPerRow(imageBuffer) 163 let width:Int = CVPixelBufferGetWidth(imageBuffer) 164 let height:Int = CVPixelBufferGetHeight(imageBuffer) 165 166 167 // 色空間 168 let colorSpace:CGColorSpace = CGColorSpaceCreateDeviceRGB() 169 170 //let bitsPerCompornent:Int = 8 171 // swift 2.0 172 let newContext:CGContext = CGContext(data: baseAddress, 173 width: width, height: height, bitsPerComponent: 8, 174 bytesPerRow: bytesPerRow, space: colorSpace, 175 bitmapInfo: CGImageAlphaInfo.premultipliedFirst.rawValue|CGBitmapInfo.byteOrder32Little.rawValue)! 176 177 let imageRef:CGImage = newContext.makeImage()! 178 let resultImage = UIImage(cgImage: imageRef, 179 scale: 1.0, orientation: UIImageOrientation.right) 180 181 182 return resultImage 183 } 184 185 186 override func didReceiveMemoryWarning() { 187 super.didReceiveMemoryWarning() 188 // Dispose of any resources that can be recreated. 189 } 190} 191

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

やりたいことと異なっていたらすいません。

カメラはデフォルトの向きが横長(Landscape)なので、縦方向で撮影したい場合は画面を回転させる必要があります。

下記の部分のコメントアウトを外して向きを設定すると縦(Portrait)になります。

let connection = output.connection(with: AVMediaType.video) connection?.videoOrientation = .portrait

参考記事:(コード自体はちょっと古いですが、内容は参考になると思います)
https://qiita.com/shu223/items/057351d41229861251af

投稿2018/04/22 21:50

newmt

総合スコア1277

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

TakumiOchiai

2018/04/22 23:16

こちらで、解決しました!!! ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問