如何解释 Swift 中从 CMSampleBuffer 派生的像素数组
How to interpret the pixel array derived from CMSampleBuffer in Swift
也许这是一个非常愚蠢的问题。
我在我的应用程序中使用 AVFoundation,并且能够获取帧(32BGRA 格式)。
框架的宽度为 1504,高度为 1128,bytes-Per-Row 值为 6016。
当我从这个样本缓冲区创建一个 UInt8 像素数组时,这个数组的长度 (array.count) 是 1696512,恰好等于宽度 * 高度。
我不明白为什么数组长度是宽度 * 高度。不应该是width * height * 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)
}
罪魁祸首是数据类型 (UInt8
) 与 count
:
您假设内存包含 UInt8
个值 (assumingMemoryBound(to: UInt8.self)
),共 pixelCount
个计数。但正如您正确得出的结论,它应该是该数字的四倍。
我建议您 import simd
并使用 simd_uchar4
作为数据类型。那是一个包含 4 UInt8
的结构类型。然后您的数组将包含 pixelCount
个 4 元组像素值的值。您可以分别使用 array[index].x
、.y
、.z
和 .w
访问频道。
也许这是一个非常愚蠢的问题。 我在我的应用程序中使用 AVFoundation,并且能够获取帧(32BGRA 格式)。 框架的宽度为 1504,高度为 1128,bytes-Per-Row 值为 6016。 当我从这个样本缓冲区创建一个 UInt8 像素数组时,这个数组的长度 (array.count) 是 1696512,恰好等于宽度 * 高度。
我不明白为什么数组长度是宽度 * 高度。不应该是width * height * 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)
}
罪魁祸首是数据类型 (UInt8
) 与 count
:
您假设内存包含 UInt8
个值 (assumingMemoryBound(to: UInt8.self)
),共 pixelCount
个计数。但正如您正确得出的结论,它应该是该数字的四倍。
我建议您 import simd
并使用 simd_uchar4
作为数据类型。那是一个包含 4 UInt8
的结构类型。然后您的数组将包含 pixelCount
个 4 元组像素值的值。您可以分别使用 array[index].x
、.y
、.z
和 .w
访问频道。