You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swift使用CoreML结合DeepLabV3移除图片背景部分场景失效咨询

问题描述

我目前使用CoreML搭配DeepLabV3模型实现图片背景移除功能,所用模型来自苹果官方机器学习模型库。
该方案对主体为人、狗、汽车类的照片背景移除效果良好,但在处理天际线、桌面摆放物件等其他场景时,模型无法正确区分检测目标与背景,效果对比如下:

  • 效果正常示例:
    效果正常示例图
  • 效果异常示例:
    效果异常示例图

现有实现代码如下:

var imageSegmentationModel = DeepLabV3()
var request :  VNCoreMLRequest?

func setUpModel() {
        if let visionModel = try? VNCoreMLModel(for: imageSegmentationModel.model) {
                request = VNCoreMLRequest(model: visionModel, completionHandler: visionRequestDidComplete)
                request?.imageCropAndScaleOption = .scaleFill
        }
        else {
                fatalError()
        }
}

func predict() {
        DispatchQueue.global(qos: .userInitiated).async {
            guard let request = self.request else { fatalError() }
            let handler = VNImageRequestHandler(cgImage: (self.originalImage?.cgImage)!, options: [:])
            do {
                try handler.perform([request])
            }catch {
                print(error)
            }
        }
   }

func visionRequestDidComplete(request: VNRequest, error: Error?) {
        DispatchQueue.main.async {
            if let observations = request.results as? [VNCoreMLFeatureValueObservation],
                let segmentationmap = observations.first?.featureValue.multiArrayValue {
                
                self.maskImage = segmentationmap.image(min: 0, max: 255)
                print(self.maskImage!.size)
                
                self.maskImage = self.maskImage?.resizedImage(for: self.originalImage!.size)
                if let image:UIImage = self.maskOriginalImage(){
                    print("Success")
                    self.outputImageView.image = image
                }
            }
        }
            
    }

func maskOriginalImage() -> UIImage? {
        if(self.maskImage != nil && self.originalImage != nil){
            let maskReference = self.maskImage?.cgImage!
            let imageMask = CGImage(maskWidth: maskReference!.width,
                                    height: maskReference!.height,
                                    bitsPerComponent: maskReference!.bitsPerComponent,
                                    bitsPerPixel: maskReference!.bitsPerPixel,
                                    bytesPerRow: maskReference!.bytesPerRow,
                                    provider: maskReference!.dataProvider!, decode: nil, shouldInterpolate: true)
            
            let maskedReference = self.originalImage?.cgImage!.masking(imageMask!)
            return UIImage(cgImage: maskedReference!)
            
        }
        return nil
    }
解答

识别不准的核心原因和你的代码逻辑无关,问题出在模型本身:苹果提供的这个DeepLabV3是在Pascal VOC数据集上训练的,只支持分割20类固定物体,刚好覆盖你测试效果好的人、狗、汽车这类常见目标,完全没收录桌面小摆件、自然天际线地貌这类类别,自然没法正确区分前景和背景。

你可以按优先级尝试以下调整:

零成本先调现有参数

你现在写的request?.imageCropAndScaleOption = .scaleFill会强制拉伸图片适配模型的输入尺寸,导致物体比例变形、小目标边缘错位,直接拉低分割准确率。先把这个参数改成.scaleFit,图片会按原比例缩放后补黑边适配模型,分割完成后再把mask对应原图的有效区域裁出来,就能修复一部分比例变形导致的分割错误,改完先测下目标场景的效果。

替换适配通用场景的模型

如果调完参数效果还是不达标,不用换CoreML+Vision的技术栈,只换模型文件就行:

  • 别再用通用语义分割的DeepLabV3了,优先选专门做抠图的Matting类模型,比如RVM、MODNet、PP-Matting,这类模型不限制前景类别,只要是视觉上的突出主体都能分出精细边缘,对桌面物件、风景场景的适配性比DeepLabV3好很多。这些模型都有现成的CoreML格式开源版本,替换后你现有的请求调度、mask生成、图片合成逻辑基本不用改,只需要根据新模型输出的数组维度、数值范围,调整生成mask时的min、max参数即可。
  • 如果还是想用语义分割方案,可以换在COCO数据集上训练的分割模型,COCO覆盖80+常见物体类别,比Pascal VOC的覆盖范围广很多,对日常小物件的识别率会有明显提升,但泛化能力还是不如专门的抠图模型。

内容的提问来源于stack exchange,提问作者Tom Coomer

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.02 23:21:41