如何将几个CGImage合并成一个更大的CGImage?
How to merge several CGImage into a bigger CGImage?
我创建了一个应用程序,它将神经网络 (convnet) 应用于输入图像,然后进行 post 处理。这个 convnet 基本上是一个过滤器,它输入一个图像(加上一个参数)并输出一个相似大小的图像。由于内存问题,convnet 无法一次处理大图像,因此必须将图像分成小块,然后在应用模型后将它们粘在一起(或统一)在一起。我的问题是关于图像处理。具体做了什么,我给大家介绍一下就更清楚了:
- 输入图像是 UIImage
- 将输入图像拆分为名为
listInput
的 UIImage 列表
- 创建一个空的
listOutput
- 对于
listInput
中的每个图块:
- 将 UIImage 转换为 CGImage
- 将 CGImage 转换为 CVPixelBuffer
- 将 CoreML 模型应用于 CVPixelBuffer,returns 相同大小的 CVPixelBuffer
- 将 CVPixelBuffer 转换为 CIImage
- 将 CIImage 转换为 CGImage
- 将 CGImage 转换为 UIImage
- 将 UIImage 附加到
listOutput
- 将
listOutput
中的所有图块统一为一个输出UIImage
- 融合输入输出UIImage(post-处理):
- 将输入的 UIImage 转换为 CGImage,然后再转换为 CIImage
- 将输出的 UIImage 转换为 CGImage,然后再转换为 CIImage
- 使用 CIFilter 融合 2 个 CIImage
- 将生成的 CIImage 转换为 CGImage
- 将 CGImage 转换为 UIImage
如果需要,我可以post上面列出的任何部分对应的代码。
我遇到的一般问题是 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 来做同样的事情?
- 这是个好主意吗?
一些注意事项:
post-processing 必须与前面的部分分开,因为用户想要修改post-processing 参数而不重新应用convnet。 convnet 的应用程序确实很长,在 post 处理接近实时的情况下,可能需要一分钟来计算大图像。
在post-processing部分,有人建议我直接转换UIImage <-> CIImage而不通过CGImage。由于某种我不知道的原因,据我所知这不起作用。
我知道使用 Vision 我可以将 CGImage 直接输入网络而不是 CVPixelBuffer,但我不知道 Vision 是否也可以输出 CGImage。希望很快会对此进行调查。
感谢您提供的任何信息。
UIImage 转 CIImage
这一步:
UIImage into CGImage then to CIImage
被夸大了,因为 CIImage 有一个 init(image:)
直接从 UIImage 到 CIImage 的初始化器。
裁剪
您似乎认为裁剪 CGImage 比裁剪 UIImage 更容易,但事实并非如此。要裁剪 UIImage,只需将其绘制到较小的图形上下文中,偏移以便将所需的点放在裁剪的左上角。
图形上下文
您只能在图形上下文中绘图,无论您喜欢与否,它都将是图像上下文。如果您是这么想的,那么就没有绘制成 "CGImage context" 这样的东西。您可以将 CGImage 直接绘制到图像上下文中,但结果通常是灾难性的(我将在下一段中解释)。
最后的想法
总的来说,我想让您放心使用 UIImage。 UIImage 是 good 东西。它(通常)是一个非常轻量级的 CGImage 包装器。 CGImage是位图数据;包装器添加了比例和方向等信息。丢失该信息可能会导致您的绘图非常糟糕;尝试绘制 CGImage 可能会导致绘图翻转和错误缩放。不要这样做!使用 UIImage 并快乐。
我创建了一个应用程序,它将神经网络 (convnet) 应用于输入图像,然后进行 post 处理。这个 convnet 基本上是一个过滤器,它输入一个图像(加上一个参数)并输出一个相似大小的图像。由于内存问题,convnet 无法一次处理大图像,因此必须将图像分成小块,然后在应用模型后将它们粘在一起(或统一)在一起。我的问题是关于图像处理。具体做了什么,我给大家介绍一下就更清楚了:
- 输入图像是 UIImage
- 将输入图像拆分为名为
listInput
的 UIImage 列表
- 创建一个空的
listOutput
- 对于
listInput
中的每个图块:- 将 UIImage 转换为 CGImage
- 将 CGImage 转换为 CVPixelBuffer
- 将 CoreML 模型应用于 CVPixelBuffer,returns 相同大小的 CVPixelBuffer
- 将 CVPixelBuffer 转换为 CIImage
- 将 CIImage 转换为 CGImage
- 将 CGImage 转换为 UIImage
- 将 UIImage 附加到
listOutput
- 将
listOutput
中的所有图块统一为一个输出UIImage - 融合输入输出UIImage(post-处理):
- 将输入的 UIImage 转换为 CGImage,然后再转换为 CIImage
- 将输出的 UIImage 转换为 CGImage,然后再转换为 CIImage
- 使用 CIFilter 融合 2 个 CIImage
- 将生成的 CIImage 转换为 CGImage
- 将 CGImage 转换为 UIImage
如果需要,我可以post上面列出的任何部分对应的代码。
我遇到的一般问题是 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 来做同样的事情?
- 这是个好主意吗?
一些注意事项:
post-processing 必须与前面的部分分开,因为用户想要修改post-processing 参数而不重新应用convnet。 convnet 的应用程序确实很长,在 post 处理接近实时的情况下,可能需要一分钟来计算大图像。
在post-processing部分,有人建议我直接转换UIImage <-> CIImage而不通过CGImage。由于某种我不知道的原因,据我所知这不起作用。
我知道使用 Vision 我可以将 CGImage 直接输入网络而不是 CVPixelBuffer,但我不知道 Vision 是否也可以输出 CGImage。希望很快会对此进行调查。
感谢您提供的任何信息。
UIImage 转 CIImage
这一步:
UIImage into CGImage then to CIImage
被夸大了,因为 CIImage 有一个 init(image:)
直接从 UIImage 到 CIImage 的初始化器。
裁剪
您似乎认为裁剪 CGImage 比裁剪 UIImage 更容易,但事实并非如此。要裁剪 UIImage,只需将其绘制到较小的图形上下文中,偏移以便将所需的点放在裁剪的左上角。
图形上下文
您只能在图形上下文中绘图,无论您喜欢与否,它都将是图像上下文。如果您是这么想的,那么就没有绘制成 "CGImage context" 这样的东西。您可以将 CGImage 直接绘制到图像上下文中,但结果通常是灾难性的(我将在下一段中解释)。
最后的想法
总的来说,我想让您放心使用 UIImage。 UIImage 是 good 东西。它(通常)是一个非常轻量级的 CGImage 包装器。 CGImage是位图数据;包装器添加了比例和方向等信息。丢失该信息可能会导致您的绘图非常糟糕;尝试绘制 CGImage 可能会导致绘图翻转和错误缩放。不要这样做!使用 UIImage 并快乐。