在 Swift 中以浮点精度从 CMSampleBuffer 获取“CIAreaAverage”的 RGB 平均值
Posted
技术标签:
【中文标题】在 Swift 中以浮点精度从 CMSampleBuffer 获取“CIAreaAverage”的 RGB 平均值【英文标题】:Get RGB average of "CIAreaAverage" from CMSampleBuffer in Float precision in Swift 【发布时间】:2022-01-15 13:58:33 【问题描述】:我正在尝试获取“AVCaptureVideoDataOutput”提要的平均 RGB 值。我在 *** 上找到了以下解决方案:
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 平均值?
非常感谢!
【问题讨论】:
因为像素是 8 位,所以最大值是 255。假设浮点值是从 0.0 到 1.0,计算应该是 CGFloat(pixel) / 255.0 是的,问题在于它将平均值输出为 8 位整数,因此它将浮点数舍入为整数...我想要 0-255 范围内的浮点平均值,无需转换到 8 位像素值 你指的是什么像素值转换?像素由 8 位值表示。相当标准的东西。 好吧,我希望在将其转换为 8 位整数之前获得平均像素值 - 所以它不会四舍五入,因为我需要在浮点精度级别上进行那些微小的更改。 【参考方案1】:我可以推荐使用我们的库CoreImageExtensions
来读取值吗?我们添加了从CIImage
s 以不同格式读取像素值的方法。对于您的情况,它看起来像这样:
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
实例并将其用于每个相机帧。创建它的成本很高,而且它实际上会提高使用相同实例的性能,因为它会缓存内部资源。
【讨论】:
这太棒了!谢谢你分享这个。只是一个简单的问题,浮动值在 0-1 范围内。这些是根据浮点数中的实际像素平均值计算得出的,还是只是将每个颜色通道的 8 位输出除以 255?我进行了一些实验,似乎是前者,但想仔细检查! Core Image 实际上以默认为 16 位浮点的工作格式运行(不过,您可以在创建上下文时将其设置为选项)。因此,当加载图像时,它会在应用任何过滤器之前转换为工作格式。然后将 8 位 uchar 值 [0...255] 转换为 [0.0...1.0]。然后根据浮点值计算平均值(因此也更精确)。 知道了!非常感谢!以上是关于在 Swift 中以浮点精度从 CMSampleBuffer 获取“CIAreaAverage”的 RGB 平均值的主要内容,如果未能解决你的问题,请参考以下文章
NSDecimalNumber 用于 Swift 中的货币精度 [重复]
如何在 PySpark 1.6 中将 DataFrame 列从字符串转换为浮点/双精度?