2016-01-02 3 views
10

Как получить значение пикселя RGB (или любого другого формата) из CVPixelBufferRef? Ive пробовал много подходов, но пока не успел.Получить значение пикселя из CVPixelBufferRef в 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

Основной буфер видеопикселя не содержит информации об одном пикселе, вместо этого он содержит информацию о пикселях всего пикселя, захваченного из сцены (матрица растровых изображений пикселей). Вы хотите иметь значения RGB для каждого пикселя внутри буфера? –

+0

Возможный дубликат [Как преобразовать вызов CVPixelBufferGetBaseAddress в Swift?] (Http://stackoverflow.com/questions/29814143/how-to-convert-cvpixelbuffergetbaseaddress-call-to-swift). –

ответ

12

baseAddress является небезопасным изменчивый указатель или точнее в UnsafeMutablePointer<Void>. Вы можете легко получить доступ к памяти, как только вы преобразовали указатель от Void к более конкретному типу:

// 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 

Убедитесь, что вы используете правильный тип (8, 16 или 32 бит без знака Int). Это зависит от формата видео. Скорее всего, это 8 бит.

Обновление на форматы буфера:

Вы можете указать формат при инициализации экземпляра AVCaptureVideoDataOutput. Вы в основном есть выбор:

  • BGRA: одну плоскость, где значения синий, зеленый, красный и альфа сохраняются в 32 разрядное целое число каждый
  • 420YpCbCr8BiPlanarFullRange: Два самолета, первый содержащий байт для каждый пиксель со значением Y (яркость), второй содержит значения Cb и Cr (цветности) для групп пикселей
  • 420YpCbCr8BiPlanarVideoRange: то же, что и 420YpCbCr8BiPlanarFullRange, но значения Y ограничены диапазоном 16-235 (по историческим причинам)

Если вас интересуют значения цвета и скорость (или, скорее, максимальная частота кадров), не проблема, а затем перейти к более простому формату BGRA. В противном случае возьмите один из более эффективных собственных видеоформатов.

Если у вас есть два самолета, вы должны получить базовый адрес нужной плоскости (см пример формата видео):

Видео Пример формата

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 пример

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] не скомпилируется. «Двоичный оператор« * »не может быть применен к операндам типа« Int »и« UnsafeMutablePointer ». Аналогичная проблема, с которой сталкивается, будет обновляться, если я найду способ ее правильного преобразования. – scord

+0

Извините, Typo. Исправлено. – Codo

+4

Can мы обновляем это до Swift 3? – scord

6

Обновление для 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

Как вы получите массив UInt8 из это, что содержит все изображение?CMSampleBuffer to [UInt8] – omarojo

+0

Как получить значения пикселей, если я использую формат RAW kCVPixelFormatType_14Bayer_RGGB? –

 Смежные вопросы

  • Нет связанных вопросов^_^