Как интерпретировать массив пикселей, полученный из CMSampleBuffer в Swift - PullRequest
1 голос
/ 03 апреля 2020

Может быть, это очень глупый вопрос. Я использую AVFoundation в своем приложении, и я могу получить кадры (формат 32BGRA). Ширина кадра равна 1504, высота равна 1128, а значение bytes-Per-Row равно 6016. Когда я создаю пиксельный массив UInt8 из этого выборочного буфера, длина (array.count) этого массива равна 1696512, что равно ширина высота.

Я не понимаю, почему длина массива равна ширине * высоте. Разве это не ширина * высота * 4.

Что мне здесь не хватает?

Правка - 1: Код

func BufferToArray(sampleBuffer: CMSampleBuffer) -> ([UInt8], Int, Int, Int) {

    var rgbBufferArray = [UInt8]()

    //Get pixel Buffer from CMSSampleBUffer
    let pixelBuffer: CVPixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer)!

    //Lock the base Address
    CVPixelBufferLockBaseAddress(pixelBuffer, CVPixelBufferLockFlags.readOnly)

    let width = CVPixelBufferGetWidth(pixelBuffer)
    let height = CVPixelBufferGetHeight(pixelBuffer)
    //get pixel count
    let pixelCount = CVPixelBufferGetWidth(pixelBuffer) * CVPixelBufferGetHeight(pixelBuffer)

    //Get base address
    let baseAddress = CVPixelBufferGetBaseAddress(pixelBuffer)

    //Get bytes per row of the image
    let bytesPerRow = CVPixelBufferGetBytesPerRow(pixelBuffer)

    //Cast the base address to UInt8. This is like an array now
    let frameBuffer = baseAddress?.assumingMemoryBound(to: UInt8.self)


    rgbBufferArray = Array(UnsafeMutableBufferPointer(start: frameBuffer, count: pixelCount))


    //Unlock and release memory
    CVPixelBufferUnlockBaseAddress(pixelBuffer, CVPixelBufferLockFlags(rawValue: 0))

return (rgbBufferArray, bytesPerRow, width, height)

}

1 Ответ

1 голос
/ 03 апреля 2020

Преступником является тип данных (UInt8) в сочетании с count:

Вы предполагаете, что память содержит UInt8 значений (assumingMemoryBound(to: UInt8.self)) из числа pixelCount. Но, как вы правильно сделали, это число должно быть в четыре раза больше.

Я бы порекомендовал вам import simd и использовать simd_uchar4 в качестве типа данных. Это тип структуры, содержащий 4 UInt8. Тогда ваш массив будет содержать pixelCount значений 4-х значных пикселей. Вы можете получить доступ к каналам с помощью array[index].x, .y, .z и .w соответственно.

...