从 CMSampleBuffer 获取 "CIAreaAverage" 的 RGB 平均值,精度为 Swift

Get RGB average of "CIAreaAverage" from CMSampleBuffer in Float precision in Swift

我正在尝试获取“AVCaptureVideoDataOutput”提要的平均 RGB 值。我在 Whosebug 上找到了以下解决方案:

let pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer)
let cameraImage = CIImage(CVPixelBuffer: pixelBuffer!)
let filter = CIFilter(name: "CIAreaAverage")
filter!.setValue(cameraImage, forKey: kCIInputImageKey)
let outputImage = filter!.valueForKey(kCIOutputImageKey) as! CIImage!

let ctx = CIContext(options:nil)
let cgImage = ctx.createCGImage(outputImage, fromRect:outputImage.extent)

let rawData:NSData = CGDataProviderCopyData(CGImageGetDataProvider(cgImage))!
let pixels = UnsafePointer<UInt8>(rawData.bytes)
let bytes = UnsafeBufferPointer<UInt8>(start:pixels, count:rawData.length)
var BGRA_index = 0
for pixel in UnsafeBufferPointer(start: bytes.baseAddress, count: bytes.count) {
     switch BGRA_index {
         case 0:
              bluemean = CGFloat (pixel)
         case 1:
              greenmean = CGFloat (pixel)
         case 2:
              redmean = CGFloat (pixel)
         case 3:
              break
         default:
              break
     }
     BGRA_index++
}

但这会生成 Int 形式的平均值,但我需要保持精度的 Float 格式。在我正在处理的问题域中,四舍五入是很有问题的。有没有办法有效地计算浮动平均值?

非常感谢!

我可以推荐使用我们的库 CoreImageExtensions 来读取值吗?我们添加了从 CIImages 以不同格式读取像素值的方法。对于您的情况,它看起来像这样:

 import CoreImageExtensions

 let pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer)
 let cameraImage = CIImage(cvPixelBuffer: pixelBuffer!)
 let filter = CIFilter(name: "CIAreaAverage")!
 filter.setValue(cameraImage, forKey: kCIInputImageKey)
 filter.setValue(CIVector(cgRect: cameraImage.extent), forKey: kCIInputExtentKey)
 let outputImage = filter.outputImage!

 let context = CIContext()
 // get the value of a specific pixel as a `SIMD4<Float32>`
 let average = context.readFloat32PixelValue(from: outputImage, at: CGPoint.zero)

另请记住,如果您想定期计算平均值(而不是一次),只需创建一个 CIContext 实例并将其重复用于每个相机帧。创建它的成本很高,而且它实际上提高了使用同一实例的性能,因为它缓存了内部资源。