2016-01-02 11 views
10

Come posso ottenere il valore di pixel RGB (o qualsiasi altro formato) da un CVPixelBufferRef? Ho provato molti approcci ma nessun successo ancora.Ottieni il valore pixel da CVPixelBufferRef in Swift

 func captureOutput(captureOutput: AVCaptureOutput!, didOutputSampleBuffer sampleBuffer: CMSampleBuffer!, fromConnection connection: AVCaptureConnection!) { 

      let pixelBuffer: CVPixelBufferRef = CMSampleBufferGetImageBuffer(sampleBuffer)! 
      CVPixelBufferLockBaseAddress(pixelBuffer, 0) 
      let baseAddress = CVPixelBufferGetBaseAddress(pixelBuffer) 


    //Get individual pixel values here 

    CVPixelBufferUnlockBaseAddress(pixelBuffer, 0) 
     } 
+0

Il buffer dei pixel del core video non contiene le informazioni su un singolo pixel, ma contiene le informazioni sui pixel di tutti i pixel catturati da una scena (una matrice bitmap di pixel). Vuoi dire che vuoi ottenere valori RGB per ogni pixel all'interno del buffer? –

+0

Possibile duplicato di [Come convertire CVPixelBufferGetBaseAddress chiamata a Swift?] (Http://stackoverflow.com/questions/29814143/how-to-convert-cvpixelbuffergetbaseaddress-call-to-swift). –

risposta

12

baseAddress è un puntatore mutevole sicure o più precisamente una UnsafeMutablePointer<Void>. Si può facilmente accedere alla memoria una volta che avete convertito il puntatore lontano da Void a un tipo più specifico:

// Convert the base address to a safe pointer of the appropriate type 
let byteBuffer = UnsafeMutablePointer<UInt8>(baseAddress) 

// read the data (returns value of type UInt8) 
let firstByte = byteBuffer[0] 

// write data 
byteBuffer[3] = 90 

Assicurarsi di utilizzare il tipo corretto (8, 16 o 32 bit unsigned int). Dipende dal formato video. Molto probabilmente è 8 bit.

Aggiornamento sui formati di buffer:

È possibile specificare il formato quando si inizializza l'istanza AVCaptureVideoDataOutput. Hai sostanzialmente la scelta di:

  • BGRA: un singolo piano dove i valori blu, verde, rosso e alfa sono memorizzati in un numero intero di 32 bit ciascuna
  • 420YpCbCr8BiPlanarFullRange: Due aerei, il primo contenente un byte per ogni pixel con il valore Y (luma), il secondo contenente i valori Cb e Cr (chroma) per gruppi di pixel
  • 420YpCbCr8BiPlanarVideoRange: lo stesso di 420YpCbCr8BiPlanarFullRange ma i valori Y sono ristretti all'intervallo 16 - 235 (per motivi storici)

Se ti interessano i valori dei colori e la velocità (o meglio la frequenza massima dei fotogrammi) non è un problema, quindi scegli il più semplice formato BGRA. Altrimenti, prendi uno dei formati video nativi più efficienti.

Se si dispone di due piani, è necessario ottenere l'indirizzo di base del piano desiderato (vedi esempio in formato video):

Formato video esempio

let pixelBuffer: CVPixelBufferRef = CMSampleBufferGetImageBuffer(sampleBuffer)! 
CVPixelBufferLockBaseAddress(pixelBuffer, 0) 
let baseAddress = CVPixelBufferGetBaseAddressOfPlane(pixelBuffer, 0) 
let bytesPerRow = CVPixelBufferGetBytesPerRowOfPlane(pixelBuffer, 0) 
let byteBuffer = UnsafeMutablePointer<UInt8>(baseAddress) 

// Get luma value for pixel (43, 17) 
let luma = byteBuffer[17 * bytesPerRow + 43] 

CVPixelBufferUnlockBaseAddress(pixelBuffer, 0) 

BGRA esempio

let pixelBuffer: CVPixelBufferRef = CMSampleBufferGetImageBuffer(sampleBuffer)! 
CVPixelBufferLockBaseAddress(pixelBuffer, 0) 
let baseAddress = CVPixelBufferGetBaseAddress(pixelBuffer) 
let int32PerRow = CVPixelBufferGetBytesPerRow(pixelBuffer) 
let int32Buffer = UnsafeMutablePointer<UInt32>(baseAddress) 

// Get BGRA value for pixel (43, 17) 
let luma = int32Buffer[17 * int32PerRow + 43] 

CVPixelBufferUnlockBaseAddress(pixelBuffer, 0) 
+0

let luma = int32Buffer [17 * int32Buffer + 43] non viene compilato. "L'operatore binario" * "non può essere applicato agli operandi di tipo" Int "e" UnsafeMutablePointer ". Il problema simile che sto riscontrando si aggiornerà se trovo un modo per convertirlo correttamente – scord

+0

Spiacenti, errore di battitura risolto – Codo

+4

aggiorniamo questo a Swift 3? – scord

6

Aggiornamento per Swift3:

let pixelBuffer: CVPixelBufferRef = CMSampleBufferGetImageBuffer(sampleBuffer)! 
CVPixelBufferLockBaseAddress(pixelBuffer, CVPixelBufferLockFlags(rawValue: 0)); 
let int32Buffer = unsafeBitCast(CVPixelBufferGetBaseAddress(pixelBuffer), to: UnsafeMutablePointer<UInt32>.self) 
let int32PerRow = CVPixelBufferGetBytesPerRow(pixelBuffer) 
// Get BGRA value for pixel (43, 17) 
let luma = int32Buffer[17 * int32PerRow + 43] 

CVPixelBufferUnlockBaseAddress(pixelBuffer, 0) 
+0

Come si ottiene un array di UInt8 da questo, che contiene l'intera immagine?CMSampleBuffer a [UInt8] – omarojo

+0

Come posso ottenere i valori dei pixel se sto utilizzando il formato RAW kCVPixelFormatType_14Bayer_RGGB? –