WWDC Quick Look 💓 By SwiftGGTeam
What's new in image understanding

What's new in image understanding

观看原视频

Highlight

Apple 在 Vision 框架新增 tap-to-segment API 支持任意物体分割,Foundation Models 框架新增图像输入能力,两者通过 Tool Calling 打通,LLM 可自动调用 Vision 工具完成条形码读取、OCR 等像素级任务,且 Vision 首次支持 watchOS。

核心内容

从”只能分人”到”点哪分哪”

以前用 Vision 做图像分割,选择很有限。VNGeneratePersonSegmentationRequest 只能把人从背景里抠出来。想抠一朵花、一个咖啡杯、一块地板?没门,开发者得自己训练模型或者接第三方服务。

今年 Vision 新增了 GenerateIterativeSegmentationRequest,用户点一下图片里的任意物体,系统就能生成对应的遮罩(mask)。

交互方式有四种:

  • 单点:点一下杯子,杯子被抠出
  • 矩形框选:框住杯子和盘子,两者一起被抠出
  • 套索:画一个闭合圈,圈住牛角包
  • 涂鸦:随手涂过多个物体,一次性全部选中

02:19

更实用的是迭代能力。先点一下杯子生成 mask,再点一下旁边的盘子,mask 自动合并。点错了也能减——在杯身上点一下排除,就只剩杯中的咖啡。

03:16

LLM 终于能”看”图了

Foundation Models 框架今年支持图像输入。给 LLM 一张冰箱内部的照片,它能生成菜谱;给一张客厅照片,它能给装修建议。

06:09

API 很直接:

import FoundationModels

let prompt = Prompt {
    "Generate a caption for this image"
    Attachment(image)
}
let response = try await session.respond(to: prompt)
let caption = response.content

06:41

Vision 和 LLM 不是二选一,是组合拳

Vision 的 API 针对特定任务做了优化,速度快到能处理视频帧。但 Vision 只能做预设好的事,不能”理解”图像内容。

LLM 什么都能问,但读不准条形码上的小字,也搞不定像素级精度。

Apple 的解法是用 Tool Calling 把两者串起来。LLM 遇到自己搞不定的任务,自动调用 Vision 工具去完成。

举个例子:给 LLM 一张活动海报,让它提取日期、地点和报名网址。海报上有个 QR 码,LLM 自己读不出来,就调用 Vision 的 BarcodeReaderTool,拿到网址后再组织回答。

11:16

Vision 内置了两个工具:

  • BarcodeReaderTool:读条形码和 QR 码
  • OCRTool:识别 30 多种语言的密集小字

11:53

Vision 上了手表

Vision 框架首次支持 watchOS。手表屏幕小,显示完整照片时主体看不清。用 GenerateObjectnessBasedSaliencyImageRequest 找出照片里最显眼的物体,裁剪后只显示主体部分。

13:18

详细内容

Tap-to-segment 的完整用法

let handler = ImageRequestHandler(image)
let request = GenerateIterativeSegmentationRequest(seed: point)
let observation = try await handler.perform(request)
let mask = observation?.pixelBuffer

// 迭代细化:添加新点
request.addIncludedPoint(newPoint)
let refinedObservation = try await handler.perform(request)

04:15

关键点:

  • ImageRequestHandler 持有待处理的图像
  • GenerateIterativeSegmentationRequest 是本次新增的请求类型
  • seed 参数传入初始点,系统据此生成初始 mask
  • addIncludedPoint 把新区域加入 mask,addExcludedPoint 从 mask 中移除
  • 返回的 pixelBuffer 是黑白遮罩,白色像素表示属于目标物体

三个注意事项:

  1. 坐标系原点在左下角,数值范围 0~1,用之前要归一化
  2. 套索线宽至少占图像宽度的 1%,太细识别不出
  3. 首次使用需下载模型,可用 downloadAssets 预下载,用 assetStatus 查状态

04:51

给 LLM 写图像工具

struct PlantIdentifierTool: Tool {
    @SessionProperty(\.history) var history

    @Generable
    struct Arguments {
        var image: ImageReference
    }

    func call(arguments: Arguments) async throws -> String {
        let imageReference = arguments.image
        let transcript = Transcript(history)
        guard let imageAttachment = imageReference.resolve(in: transcript) else {
            throw AppError.imageNotFound
        }
        let image = try imageAttachment.pixelBuffer()
        return classifyPlant(image)
    }
}

09:55

关键点:

  • 工具要遵循 Tool 协议
  • @Generable 标记的参数结构体让模型自动生成调用参数
  • ImageReference 是图像的引用,不是真实图像数据
  • @SessionProperty(\.history) 拿到当前对话历史
  • Transcript(history) 把历史转成可查询的 transcript
  • imageReference.resolve(in: transcript) 在对话上下文中解析出真实图像附件
  • pixelBuffer() 把附件转成 CVPixelBuffer,供传统 CV 代码处理

使用 Vision 内置工具

import FoundationModels
import Vision

let session = LanguageModelSession(model: model, tools: [BarcodeReaderTool()])
let response = try await session.respond(generating: EventInfo.self) {
    "Get the date, location, and website from this flyer"
    Attachment(image)
        .label("flyer")
}

12:09

关键点:

  • import Vision 后就能用 BarcodeReaderToolOCRTool
  • 创建 LanguageModelSession 时通过 tools 参数传入工具列表
  • Attachment(image).label("flyer") 给图像打标签,模型调用工具时靠标签定位用哪张图
  • generating: EventInfo.self 让模型按指定结构体格式返回结果

watchOS 显著性裁剪

func generateImageCrop(in image: CGImage) async throws -> NormalizedRect? {
    let request = GenerateObjectnessBasedSaliencyImageRequest()
    let observation = try await request.perform(on: image)
    let prominentObjects = observation.salientObjects
    return prominentObjects.first
}

13:54

关键点:

  • GenerateObjectnessBasedSaliencyImageRequest 分析图像中”最显眼”的区域
  • salientObjects 返回按显著性排序的矩形框数组
  • first 得到最突出的主体区域
  • 返回的 NormalizedRect 可直接用于裁剪图像

核心启发

1. 做一个”智能相册编辑器”

用户点一下照片里的物体就能抠出来换背景、调滤镜。用 GenerateIterativeSegmentationRequest 做交互式分割,点选、框选、涂鸦都支持。入口 API 就是 ImageRequestHandler + GenerateIterativeSegmentationRequest

2. 做一个”拍照识万物”的 App

用户拍一张植物照片,App 自动识别品种。用 Foundation Models 做自然语言交互,遇到具体识别任务时调用自定义 Vision 工具。实现思路:定义一个 PlantIdentifierTool,在 call 方法里用 ImageReference.resolve 拿到图像,跑自己的分类模型。

3. 做一个”票据自动录入”工具

用户拍一张发票或活动海报,LLM 自动提取金额、日期、地点、网址。LLM 读不清 QR 码时自动调用 BarcodeReaderTool,密集小字自动调用 OCRTool。配置 LanguageModelSession(tools: [BarcodeReaderTool(), OCRTool()]) 即可。

4. 优化手表端的图片展示

在 watchOS 相册或消息 App 里,用 GenerateObjectnessBasedSaliencyImageRequest 自动裁剪出照片主体,小屏幕上也能看清重点。这个 API 今年刚支持 watchOS,之前只能在 iOS 上用。

5. 做一个”冰箱食材管理”App

用户打开冰箱拍一张照,LLM 识别出有哪些食材并推荐菜谱。用 Foundation Models 的图像输入能力,Attachment(image) 直接塞进 prompt,让模型生成食材清单和菜谱建议。

关联 Session

评论

GitHub Issues · utterances