简体   繁体   English

如何将多个 CGImage 合并成一个更大的 CGImage?

[英]How to merge several CGImage into a bigger CGImage?

I have created an app that applies a neural network (convnet) to an input image followed by a post-processing.我创建了一个应用程序,将神经网络 (convnet) 应用于输入图像,然后进行后处理。 This convnet is basically a filter that inputs an image (plus one parameter) and outputs an image of similar size.这个 convnet 基本上是一个过滤器,它输入一张图像(加上一个参数)并输出一张相似大小的图像。 Since the convnet cannot process a large image in one pass due to memory issue, the image must be split in tiles which are then sticked (or unified) together after the model is applied.由于由于内存问题,convnet 无法一次性处理大图像,因此必须将图像拆分为切片,然后在应用模型后将其粘贴(或统一)在一起。 My problem is about image manipulation.我的问题是关于图像处理。 It will be more clear after I present you what is done in details:具体做了哪些事情,等我给大家介绍一下就更清楚了:

  • Input image is a UIImage输入图像是一个 UIImage
  • Split the input image into as a list of UIImage called listInput将输入图像拆分为一个名为listInput的 UIImage 列表
  • Create an empty listOutput创建一个空listOutput
  • For each tile in listInput :对于listInput每个图块:
    • Convert the UIImage into a CGImage将 UIImage 转换为 CGImage
    • Convert the CGImage into a CVPixelBuffer将 CGImage 转换为 CVPixelBuffer
    • Apply a CoreML model to the CVPixelBuffer which returns a CVPixelBuffer of the same size将 CoreML 模型应用于返回相同大小的 CVPixelBuffer 的 CVPixelBuffer
    • Convert the CVPixelBuffer into a CIImage将 CVPixelBuffer 转换为 CIImage
    • Convert the CIImage into a CGImage将 CIImage 转换为 CGImage
    • Convert the CGImage into a UIImage将 CGImage 转换为 UIImage
    • Append the UIImage into listOutput将 UIImage 附加到listOutput
  • Unify all the tiles in listOutput into an output UIImagelistOutput所有图块统一为一个输出 UIImage
  • Fuse input and output UIImage (post-processing):融合输入输出 UIImage(后处理):
    • Convert input UIImage into CGImage then to CIImage将输入的 UIImage 转换为 CGImage 再转换为 CIImage
    • Convert output UIImage into CGImage then to CIImage将输出 UIImage 转换为 CGImage 再转换为 CIImage
    • Fuse the 2 CIImage using a CIFilter使用 CIFilter 融合 2 CIImage
    • Convert the resulting CIImage into a CGImage将生成的 CIImage 转换为 CGImage
    • Convert the CGImage into a UIImage将 CGImage 转换为 UIImage

I can post the code corresponding to any of the part listed above if needed.如果需要,我可以发布与上面列出的任何部分相对应的代码。

The general problem I have is all the conversions between UIImage to CGImage to CIImage and conversly.我遇到的一般问题是 UIImage 到 CGImage 到 CIImage 和 conversly 之间的所有转换。 I'm trying to get rid of UIImage completely (except for loading the image).我试图完全摆脱 UIImage (加载图像除外)。 I want indeed to manipulate CGImage from the start until the end.我确实想从头到尾操纵 CGImage。 This will already simplify the code.这已经简化了代码。

I've modified my code to manipulate list of CGImage instead of list of UIImage.我修改了我的代码来操作 CGImage 列表而不是 UIImage 列表。 The cropping part is in fact simpler with CGImage than with UIImage. CGImage 的裁剪部分实际上比 UIImage 更简单。 But I cannot figure out the other way around: unify CGImage together into a bigger image.但我无法想出相反的方法:将 CGImage 统一成一个更大的图像。 This is my specific problem.这是我的具体问题。 Bellow is the function I've created to unify the UIImage. 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
}

So my question is:所以我的问题是:

  • Is it possible to do the same just manipulating CGImage?是否可以仅操作 CGImage 来做同样的事情?
  • Is it even a good idea?这甚至是个好主意吗?

Some notes:一些注意事项:

  • The post-procesing must be separated from the previous part because the user wants to modify the post-processing parameters without reapplying the convnet.后处理必须和前一部分分开,因为用户想修改后处理参数而不需要重新应用convnet。 The application of the convnet is indeed very long and can take up to a minute to compute on large images while the post-processing is near real-time. convnet 的应用确实很长,在大图像上计算可能需要长达一分钟的时间,而后处理几乎是实时的。

  • In the post-processing part, it was suggested to me to convert directly UIImage <-> CIImage without going through CGImage.后处理部分,建议我直接转换UIImage<->CIImage,不经过CGImage。 For some reason that I don't know, this doesn't work as far as I remember.出于某种我不知道的原因,据我所知,这不起作用。

  • I'm aware that using Vision I could feed directly a CGImage into the network instead of a CVPixelBuffer, but I don't know if Vision can output a CGImage as well.我知道使用 Vision 我可以直接将 CGImage 输入网络而不是 CVPixelBuffer,但我不知道 Vision 是否也可以输出 CGImage。 This will be investigated soon hopefully.这将有望很快得到调查。

Thanks for any information you could give me.感谢您提供给我的任何信息。

UIImage to CIImage UIImage 到 CIImage

This step:这一步:

UIImage into CGImage then to CIImage UIImage 到 CGImage 然后到 CIImage

is overblown, as CIImage has an init(image:) initializer that goes directly from UIImage to CIImage.被夸大了,因为 CIImage 有一个init(image:)初始化程序,它直接从 UIImage 转到 CIImage。

Cropping裁剪

You seem to think that cropping a CGImage is easier than cropping a UIImage, but it isn't.您似乎认为裁剪 CGImage 比裁剪 UIImage 更容易,但事实并非如此。 To crop a UIImage, just draw it into a smaller graphics context, offset so as to place the desired point at the top left of the crop.要裁剪 UIImage,只需将其绘制到较小的图形上下文中,偏移以便将所需的点放置在裁剪的左上角。

Graphics Contexts图形上下文

You can only draw in a graphics context, and that's going to be an image context whether you like it or not.您只能在图形上下文中绘制,无论您喜欢与否,这都将是图像上下文。 There's no such thing as drawing into a "CGImage context" if that's what you're thinking.如果那是您的想法,那么就没有绘制到“CGImage 上下文”之类的东西。 You can draw a CGImage directly into an image context, but the results are usually disastrous (as I shall explain in the next paragraph).您可以将 CGImage 直接绘制到图像上下文中,但结果通常是灾难性的(我将在下一段中解释)。

Final thoughts最后的想法

In general I would like to set your mind at rest about UIImage.总的来说,我想让你对 UIImage 放心。 A UIImage is a good thing.一个UIImage是一件好事 It is (usually) a very lightweight wrapper around a CGImage.它(通常)是围绕 CGImage 的一个非常轻量级的包装器。 The CGImage is the bitmap data; CGImage 是位图数据; the wrapper adds information like scale and orientation.包装器添加了比例和方向等信息。 Losing that information can cause your drawing to come out very badly;丢失这些信息可能会导致您的绘图非常糟糕; trying to draw a CGImage can cause the drawing to be flipped and incorrectly scaled.尝试绘制 CGImage 可能会导致绘图被翻转和错误缩放。 Don't do it!不要这样做! Use UIImage and be happy.使用 UIImage 并快乐。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM