【发布时间】:2020-07-03 22:26:05
【问题描述】:
我创建了一个应用程序,它将神经网络 (convnet) 应用于输入图像,然后进行后处理。这个卷积网络基本上是一个输入图像(加一个参数)并输出相似大小图像的过滤器。由于内存问题,卷积网络无法一次性处理大图像,因此必须将图像分割成小块,然后在应用模型后将这些小块粘贴(或统一)在一起。我的问题是关于图像处理。详细介绍完之后你会更清楚:
- 输入图像是 UIImage
- 将输入图像拆分为 UIImage 列表,称为
listInput - 创建一个空的
listOutput - 对于
listInput中的每个图块:- 将 UIImage 转换为 CGImage
- 将 CGImage 转换为 CVPixelBuffer
- 将 CoreML 模型应用于返回相同大小的 CVPixelBuffer 的 CVPixelBuffer
- 将 CVPixelBuffer 转换为 CIImage
- 将 CIImage 转换为 CGImage
- 将 CGImage 转换为 UIImage
- 将 UIImage 附加到
listOutput
- 将
listOutput中的所有图块统一到一个输出UIImage中 - 融合输入输出UIImage(后处理):
- 将输入的 UIImage 转换为 CGImage,然后转换为 CIImage
- 将输出 UIImage 转换为 CGImage 再转换为 CIImage
- 使用 CIFilter 融合 2 CIImage
- 将生成的 CIImage 转换为 CGImage
- 将 CGImage 转换为 UIImage
如果需要,我可以发布与上面列出的任何部分相对应的代码。
我遇到的一般问题是 UIImage 到 CGImage 到 CIImage 之间的所有转换,反之亦然。我正在尝试完全摆脱 UIImage (加载图像除外)。我确实想从头到尾操纵 CGImage 。这已经可以简化代码了。
我修改了我的代码来操作 CGImage 列表而不是 UIImage 列表。 CGImage 的裁剪部分实际上比 UIImage 更简单。但我无法找出相反的方法:将 CGImage 统一成一个更大的图像。这是我的具体问题。 Bellow 是我为统一 UIImage 而创建的函数。
func unifyTiles(listTiles: [UIImage], listRect: [CGRect]) -> UIImage? {
guard let input = input else {
return nil
}
let outputSize = CGSize(width : Int(input.size.width), height: Int(input.size.height))
UIGraphicsBeginImageContextWithOptions(outputSize, true, 1.0)
for i in 0..<listTiles.count {
listTiles[i].draw(at: listRect[i].origin)
}
guard let output = UIGraphicsGetImageFromCurrentImageContext() else {
return nil
}
UIGraphicsEndImageContext()
return output
}
所以我的问题是:
- 是否可以仅操作 CGImage 来做同样的事情?
- 这是个好主意吗?
一些注意事项:
后处理必须与前一部分分开,因为用户想要修改后处理参数而不重新应用卷积网络。卷积网络的应用确实很长,在大图像上计算可能需要一分钟,而后处理接近实时。
在后处理部分,有人建议我直接转换 UIImage CIImage 而不经过 CGImage。出于某种我不知道的原因,据我所知,这不起作用。
我知道使用 Vision 我可以直接将 CGImage 输入网络而不是 CVPixelBuffer,但我不知道 Vision 是否也可以输出 CGImage。希望很快会对此进行调查。
感谢您提供的任何信息。
【问题讨论】: