关于UIImage的问题-> CVPixelBuffer-> UIImage转换

问题描述 投票:0回答:1

我正在SwiftUI中研究一个简单的去噪POC,我想在其中进行:

  1. 加载输入图像
  2. 将CoreML模型(去噪)应用于输入图像
  3. 显示输出图像

我根据网上找到的数十种源代码进行工作。根据我所读的内容,CoreML模型(至少是我正在使用的模型)接受CVPixelBuffer并输出CVPixelBuffer。所以我的想法是执行以下操作:

  1. 将输入的UIImage转换为CVPixelBuffer
  2. 将CoreML模型应用于CVPixelBuffer
  3. 将新创建的CVPixelBuffer转换为UIImage

((请注意,我已经阅读了使用Vision框架,可以将CGImage直接输入到模型中。一旦我熟悉我想在这里实现的目标,我就会立即尝试这种方法。这是一个很好的练习。)

首先,我想跳过步骤(2),专注于转换问题。我在下面的代码中尝试实现的是:

  1. 将输入的UIImage转换为CVPixelBuffer
  2. 将CVPixelBuffer转换为UIImage

我不是Swift或Objective-C开发人员,所以我很确定自己至少犯了一些错误。我发现这段代码相当复杂,我想知道是否有更好/更简单的方法来做同样的事情?

func convert(input: UIImage) -> UIImage? {

    // Input CGImage
    guard let cgInput = input.cgImage else {
        return nil
    }

    // Image size
    let width = cgInput.width
    let height = cgInput.height
    let region = CGRect(x: 0, y: 0, width: width, height: height)

    // Attributes needed to create the CVPixelBuffer
    let attributes = [kCVPixelBufferCGImageCompatibilityKey: kCFBooleanTrue,
                      kCVPixelBufferCGBitmapContextCompatibilityKey: kCFBooleanTrue]

    // Create the input CVPixelBuffer
    var pbInput:CVPixelBuffer? = nil
    let status = CVPixelBufferCreate(kCFAllocatorDefault,
                                     width,
                                     height,
                                     kCVPixelFormatType_32ARGB,
                                     attributes as CFDictionary,
                                     &pbInput)

    // Sanity check
    if status != kCVReturnSuccess {
        return nil
    }

    // Fill the input CVPixelBuffer with the content of the input CGImage
    CVPixelBufferLockBaseAddress(pbInput!, CVPixelBufferLockFlags(rawValue: 0))
    guard let context = CGContext(data: CVPixelBufferGetBaseAddress(pbInput!),
                                  width: width,
                                  height: height,
                                  bitsPerComponent: cgInput.bitsPerComponent,
                                  bytesPerRow: cgInput.bytesPerRow,
                                  space: cgInput.colorSpace!,
                                  bitmapInfo: CGImageAlphaInfo.noneSkipFirst.rawValue) else {
                                    return nil
    }
    context.draw(cgInput, in: region)
    CVPixelBufferUnlockBaseAddress(pbInput!, CVPixelBufferLockFlags(rawValue: 0))

    // Create the output CGImage
    let ciOutput = CIImage(cvPixelBuffer: pbInput!)
    let temporaryContext = CIContext(options: nil)
    guard let cgOutput = temporaryContext.createCGImage(ciOutput, from: region) else {
        return nil
    }

    // Create and return the output UIImage
    return UIImage(cgImage: cgOutput)
}

当我在SwiftUI项目中使用此代码时,输​​入和输出图像看起来相同,但不完全相同。我认为输入图像具有与之关联的色图(ColorSync配置文件),在转换期间已丢失。我以为我应该在CGContext创建期间使用cgInput.colorSpace,但似乎使用CGColorSpace(name: CGColorSpace.sRGB)!的效果更好。有人可以向我解释一下吗?

感谢您的帮助。

swift uiimage coreml cvpixelbuffer
1个回答
0
投票
您还可以在Core ML中使用CGImage对象,但是您必须手动创建MLFeatureValue对象,然后将其放入MLFeatureProvider中才能提供给模型。但这仅处理模型输入,而不处理输出。
© www.soinside.com 2019 - 2024. All rights reserved.