如何从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转换为更特定的类型后,即可轻松访问内存:

// 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位unsigned int)。这取决于视频格式。最有可能是8位。

更新缓冲区格式:

您可以在初始化AVCaptureVideoDataOutput实例时指定格式。您基本上可以选择:
  • BGRA:一个平面,其中bluet,green,red和alpha值以32位整数形式存储,每个
  • 420YpCbCr8BiPlanarFullRange:两个平面,第一个平面包含每个具有Y(亮度)值的像素的字节,第二个包含像素组
  • 的Cb和Cr(色度)值
  • 420YpCbCr8BiPlanarVideoRange:与420YpCbCr8BiPlanarFullRange相同,但Y值限制在16 – 235范围内(由于历史原因)

  • 如果您对颜色值和速度(或更确切地说,最大帧速率)不感兴趣,那么请选择更简单的BGRA格式。否则,请选择一种更有效的 native 视频格式。

    如果有两个平面,则必须获取所需平面的基地址(请参见视频格式示例):

    视频格式示例
    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)
    

    关于ios - 在Swift中从CVPixelBufferRef获取像素值,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/34569750/

    10-11 22:32
    查看更多