ハイライト
Apple は Vision フレームワークに、任意の物体を分割できる tap-to-segment API を追加し、Foundation Models フレームワークには画像入力を追加しました。両者は Tool Calling でつながり、LLM はバーコード読み取りや OCR などのピクセル単位のタスクを Vision ツールに自動委譲できます。さらに Vision は初めて watchOS に対応しました。
主要内容
「人だけ切り抜ける」から「タップしたものを切り抜ける」へ
これまで Vision で画像セグメンテーションを行う場合、選択肢は限られていました。VNGeneratePersonSegmentationRequest で切り抜けるのは人物と背景だけです。花、コーヒーカップ、床の一部を切り抜きたい場合は、開発者が自分でモデルを訓練するか、サードパーティサービスに頼る必要がありました。
今年 Vision に追加された GenerateIterativeSegmentationRequest では、ユーザーが画像内の任意の物体をタップすると、システムが対応するマスクを生成できます。
操作方法は 4 種類あります。
- 単一点:カップをタップすると、カップが切り抜かれる
- 矩形選択:カップと皿を囲むと、両方がまとめて切り抜かれる
- 投げ縄:クロワッサンの周りに閉じた線を描く
- スクリブル:複数の物体をざっとなぞり、一度にまとめて選択する
(02:19)
より実用的なのは反復できる点です。まずカップをタップして mask を作り、次に隣の皿をタップすると、mask が自動的に結合されます。間違えて選んだ場合は減算もできます。カップの本体を除外点としてタップすると、カップの中のコーヒーだけを残せます。
(03:16)
LLM がついに画像を「見られる」ようになった
Foundation Models フレームワークは今年、画像入力に対応しました。冷蔵庫の中の写真を LLM に渡すとレシピを作れます。リビングの写真を渡すと、インテリアの提案を返せます。
(06:09)
API はとても直接的です。
import FoundationModels
let prompt = Prompt {
"この画像のキャプションを生成してください"
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 に渡し、日付、場所、申し込み URL を抽出させるとします。チラシに QR コードがある場合、LLM は自分では読み取れないので、Vision の BarcodeReaderTool を呼び出します。URL を取得したあと、LLM が回答を整理します。
(11:16)
Vision には 2 つの組み込みツールがあります。
BarcodeReaderTool:バーコードと QR コードを読み取るOCRTool:30 以上の言語で密集した小さな文字を認識する
(11:53)
Vision が Apple Watch に来た
Vision フレームワークは初めて watchOS に対応しました。Apple Watch の画面は小さいため、写真全体を表示すると主役が見えにくくなります。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は今年追加された新しい request 型seedパラメータに初期点を渡し、システムはそこから初期 mask を生成するaddIncludedPointは新しい領域を mask に追加し、addExcludedPointは mask から領域を取り除く- 返される
pixelBufferは白黒のマスクで、白いピクセルが対象物体に属する
注意点は 3 つです。
- 座標系の原点は左下で、値の範囲は 0 から 1。使用前に正規化が必要
- 投げ縄の線幅は画像幅の 1% 以上が必要。細すぎると認識されない
- 初回使用時はモデルのダウンロードが必要。
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に変換し、従来のコンピュータビジョンコードで扱えるようにする
Vision の組み込みツールを使う
import FoundationModels
import Vision
let session = LanguageModelSession(model: model, tools: [BarcodeReaderTool()])
let response = try await session.respond(generating: EventInfo.self) {
"このチラシから日付、場所、Web サイトを取得してください"
Attachment(image)
.label("チラシ")
}
(12:09)
要点:
import VisionすればBarcodeReaderToolとOCRToolを使えるLanguageModelSessionを作成するときにtoolsパラメータでツール一覧を渡すAttachment(image).label("チラシ")で画像にラベルを付け、モデルがツール呼び出し時にどの画像を使うか特定できるようにする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 が金額、日付、場所、URL を自動抽出します。QR コードが読みにくい場合は BarcodeReaderTool を自動呼び出しし、密集した小さな文字は OCRTool で処理します。LanguageModelSession(tools: [BarcodeReaderTool(), OCRTool()]) を設定すれば使えます。
4. Apple Watch での画像表示を最適化する
watchOS の写真 App やメッセージ App で、GenerateObjectnessBasedSaliencyImageRequest を使って写真の主体を自動切り抜きすれば、小さな画面でも重要な部分を見やすくできます。この API は今年初めて watchOS に対応し、それ以前は iOS でしか使えませんでした。
5. 「冷蔵庫の食材管理」App を作る
ユーザーが冷蔵庫を開けて写真を撮ると、LLM が食材を識別し、レシピを提案します。Foundation Models の画像入力機能を使い、Attachment(image) を prompt に直接入れて、食材一覧とレシピ提案を生成させます。
関連セッション
- Vision フレームワークにおける Swift の強化を確認する — 顔解析、姿勢推定、物体追跡など、Vision フレームワークの 30 種類以上の画像解析機能を詳しく学ぶ
- Foundation Models フレームワークの新機能 — ツール呼び出しの仕組み全体を含め、Foundation Models フレームワークのその他の新機能を学ぶ
- Foundation Models フレームワークでエージェント App を構築する — ツール呼び出し機能を持つ Agent App の作り方を学ぶ
- SwiftUI の新機能 — SwiftUI で画像編集とプレビューのインタラクティブな画面を構築する
- watchOS の新機能 — watchOS のその他の新機能を学び、Vision と組み合わせて Apple Watch 向け画像 App を作る
コメント
GitHub Issues · utterances