在Swift中从CVPixelBufferRef获取像素值

我怎样才能从一个CVPixelBufferRef RGB(或任何其他格式)的像素值? 我尝试了很多方法,但没有成功。

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) } 

baseAddress是一个不安全的可变指针,或者更确切地说是一个UnsafeMutablePointer<Void> 。 将指针从Void转换为更具体的types后,可以轻松访问内存:

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

确保使用正确的types(8,16或32位无符号整数)。 这取决于video格式。 最有可能的是8位。

缓冲区格式更新:

您可以在初始化AVCaptureVideoDataOutput实例时指定格式。 你基本上有以下select:

  • BGRA:蓝色,绿色,红色和alpha值分别以32位整数存储的单一平面
  • 420YpCbCr8BiPlanarFullRange:两个平面,第一个包含Y(亮度)值的每个像素的字节,第二个包含像素组的Cb和Cr(色度)值
  • 420YpCbCr8BiPlanarVideoRange:与420YpCbCr8BiPlanarFullRange相同,但Y值限制在16-235的范围内(由于历史原因)

如果您对颜色值和速度感兴趣(或者说最大帧速率)不是问题,那么可以使用更简单的BGRA格式。 否则,采取更有效的原生video格式之一。

如果您有两架飞机,则必须获得所需飞机的基地址(请参阅video格式示例):

video格式示例

 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) 

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)