图像分层需要Visioni和CoreML框架

CoreML作用是把图像识别模型代码化,Vision根据CoreML模型去识别图像。 本文主要是将图像进行简单的分层,所以需要DeeplabV3这个模型,这里还有一些其它的模型,也同样可以使用本文demo用法去使用,并识别不同的图片。

Vision和CoreML的使用方法

1. 直接将DeeplabV3拖进工程,并在代码中初始化模型,并在后面提供给Vision框架使用,这里CoreML框架会直接把模型处理为类对象
lazy var model = try! DeepLabV3(configuration: {
        let config = MLModelConfiguration()
        config.allowLowPrecisionAccumulationOnGPU = true
        config.computeUnits = .cpuAndNeuralEngine
        return config
    }())
2.创建Vision的request,用来设置模型和执行的回调
lazy var request = VNCoreMLRequest(model: try! VNCoreMLModel(for: model.model)) ( block ...)

这里回调会返回一个多个识别到的相对图层(一般简单的图片只会返回一个),每个相对图层会有两个图层,一个前景每一个背景,前景就是我们一般情况下需要识别的图像主体。

3.图像分层处理
case 0:
    bitmapData[j * stride * components + i * components + 0] = 0x0
    bitmapData[j * stride * components + i * components + 1] = 0x0
    bitmapData[j * stride * components + i * components + 2] = 0x0
    bitmapData[j * stride * components + i * components + 3] = 0x0
default:
    bitmapData[j * stride * components + i * components + 0] = 0x0
    bitmapData[j * stride * components + i * components + 1] = 0x0
    bitmapData[j * stride * components + i * components + 2] = 0x0
    bitmapData[j * stride * components + i * components + 3] = 0xff

原理是使用Vision去识别不同层级的轮廓数据,然后将我们想要保留的前景图层数据处理为不透明颜色,背景景数据处理为透明颜色,然后用处理后的数据去生成一个遮罩图像,作为遮罩去遮在原图上,然后就可以生成一张已识别的前景图片

let bitmapImage1 = CGImage(width: width,
                                          height: height,
                                          bitsPerComponent: 8,
                                          bitsPerPixel: 8 * components,
                                          bytesPerRow: width * components,
                                          space: CGColorSpaceCreateDeviceRGB(),
                                          bitmapInfo: .init(rawValue: CGImageAlphaInfo.last.rawValue),
                                          provider: .init(data: bitmapData1 as CFData)!,
                                          decode: nil,
                                          shouldInterpolate: false,
                                          intent: .defaultIntent)
                let image1 = UIImage(cgImage: bitmapImage1!).resize(to: self.imageSize)
                DispatchQueue.main.async {
                    self.maskImage = image1
                }

demo 地址 TestVisionML