ios - 在 Swift 中从 CVPixelBufferRef 获取像素值

标签 ios swift image-processing cvpixelbuffer

如何从 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:一个平面,其中蓝色、绿色、红色和 alpha 值分别存储在一个 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)

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

相关文章:

ios - 仅使顶部 ViewController 旋转

python - 使用 Python 和 OpenCV 实现万花筒效果

c++ - 如何使用 SVM 从视频中检测对象

image-processing - 从直方图中获取黑白强度值

ios - 为什么我的应用程序图标没有显示在我的实际手机上?

ios - 移动 Safari 中的 React PWA 图像上传会破坏应用程序吗?

安卓和 iOS : storage of credit card data

ios - Swift:对 NSNotFound 的模糊引用