Swift 使用加速器规范化视差图像

Swift 使用加速器规范化视差图像,swift,core-image,disparity-mapping,Swift,Core Image,Disparity Mapping,我有一个视差图像,我正在使用下面的示例代码对其进行规范化,但速度非常慢。 我需要使用一些加速器,比如定制的CIFilter或其他技术,但我不知道怎么做?我目前正在用CIContext()运行代码,它正在CPU上运行(不确定)。有没有一种方法可以在GPU上运行它并在没有定制CIfilter的情况下加速? 以下是当前代码: extension CVPixelBuffer { func normalize() { let width = CVPixelBufferGetWidth(se

我有一个视差图像,我正在使用下面的示例代码对其进行规范化,但速度非常慢。 我需要使用一些加速器,比如定制的CIFilter或其他技术,但我不知道怎么做?我目前正在用CIContext()运行代码,它正在CPU上运行(不确定)。有没有一种方法可以在GPU上运行它并在没有定制CIfilter的情况下加速? 以下是当前代码:

extension CVPixelBuffer {

  func normalize() {

    let width = CVPixelBufferGetWidth(self)
    let height = CVPixelBufferGetHeight(self)

    CVPixelBufferLockBaseAddress(self, CVPixelBufferLockFlags(rawValue: 0))

    let baseAddr = CVPixelBufferGetBaseAddress(self)!
    let floatBuffer = unsafeBitCast(CVPixelBufferGetBaseAddress(self), to: UnsafeMutablePointer<Float>.self)

    var minPixel: Float = 1.0
    var maxPixel: Float = 0.0

    for y in 0 ..< height {
      for x in 0 ..< width {
        let pixel = floatBuffer[y * width + x]
        minPixel = min(pixel, minPixel)
        maxPixel = max(pixel, maxPixel)
      }
    }


    let range = maxPixel - minPixel

    for y in 0 ..< height {
      for x in 0 ..< width {
        let pixel = floatBuffer[y * width + x]
        floatBuffer[y * width + x] = (pixel - minPixel) / range
      }
    }

    CVPixelBufferUnlockBaseAddress(self, CVPixelBufferLockFlags(rawValue: 0))
  }
}
扩展CVPixelBuffer{ func正规化(){ let width=CVPixelBufferGetWidth(自) let height=CVPixelBufferGetHeight(自) CVPixelBufferLockBaseAddress(自身,CVPixelBufferLockFlags(原始值:0)) 让baseAddr=CVPixelBufferGetBaseAddress(self)! 让floatBuffer=unsafeBitCast(CVPixelBufferGetBaseAddress(self),to:UnsafeMutablePointer.self) var minPixel:Float=1.0 var maxPixel:Float=0.0 对于y,0..<高度{ 对于0中的x..<宽度{ 设像素=浮动缓冲区[y*宽度+x] 最小像素=最小(像素,最小像素) maxPixel=max(像素,maxPixel) } } 让范围=最大像素-最小像素 对于y,0..<高度{ 对于0中的x..<宽度{ 设像素=浮动缓冲区[y*宽度+x] 浮动缓冲区[y*宽度+x]=(像素-最小像素)/范围 } } CVPixelBufferUnlockBaseAddress(self,CVPixelBufferLockFlags(rawValue:0)) } }
对于您的用例,vImage可能是最好的选择。见附件中的选项3


在核心映像中也有这样做的方法。我可以想象使用
CIAreaMinMax
过滤器获取极值,然后使用一些巧妙的混合进行规范化。如果您愿意,我可以详细说明。

您的像素值为
浮点值,因此您也可以使用vDSP

计算极值,然后:

floatBuffer[y * width + x] = (pixel - minPixel) / range
可以替换为(需要乘以
范围的倒数)

查看此计算中的哪一项可能也很有用:

            m = sum(A[n], 0 <= n < N) / N;
            d = sqrt(sum(A[n]**2, 0 <= n < N) / N - m**2);

            if (C)
            {
                // Normalize.
                for (n = 0; n < N; ++n)
                    C[n] = (A[n] - m) / d;
            }

m=sum(A[n],0我使用加速框架vDSP向量函数来规范化视差。有关工作演示,请参阅gitHub中的修改

下面是两个函数中的相关代码

extension CVPixelBuffer {
    func vectorNormalize( targetVector: UnsafeMutableBufferPointer<Float>) -> [Float] {
        // range = max - min
        // normalized to 0..1 is (pixel - minPixel) / range

        // see Documentation "Using vDSP for Vector-based Arithmetic" in vDSP under system "Accelerate" documentation

        // see also the Accelerate documentation section 'Vector extrema calculation'
        // Maximium static func maximum<U>(U) -> Float
        //      Returns the maximum element of a single-precision vector.

        //static func minimum<U>(U) -> Float
        //      Returns the minimum element of a single-precision vector.


        let maxValue = vDSP.maximum(targetVector)
        let minValue = vDSP.minimum(targetVector)

        let range = maxValue - minValue
        let negMinValue = -minValue

        let subtractVector = vDSP.add(negMinValue, targetVector)
            // adding negative value is subtracting
        let result = vDSP.divide(subtractVector, range)

        return result
    }

    func setUpNormalize() -> CVPixelBuffer {
        // grayscale buffer float32 ie Float
        // return normalized CVPixelBuffer

        CVPixelBufferLockBaseAddress(self,
                                     CVPixelBufferLockFlags(rawValue: 0))
        let width = CVPixelBufferGetWidthOfPlane(self, 0)
        let height = CVPixelBufferGetHeightOfPlane(self, 0)
        let count = width * height

        let bufferBaseAddress = CVPixelBufferGetBaseAddressOfPlane(self, 0)
            // UnsafeMutableRawPointer

        let pixelBufferBase  = unsafeBitCast(bufferBaseAddress, to: UnsafeMutablePointer<Float>.self)

        let depthCopy  =   UnsafeMutablePointer<Float>.allocate(capacity: count)
        depthCopy.initialize(from: pixelBufferBase, count: count)
        let depthCopyBuffer = UnsafeMutableBufferPointer<Float>(start: depthCopy, count: count)

        let normalizedDisparity = vectorNormalize(targetVector: depthCopyBuffer)

        pixelBufferBase.initialize(from: normalizedDisparity, count: count)
            // copy back the normalized map into the CVPixelBuffer

        depthCopy.deallocate()
//        depthCopyBuffer.deallocate()

        CVPixelBufferUnlockBaseAddress(self, CVPixelBufferLockFlags(rawValue: 0))

        return self

    }

}
扩展CVPixelBuffer{ func vectorNormalize(targetVector:UnsafemtableBufferPointer)->[浮点]{ //范围=最大值-最小值 //标准化为0..1是(像素-最小像素)/范围 //请参阅vDSP中系统“加速”文档下的“使用vDSP进行矢量运算”文档 //另请参见加速文档部分“向量极值计算” //最大静态函数最大值(U)->浮点 //返回单个精度向量的最大元素。 //静态函数最小值(U)->浮点 //返回单个精度向量的最小元素。 设maxValue=vDSP.maximum(targetVector) 设minValue=vDSP.minimum(targetVector) 让范围=最大值-最小值 设negMinValue=-minValue 让subtractVector=vDSP.add(negMinValue,targetVector) //加负值等于减 让结果=vDSP.除法(减法向量,范围) 返回结果 } func setUpNormalize()->CVPixelBuffer{ //灰度缓冲浮点32 ie浮点 //返回标准化的CVPixelBuffer CVPixelBufferLockBaseAddress(自, CVPixelBufferLockFlags(原始值:0)) let width=CVPixelBufferGetWidthOfPlane(self,0) let height=CVPixelBufferGetHeightof平面(自,0) 让计数=宽度*高度 让bufferBaseAddress=CVPixelBufferGetBaseAddressOfPlane(self,0) //不可女性化的指针 让pixelBufferBase=unsafeBitCast(bufferBaseAddress,to:UnsafeMutablePointer.self) let depthCopy=UnsafeMutablePointer.allocate(容量:计数) 初始化(起始:pixelBufferBase,计数:计数) 让depthCopyBuffer=UnsafemeutableBufferPointer(开始:depthCopy,计数:计数) 让normalizedDisparity=vectorNormalize(targetVector:depthCopyBuffer) pixelBufferBase.initialize(起始:normalizedDisparity,计数:计数) //将规格化贴图复制回CVPixelBuffer depthCopy.deallocate() //depthCopyBuffer.deallocate() CVPixelBufferUnlockBaseAddress(self,CVPixelBufferLockFlags(rawValue:0)) 回归自我 } }
谢谢您的回答。是的,如果您给出代码示例,这将非常有用。我试图让它与内置CI过滤器一起工作,但目前为止运气不佳。对于您的用例,使用
vImage
vDSP
很可能是更快的选择。谢谢。我会的。我认为这是一个正确的答案,尽管不再需要它了(我用CIContext在真实设备上运行了我的代码,速度足够快)。如果将来需要额外的速度,我会使用你的代码。再次感谢你!