CVPixelBuffer使用UIImage.draw()编写是太慢了

时间:2017-09-28 01:48:37

标签: ios swift uiimage coreml

我是一名本科生,我现在正在使用CoreML框架在iPhone上制作一些视频HumanSeg应用程序,但正如标题所示,我有一个huuuuuge问题。

我有一个UIImage,我必须调整大小并填充它,并将其绘制到CVPixelBuffer中以提供MobileNet模型,但这样的过程只是太慢,耗时约30ms,这是不可接受的。

具体来说,在我的代码中,方法UIImage.draw(in:CGRect(x:Int,y:Int,width:Int,height:Int))太慢了,花了我2​​0多毫秒,这是主要问题。

我的代码如下:

func dealRawImage(image : UIImage, dstshape : [Int], pad : UIImage) -> CVPixelBuffer?
{
    // decide whether to shrink in height or width
    let height = image.size.height
    let width = image.size.width
    let ratio = width / height
    let dst_width = Int(min(CGFloat(dstshape[1]) * ratio, CGFloat(dstshape[0])))
    let dst_height = Int(min(CGFloat(dstshape[0]) / ratio, CGFloat(dstshape[1])))
    let origin = [Int((dstshape[0] - dst_height) / 2), Int((dstshape[1] - dst_width) / 2)]

    // init a pixelBuffer to store the resized & padded image
    var pixelBuffer: CVPixelBuffer?
    let attrs = [kCVPixelBufferCGImageCompatibilityKey: kCFBooleanTrue,
                 kCVPixelBufferCGBitmapContextCompatibilityKey: kCFBooleanTrue]
    CVPixelBufferCreate(kCFAllocatorDefault,
                        dstshape[1],
                        dstshape[0],
                        kCVPixelFormatType_32ARGB,
                        attrs as CFDictionary,
                        &pixelBuffer)

    // get the pointer of this pixelBuffer
    CVPixelBufferLockBaseAddress(pixelBuffer!, CVPixelBufferLockFlags(rawValue: 0))
    let pixelData = CVPixelBufferGetBaseAddress(pixelBuffer!)

    // init a context that contains this pixelBuffer to draw in
    let context = CGContext(data: pixelData,
                            width: dstshape[1],
                            height: dstshape[0],
                            bitsPerComponent: 8,
                            bytesPerRow: CVPixelBufferGetBytesPerRow(pixelBuffer!),
                            space: CGColorSpaceCreateDeviceRGB(),
                            bitmapInfo: CGImageAlphaInfo.noneSkipFirst.rawValue)!

    // push context
    UIGraphicsPushContext(context)
    context.translateBy(x: 0, y: CGFloat(dstshape[0]))
    context.scaleBy(x: 1, y: -1)

    pad.draw(in:CGRect(x: 0, y: 0, width: dstshape[1], height: dstshape[0]))
    // THIS SINGLE FUNCTION COSTS ME 20+ ms AND IS THE MAJOR ISSUE !
    image.draw(in: CGRect(x: origin[1], y: origin[0], width: dst_width, height: dst_height))

    UIGraphicsPopContext()

    // unlock
    CVPixelBufferUnlockBaseAddress(pixelBuffer!, CVPixelBufferLockFlags(rawValue: 0))

    return pixelBuffer
}

我只是这样称呼这个函数:

let input = dealRawImage(image: raw_input_image, dstshape: [224, 224], pad: black_image)

其中raw_input_image是我从内存中读取的UIImage,dstshape是我想要调整此图像大小的形状,而black_image是一个用于填充的全黑UIImage。

我在这个网站上搜索过但没有找到熟悉的问题。

有什么方法可以让这个过程更快并保存这个项目?我只是不想放弃我的2周工作。

1 个答案:

答案 0 :(得分:1)

自从我处理CVPixelBuffer以来已经有一段时间了,我还没有使用CoreML

当我 使用CVPixelBuffer时,我发现通过在目标大小上创建一个像素缓冲区并保持它,我获得了最佳性能。我从相机中取出像素,将它们作为纹理传递给OpenGL,操纵它们,并将输出映射到相同的CVPixelBuffer。我能够为所有这些使用相同的内存结构。我建议采用这种方法。