3

CMSampleBufferをカメラ出力からvImageに変換して処理しようとしています。残念ながら、でも任意のさらに編集せずに、私はバッファから取得したフレームは、間違った色を持っていますvimageに変換されたCMSampleBufferフレームの色が間違っています

Example image of current implementation

実装(メモリ管理とエラーが問題では考慮されません):

は、ビデオ出力デバイスの設定:

CASampleBufferから vImageを作成する
videoDataOutput = AVCaptureVideoDataOutput() 
    videoDataOutput.videoSettings = [String(kCVPixelBufferPixelFormatTypeKey): kCVPixelFormatType_32BGRA] 
    videoDataOutput.alwaysDiscardsLateVideoFrames = true 
    videoDataOutput.setSampleBufferDelegate(self, queue: captureQueue) 
    videoConnection = videoDataOutput.connection(withMediaType: AVMediaTypeVideo) 

    captureSession.sessionPreset = AVCaptureSessionPreset1280x720 

    let videoDevice = AVCaptureDevice.defaultDevice(withMediaType: AVMediaTypeVideo) 
    guard let videoDeviceInput = try? AVCaptureDeviceInput(device: videoDevice) else { 
     return 
    } 

は、カメラから受信しましたCVPixelBufferはUIImageにエクスポートされるテストのために

とが、ビデオバッファに追加すると、同じ結果を有する:0

// Convert `CASampleBuffer` to `CVImageBuffer` guard let pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer) else { return } var buffer: vImage_Buffer = vImage_Buffer() buffer.data = CVPixelBufferGetBaseAddress(pixelBuffer) buffer.rowBytes = CVPixelBufferGetBytesPerRow(pixelBuffer) buffer.width = vImagePixelCount(CVPixelBufferGetWidth(pixelBuffer)) buffer.height = vImagePixelCount(CVPixelBufferGetHeight(pixelBuffer)) let vformat = vImageCVImageFormat_CreateWithCVPixelBuffer(pixelBuffer) let bitmapInfo:CGBitmapInfo = CGBitmapInfo(rawValue: CGImageAlphaInfo.last.rawValue | CGBitmapInfo.byteOrder32Little.rawValue) var cgFormat = vImage_CGImageFormat(bitsPerComponent: 8, bitsPerPixel: 32, colorSpace: nil, bitmapInfo: bitmapInfo, version: 0, decode: nil, renderingIntent: .defaultIntent) // Create vImage vImageBuffer_InitWithCVPixelBuffer(&buffer, &cgFormat, pixelBuffer, vformat!.takeRetainedValue(), cgColor, vImage_Flags(kvImageNoFlags)) 

UIImageにバッファの変換。

var dstPixelBuffer: CVPixelBuffer? 

    let status = CVPixelBufferCreateWithBytes(nil, Int(buffer.width), Int(buffer.height), 
               kCVPixelFormatType_32BGRA, buffer.data, 
               Int(buffer.rowBytes), releaseCallback, 
               nil, nil, &dstPixelBuffer) 

    let destCGImage = vImageCreateCGImageFromBuffer(&buffer, &cgFormat, nil, nil, numericCast(kvImageNoFlags), nil)?.takeRetainedValue() 

    // create a UIImage 
    let exportedImage = destCGImage.flatMap { UIImage(cgImage: $0, scale: 0.0, orientation: UIImageOrientation.right) } 

    DispatchQueue.main.async { 
     self.previewView.image = exportedImage 
    } 
+0

削除しますか? CGBitmapInfo.byteOrder32Little.rawValue' help?あなたの黄色のアヒルはFFFF00から00FF00になりました。そのため、アルファベットがゼロの場合は、バイトスワップの問題になります。 –

+0

@RhythmicFistmanそれは面白いです。私は 'byteOrder32Little'を削除しようとしましたが、' CGBitmapInfo(rawValue:CGImageByteOrderInfo.orderMask.rawValue | CGImageAlphaInfo.last.rawValue) 'に変更してデフォルトの順序を保ちましたが、結果はまったく同じように見えます。 – Dawid

+0

実行可能なサンプルにリンクできますか? –

答えて

0

vImageBuffer_InitWithCVPixelBufferへの呼び出しは、あなたが

CVPixelBufferLockBaseAddress(pixelBuffer, .readOnly) 
を言うとき、あなたの(リンク)のコードで、あなたがピクセルを変更しないと約束ので少しいたずらであなたの vImage_BufferCVPixelBuffer年代内容を修正する実行していますBGRA8888ため CGBitmapInfoを初期化する

正しい方法は、最初の非自明である32ビット、リトルエンディアン、アルファが、vImage_Utilities.hでvImage_CGImageFormatのヘッダファイルに覆わ:

私は得ることはありませんどのような10
let bitmapInfo = CGBitmapInfo(rawValue: CGImageAlphaInfo.first.rawValue | CGImageByteOrderInfo.order32Little.rawValue) 

バッファを変更するために文書化されているものの、cgFormatdesiredFormat)は、vformatと一致する必要があります、ので、多分あなたが最初にデータをコピーする必要がありますようvImageBuffer_InitWithCVPixelBufferは、あなたのバッファを変更している理由です。最後に

let error = vImageBuffer_InitWithCVPixelBuffer(&buffer, &cgFormat, pixelBuffer, vformat, nil, vImage_Flags(kvImageNoFlags)) 

vformatは今管理リファレンスであるという事実を反映してvImageBuffer_InitWithCVPixelBufferにお電話を

let vformat = vImageCVImageFormat_CreateWithCVPixelBuffer(pixelBuffer).takeRetainedValue() 

    vImageCVImageFormat_SetColorSpace(vformat, 
             CGColorSpaceCreateDeviceRGB()) 

...と更新:

1

あなたのCVの画像フォーマットに色空間を設定してみてください次の行を削除することができます。

//  buffer.data = CVPixelBufferGetBaseAddress(pixelBuffer) 
//  buffer.rowBytes = CVPixelBufferGetBytesPerRow(pixelBuffer) 
//  buffer.width = vImagePixelCount(CVPixelBufferGetWidth(pixelBuffer)) 
//  buffer.height = vImagePixelCount(CVPixelBufferGetHeight(pixelBuffer)) 

コアビデオピクセルバッファをロックする必要はないことに注意してください。ヘッダードックをチェックすると「この関数を呼び出す前にCVPixelBufferをロックする必要はありません」というメッセージが表示されます。

関連する問題