美文网首页
iOS开发之视觉框架中的人员与背景分割

iOS开发之视觉框架中的人员与背景分割

作者: iOS丶lant | 来源:发表于2022-05-24 16:37 被阅读0次

    入门

    在本教程中,您将学习:

    • 什么是图像分割以及不同类型的分割。
    • 为照片创建了人物分割。
    • 了解不同的质量水平和性能。
    • 人物为视频录制创建了分区。
    • 提供人员分区的其他框架。
    • 细分人群的最佳实践。

    注意:本教程假设您具备SwiftUIUIKitAVFoundations的工作知识。SwiftUI 的更多信息,请参阅SwiftUI:入门。您还需要一个物理的 iOS 15 相关设备来跟随。

    01.gif

    您将看到一张照片和一个漂亮的问候视频家庭语照片人员将在两个选项卡中显示和使用教程的背景。背景上。点击视频标签并显示您将看到显示的相机源头。启动项目设置为权限和相机框架。您更新实时以生成问候!

    在深入了解这些之前,您需要什么人员细分。准备好是好有趣的旅行社。

    介绍图像分割

    图像分割将图像划分为多个图像并进行细化而处理。它提供了更多对像素的理解。

    分割有类型:图像分割实例分割

    当您的一个分割实例是一个相同的部分是其组合的过程。每个人的掩体。代码分割为图像中的每个人生成一个单独的掩体。

    Apple 的 Vision 框架的人员分割 API 是单帧码。它的使用 API 是面向中流式分割为框架中的单独提供的。它用于分割处理和离线处理。

    人物分割的过程有四个步骤:

    1. 创建用户细分请求。
    2. 为该请求创建请求处理程序。
    3. 处理请求。
    4. 处理结果。

    ,您将使用 API 和步骤来创建使用照片!

    创建照片

    你有一个家庭的形象和一个形象。你的目标家庭背景中的人在背景上的背景,以产生背景。

    打开 RayGreetings并打开GreetingProcessor.swift

    在下面添加以下内容import Combine

    进口愿景
    

    下一个,将下面的内容添加到下面的GreetingProcessor内容中@Published var photoOutput = UIImage()

    让请求=  VNGeneratePersonSegmentationRequest ()
    

    在这里,您创建个人细分用于请求的实例。一个有状态的请求,可以重复整个帧的离线处理视频。

    将以下内容添加到GreetingProcessor

    func  generatePhotoGreeting(问候:问候) {
       // 1
      警卫
        让 backgroundImage = greeting.backgroundImage.cgImage,
        让foregroundImage.foregroundImage.c else { print (
         "呼唤的图像" )
        返回
      }
     
      // 2 
      // 创建请求处理程序
      让 requestHandler =  VNImageRequestHandler (
        cgImage:自己的图像,
        选项: [:])
     
      // 执行
    }
    

    这是上面的代码正在做的事情:

    1. cgImagebackgroundImage和访问foregroundImage。然后,它确保两个图像都是有效的。您将很容易使用它们来使用 Core Image 混合图像。
    2. 创建requestHandler为的实例VNImageRequestHandler。它接收图像以及指定如何处理图像的任选字典。

    替换// TODO为以下内容:

    做 {
       // 1
      试用 requestHandler.perform([request])
     
      // 2
      守卫让掩码= request.results ? .first else {
         print ( "生成分割掩码时出错" )
        返回
      }
     
      // 3
      让属性=  CIImage (cgImage:foregroundImage)
      让 maskImage =  CIImage (cvPixelBuffer: mask.pixelBuffer)
      让背景=  CIImage(cgImage:backgroundImage)
     
      // TODO:混合图像
    } 抓住 {
      print ( "处理人员分区请求异常" )
    }
    

    这是自己的代码细分:

    1. requestHandler使用处理人员分割perform(_:)。如果有多个请求,则在所有请求存在完成或失败后返回。perform(_:)在请求处理时可能会通过错误提示,因此您可以将其包含在do-catch
    2. 然后,您从结果中检索掩饰码。因为您只提交了一个请求,所以从结果中检索第一个对象。
    3. 返回结果的pixelBuffer属性掩码。然后创建 CIImage 有背景和蒙版的版本。CIImage 是 Core Image 过滤器将处理的图像的混合表示。您将需要它来图像。

    混合所有图像

    在下面的 GreetingProcessor.swift中添加以下内容import Vision

    导入CoreImage 。CIFilterBuiltins
    

    Core Image 提供了提供类型安全实例的方法CIFilter。在这里,您可以导入CIFilterBuiltins访问类型的安全 API。

    将以下内容添加到GreetingProcessor

    游戏混合图像(
      背景:CIImage,对应
      :CIImage,
      掩饰:CIImage 
    ) -> CIImage? {
       // 1
      让 maskScaleX = foreground.extent.width / mask.extent.width
      让 maskScaleY = foreground.extent.height / mask.extent.height
      让 maskScaled = mask.transformed(
        作者:__CGAffineTransformMake(maskScaleX, 0 , 0 , maskScaleY, 0 , 0 ))
     
      // 2
      让 backgroundScaleX = (foreground.extent.width / background.extent.width)
      让 backgroundScaleY = (foreground.extent.height / background.extent.height)
      让 backgroundScaled = background.transformed(
        作者:__CGAffineTransformMake(backgroundScaleX,
        0 , 0 , backgroundScaleY, 0 , 0 ))
     
      // 3
      让 blendFilter =  CIFilter .blendWithMask()
      blendFilter.inputImage =其他
      blendFilter.backgroundImage = backgroundScaled
      blendFilter.maskImage = maskScaled
     
      // 4
      返回 blendFilter.outputImage
    }
    

    的代码:

    1. 计算蒙版相对于用于相同图像的 X 和 Y 比例。然后它将缩放CGAffineTransformMake缩放到图像。mask``foreground
    2. 与的缩放一样mask,它计算出 X 和 Y 的大小,background然后缩放background到的大小foreground
    3. 创建一个核心blendFilter图像过滤器,inputImage设置为后续过滤器的和缩放版本foregroundbackgroundImage``maskImage
    4. outputImage包含混合的结果。

    返回的结果是类型CIImage。您需要将其转换为一个UIImage以在 UI 中显示的。

    GreetingProcessor以下中,在顶部、添加以下内容let request = VNGeneratePersonSegmentationRequest()

    让时间=  CIContext ()
    

    在这里,您创建一个CIContext。它用于从CIImage对象创建 Quartz 2D 图像。

    将以下内容添加到GreetingProcessor

    函数 renderAsUIImage(_image : CIImage ) -> UIImage ? {
      守卫让 cgImage = context.createCGImage(image, from: image.extent) else {
        返回零
      }
      返回UIImage (cgImage: cgImage)
    }
    

    在这里,您用于从实例context创建。CGImage``CIImage

    使用cgImage,然后创建一个UIImage。用户将看到该图像。

    显示照片问候语

    替换// TODO: Blend imagesgeneratePhotoGreeting(greeting:)添加以下内容:

    // 1守卫让输出= 
    blendImages (
      背景:背景,
      作案:特殊,
      掩码:掩码图像)否则{
        打印(“错误混合图像”)
        返回
      }
     
    // 2
    如果让 photoResult = renderAsUIImage(output) {
       self .photoOutput =照片结果
    }
    

    这是正在发生的事情:

    1. blendImages(background:foreground:mask:)混合图像并确保输出不是nil
    2. 然后,将输出转换为一个实例并将其设置为。是已发布的属性。访问它以在UIImagePhotoGreetingView.swift显示。photoOutput``photoOutput

    最后,打开PhotoGreetingView.swift// TODO: Generate Photo Greeting在行动中闭包中替换Button为以下内容:

    GreetingProcessor .shared.generatePhotoGreeting(问候语:问候语)
    

    在这里,您调用以在被点击generatePhotoGreeting(greeting:)时生成问候语。Button

    在照片设备上制造和运行。点击问候

    02.gif

    默认情况下,您将获得质量最好的节目,它确实不适合这种情况,并且实时所有场景。了解可能的不同质量和性能的处理选项。一点。

    质量和性能选项

    您之前创建的个人细分请求的默认质量等级为VNGeneratePersonSegmentationRequest.QualityLevel.accurate

    您可以从三个质量等级中进行选择:

    • accurate:非常适合您想要获得最高质量且不受时间限制的情况。
    • balanced:非常适合处理视频帧。
    • fast:最适合处理流媒体内容。
    03.png

    生成掩码的质量等级集。

    04.png

    请注意,随着质量级别的提高,蒙版的质量看起来要好得多。准确的质量在蒙版中显示更精细的细节。帧大小、内存和处理时间因质量级别而异。

    05.png

    与快速质量级别相比,精确级别的帧大小高达 64 倍。与快速和平衡的关卡相比,处理准确关卡所需的内存和时间要高得多。这代表了对掩码质量和生成掩码所需资源的权衡。

    现在您知道了权衡,是时候生成一个有趣的视频问候了!:]

    创建视频问候

    打开CameraViewController.swift。它设置了所有功能来捕获相机帧并使用 Metal 渲染它们。要了解有关使用 AVFoundation 和 SwiftUI 设置相机的更多信息,请查看本教程和本视频系列

    查看 中的逻辑CameraViewController,符合AVCaptureVideoDataOutputSampleBufferDelegate.

    extension  CameraViewController : AVCaptureVideoDataOutputSampleBufferDelegate {
       func  captureOutput ( _  output : AVCaptureOutput ,
                          didOutput  sampleBuffer : CMSampleBuffer ,
                          from  connection : AVCaptureConnection ) {
         // 从相机输出
        守卫中获取像素缓冲帧 let pixelBuffer = sampleBuffer.imageBuffer else {
           return
        }
        自.currentCIImage =  CIImage (cvPixelBuffer: pixelBuffer)
      }
    }
    

    在这里,注意pixelBuffer从 中检索sampleBuffer。然后通过更新渲染它currentCIImage。您的目标是将其pixelBuffer用作前景图像并创建视频问候语。

    打开GreetingProcessor.swift并将以下内容添加到GreetingProcessor

    func  processVideoFrame(
      前景:CVPixelBuffer,
      背景:CGImage 
    )-> CIImage?{
      让ciForeground =  CIImage (cvPixelBuffer: 前景)
    
      // TODO:人物分割请求
    
      返回 零
    }
    

    CIImage在这里,您从前景创建一个实例,CVPixelBuffer以便您可以使用 Core Image 过滤器混合图像。

    到目前为止,您已经使用Vision框架来创建、处理和处理人员细分请求。尽管它易于使用,但其他框架提供由相同技术支持的类似功能。接下来你会学到这个。

    生成人员分割的替代方案

    您可以使用这些框架作为 Vision 的替代方案来生成人物分割掩码:

    • AVFoundation:可以在某些较新的设备上拍摄照片时生成人物分割蒙版。您可以通过portraitEffectsMatte.AVCapturePhoto
    • ARKit:在处理相机馈送时生成分割掩码。segmentationBuffer您可以使用 的属性获取掩码ARFrame。它在具有 A12 Bionic 及更高版本的设备上受支持。
    • Core Image:Core Image 在 Vision 框架上提供了一个瘦包装器。它公开了qualityLevel您设置的属性VNGeneratePersonSegmentationRequest

    接下来,您将使用 Core Image 为视频问候生成人物分割掩码。

    使用核心图像生成人物分割掩码

    替换// TODO: person segmentation requestprocessVideoFrame(foreground:background:)以下内容:

    // 1
    让personSegmentFilter =  CIFilter .personSegmentation()
    personSegmentFilter.inputImage = ciForeground
    personSegmentFilter.qualityLevel =  1
     
    // 2 
    if  let mask = personSegmentFilter.outputImage {
       guard  let output = blendImages(
        背景:CIImage(cgImage:背景),
        前景:ciForeground,
        mask: mask) else {
           print ( "Error blending images" )
           return  nil
        }
      返回输出
    }
    

    这就是这样做的:

    1. personSegmentFilter使用核心图像创建CIFilter并设置inputImage前景图像。接受一个qualityLevel数字。不同的质量级别选项包括:

      • 0:准确
      • 1平衡
      • 2:快

      在这里,您设置qualityLevel为 1。

    2. outputImage从of 中获取掩码personSegmentationFilter并确保它不是nil. 然后,它用于blendImages(background:foreground:mask:)混合图像并返回结果。

    打开CameraViewController.swift。将扩展名中的内容替换为以下captureOutput(_:didOutput:from:)内容:CameraViewController

    // 1
    保护 
      let pixelBuffer = sampleBuffer.imageBuffer,
       let backgroundImage =  self .background ? .cgImage其他{
      返回
    }
     
    // 2 
    DispatchQueue .global().async {
       if  let output =  GreetingProcessor .shared.processVideoFrame(
        前景:像素缓冲区,
        背景:背景图像){
        DispatchQueue .main.async {
           self .currentCIImage =输出
        }
      }
    }
    

    这是上面代码的细分。它:

    1. 检查pixelBufferbackgroundImage有效。
    2. 通过调用processVideoFrame(foreground:background:)中定义的异步处理视频帧GreetingProcessor。然后,它更新currentCIImageoutput.

    在物理设备上构建和运行。点击视频问候标签。

    06.gif

    不好了!没有可见的摄像机流。发生了什么?

    打开GreetingProcessor.swiftguard let output = blendImages并在in处放置一个断点processVideoFrame(foreground:background:)。请注意在调试器中使用 Quick Look 生成的掩码。

    07.gif

    面具是红色的!您需要使用红色蒙版而不是常规的白色蒙版创建一个混合滤镜。

    更新blendImages(background:foreground:mask:)以采用新的布尔参数,如下所示:

    func  blendImages(
      背景:CIImage,
      前景:CIImage,
      掩码:CIImage,
       isRedMask:Bool  =  false 
    )-> CIImage?{
    

    这用于isRedMask确定要生成的混合过滤器的类型。默认情况下,它的值为false

    let blendFilter = CIFilter.blendWithMask()如下图所示替换blendImages(background:foreground:mask:isRedMask:)

    让blendFilter = isRedMask ?
    CIFilter .blendWithRedMask() :
     CIFilter .blendWithMask()
    

    在这里,您blendFilter使用红色蒙版生成 if isRedMaskis true。否则,您将使用白色蒙版进行创建。

    接下来,替换:

    守卫 让输出= blendImages(
      背景:CIImage(cgImage:背景),
      前景:ciForeground,
      掩码:掩码)否则{ 
    

    processVideoFrame(foreground:background:) with the following:

    守卫 让输出= blendImages(
      背景:CIImage(cgImage:背景),
      前景:ciForeground,
      面具:面具,
      isRedMask: true ) else {
    

    在这里,您指定生成带有红色蒙版的混合滤镜。

    在物理设备上构建和运行。点击视频问候并将前置摄像头对准您。

    08.gif

    了解最佳实践

    虽然人物分割适用于照片和视频问候语,但请记住以下一些最佳做法:

    • 尝试在一个场景中最多分割四个人,并确保所有人都可见。
    • 一个人的身高应该至少是图像高度的一半。
    • 避免在框架中出现以下歧义:
      • 雕像
      • 远距离

    结束

    您可以使用教程中的所有代码部分下载最终项目。

    这里也推荐一些面试相关的内容,祝各位网友都能拿到满意offer!
    GCD面试要点
    block面试要点
    Runtime面试要点
    RunLoop面试要点
    内存管理面试要点
    MVC、MVVM面试要点
    网络性能优化面试要点
    网络编程面试要点
    KVC&KVO面试要点
    数据存储面试要点
    混编技术面试要点
    设计模式面试要点
    UI面试要点

    相关文章

      网友评论

          本文标题:iOS开发之视觉框架中的人员与背景分割

          本文链接:https://www.haomeiwen.com/subject/qygjprtx.html