首页 > 解决方案 > CIImage 像素的 RGB 值

问题描述

CVPixelBuffer我想ARFrame实时访问特定区域的平均颜色值。我设法裁剪图像,使用过滤器计算平均颜色,并在转换为CGImage从像素中获取值后,但不幸的是,它影响了我的应用程序的性能(FPS 降至 30fps 以下)。我认为原因是使用 CGContext。CIImage有没有办法在不转换为的情况下访问颜色CGImage?这是我目前正在使用的代码:

func fun() {
  let croppVector = CIVector(cgRect: inputImageRect)

  guard let filter = CIFilter(
    name: "CIAreaAverage",
    parameters: [kCIInputImageKey: image, kCIInputExtentKey: croppVector]
  ),
    let outputImage = filter.outputImage,
    let cgImage = context.createCGImage(
      outputImage,
      from: CGRect(x: 0, y: 0, width: 1, height: 1)
    ),
    let dataProvider = cgImage.dataProvider,
    let data = CFDataGetBytePtr(dataProvider.data) else { return nil }

  let color = UIColor(
    red: CGFloat(data[0]) / 255,
    green: CGFloat(data[1]) / 255,
    blue: CGFloat(data[2]) / 255,
    alpha: CGFloat(data[3]) / 255
  )
}

标签: swiftarkitcore-imageciimagecvpixelbuffer

解决方案


我认为你可以在这里做的事情并不多——像这样的归约操作很昂贵。

您可以尝试几件事:

  • 通过将和选项设置为CIContext来设置您执行任何颜色管理。.workingColorSpace.outputColorSpaceNSNull()
  • 直接渲染到一块内存中,而不是通过CGImage. 上下文具有render(_ image: CIImage, toBitmap data: UnsafeMutableRawPointer, rowBytes: Int, bounds: CGRect, format: CIFormat, colorSpace: CGColorSpace?)您可以使用的方法。nil也在这里作为色彩空间传递。您应该能够simd_uchar4像这里一样将“指针”传递给 var data。我认为是 4,在这种情况下rowBytes格式是。.BGRA8
  • 在进行平均计算之前,您还可以尝试缩小图像(这已经是缩小操作)。它不会是相同的值,而是一个公平的近似值——它可能会更快。

推荐阅读