【问题标题】:Fast UInt to Float conversion in Swift在 Swift 中快速 UInt 到 Float 转换
【发布时间】:2021-01-24 08:26:06
【问题描述】:

我正在对实时视频流进行一些实时图像分析。我正在使用 vImage 来计算直方图和 vDSP 以进行进一步处理。我有多年来一直运行良好的 Objective-C 代码。我现在要把它转换成 Swift。虽然它有效,但它太慢了。我发现主要问题是将 vImage 直方图(即 UInt (vImagePixelCount))转换为 vDSP 可以处理的浮点数。在 Objective-C 中,我使用 vDSP 进行转换:

  err = vImageHistogramCalculation_Planar8(&vBuffY,histogramY, 0);
  vDSP_vfltu32((const unsigned int*)histogramY,2,histFloatY,1,256);

但是,vImage 直方图是 UInt,而不是 UInt32,所以我不能在 Swift 中使用 vDSP_vfltu32。相反,我正在使用

  let err = vImageHistogramCalculation_Planar8(&vBuffY, &histogramY, 0)
  let histFloatY = histogramY.compactMap{ Float($0) }

问题是这段代码比 Objective-C 版本慢了 100 多倍。有没有更快的替代方案?

【问题讨论】:

  • 你为什么不使用 swift 版本? developer.apple.com/documentation/accelerate/…
  • 试试vDSP_vfltu32(histogramY, 2, &histFloatY, 1, 256),其中histFloatYvar
  • 正如问题中提到的,vDSP_vfltu32 是否需要 UInt32 而不是 UInt。首先转换为 UInt32 也同样慢。

标签: ios swift histogram vdsp vimage


【解决方案1】:

vImageHistogramCalculation_Planar8() 将直方图写入一个包含 256 个 vImagePixelCount 类型元素的缓冲区,这是 C 中 unsigned long 的类型别名,在 64 位平台上是一个 64 位整数。

您的 Objective-C 代码“作弊”,方法是在对 vDSP_vfltu32 () 的调用中将 unsigned long 指针转换为 unsigned int 指针,并将步幅设置为 2。所以这里发生的是每个unsigned long 的低32 位被转换为float。只要计数不超过值 232-1,它就可以工作。

你可以在 Swift 中做同样的事情,只是这里的类型转换是通过“重新绑定”内存来完成的:

let err = vImageHistogramCalculation_Planar8(&vBuffY, &histogramY, 0)
histogramY.withUnsafeBytes {
    let uint32ptr = $0.bindMemory(to: UInt32.self)
    vDSP_vfltu32(uint32ptr.baseAddress!, 2, &histFloatY, 1, 256);
}

【讨论】:

  • 谢谢,这可能是朝着正确方向迈出的一步。但是“withMemoryRebound”仅在参数具有相同内存大小的情况下才有效(文档中有注释)。因此代码在 64 位设备上因“致命错误”而崩溃。
  • @Sten:你说得对(这个约束是新的,或者在以前的 Swift 版本中没有强制执行,所以我错过了)。我已更新代码以使用 bindMemory,请再次检查。
  • 谢谢!它工作正常,性能与 Objective-c 代码相同。它与原始代码具有相同的 2^32 限制,但在我的情况下这绝对没有问题。
猜你喜欢
  • 2014-11-23
  • 2020-01-25
  • 2016-09-01
  • 2014-07-31
  • 2015-08-03
  • 2015-01-23
  • 1970-01-01
相关资源
最近更新 更多