[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6E6W2FTH09WNHD4N7PC7JJR":3,"skill-same:01M6E6W2FTH09WNHD4N7PC7JJR":92},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":23,"publishedAt":42,"linkOnly":43,"markdownContent":44,"markdownBody":45,"frontMatter":46,"refName":51,"commitSha":52,"skillDirectory":53,"forksCount":54,"repositoryHtmlUrl":55,"repositoryHomepageUrl":56,"ownerHtmlUrl":57,"ownerBlogUrl":6,"ownerDescription":58,"updatedAt":59,"install":60,"resources":73},"01M6E6W2FTH09WNHD4N7PC7JJR","axiom-vision-ref",null,"Use when needing Vision framework API details for hand\u002Fbody pose, segmentation, text recognition, barcode detection, document scanning, or Visual Intelligence integration. Covers VNRequest types, coordinate conversion, DataScannerViewController, RecognizeDocumentsRequest, SemanticContentDescriptor, IntentValueQuery.","ComeOnOliver\u002Fskillshub","ComeOnOliver","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F43215937?v=4","01M6E5JNFECJAAVFE0W7SMWWD2","Haoran Shu","01M6E5JNNDQS7AJZDYFQ8TPZCK",66,"MIT","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002FCharlesWiltgen\u002FAxiom\u002Faxiom-vision-ref\u002FSKILL.md",[18],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000030","开发工程师","PROFESSION","适用职业",[24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41],"axiom vision ref","vision","scanning","barcode","visual","intelligence","coordinate","document","conversion","macos","use","text","api","segmentation","detection","ios","integration","framework","2026-11-10 10:12:30",false,"---\nname: axiom-vision-ref\ndescription: Use when needing Vision framework API details for hand\u002Fbody pose, segmentation, text recognition, barcode detection, document scanning, or Visual Intelligence integration. Covers VNRequest types, coordinate conversion, DataScannerViewController, RecognizeDocumentsRequest, SemanticContentDescriptor, IntentValueQuery.\nlicense: MIT\ncompatibility: iOS 11+, iPadOS 11+, macOS 10.13+, tvOS 11+, visionOS 1+\nmetadata:\n  version: \"1.1.0\"\n  last-updated: \"2026-01-03\"\n---\n\n# Vision Framework API Reference\n\nComprehensive reference for Vision framework computer vision: subject segmentation, hand\u002Fbody pose detection, person detection, face analysis, text recognition (OCR), barcode detection, and document scanning.\n\n## When to Use This Reference\n\n- **Implementing subject lifting** using VisionKit or Vision\n- **Detecting hand\u002Fbody poses** for gesture recognition or fitness apps\n- **Segmenting people** from backgrounds or separating multiple individuals\n- **Face detection and landmarks** for AR effects or authentication\n- **Combining Vision APIs** to solve complex computer vision problems\n- **Looking up specific API signatures** and parameter meanings\n- **Recognizing text** in images (OCR) with VNRecognizeTextRequest\n- **Detecting barcodes** and QR codes with VNDetectBarcodesRequest\n- **Building live scanners** with DataScannerViewController\n- **Scanning documents** with VNDocumentCameraViewController\n- **Extracting structured document data** with RecognizeDocumentsRequest (iOS 26+)\n\n**Related skills**: See `axiom-vision` for decision trees and patterns, `axiom-vision-diag` for troubleshooting\n\n## Vision Framework Overview\n\nVision provides computer vision algorithms for still images and video:\n\n**Core workflow**:\n1. Create request (e.g., `VNDetectHumanHandPoseRequest()`)\n2. Create handler with image (`VNImageRequestHandler(cgImage: image)`)\n3. Perform request (`try handler.perform([request])`)\n4. Access observations from `request.results`\n\n**Coordinate system**: Lower-left origin, normalized (0.0-1.0) coordinates\n\n**Performance**: Run on background queue - resource intensive, blocks UI if on main thread\n\n## Request Handlers\n\nVision provides two request handlers for different scenarios.\n\n### VNImageRequestHandler\n\nAnalyzes a **single image**. Initialize with the image, perform requests against it, discard.\n\n```swift\nlet handler = VNImageRequestHandler(cgImage: image)\ntry handler.perform([request1, request2])  \u002F\u002F Multiple requests, one image\n```\n\n**Initialize with**: `CGImage`, `CIImage`, `CVPixelBuffer`, `Data`, or `URL`\n\n**Rule**: One handler per image. Reusing a handler with a different image is unsupported.\n\n### VNSequenceRequestHandler\n\nAnalyzes a **sequence of frames** (video, camera feed). Initialize empty, pass each frame to `perform()`. Maintains inter-frame state for temporal smoothing.\n\n```swift\nlet sequenceHandler = VNSequenceRequestHandler()\n\n\u002F\u002F In your camera\u002Fvideo frame callback:\nfunc processFrame(_ pixelBuffer: CVPixelBuffer) throws {\n    try sequenceHandler.perform([request], on: pixelBuffer)\n}\n```\n\n**Rule**: Create once, reuse across frames. The handler tracks state between calls.\n\n### When to Use Which\n\n| Use Case | Handler |\n|----------|---------|\n| Single photo or screenshot | `VNImageRequestHandler` |\n| Video stream or camera frames | `VNSequenceRequestHandler` |\n| Temporal smoothing (pose, segmentation) | `VNSequenceRequestHandler` |\n| One-off analysis of a CVPixelBuffer | `VNImageRequestHandler` |\n\n### Requests That Benefit from Sequence Handling\n\nThese requests use inter-frame state when run through `VNSequenceRequestHandler`:\n- `VNDetectHumanBodyPoseRequest` — Smoother joint tracking\n- `VNDetectHumanHandPoseRequest` — Smoother landmark tracking\n- `VNGeneratePersonSegmentationRequest` — Temporally consistent masks\n- `VNGeneratePersonInstanceMaskRequest` — Stable person identity across frames\n- `VNDetectDocumentSegmentationRequest` — Stable document edges\n- Any `VNStatefulRequest` subclass — Designed for sequences\n\n### Common Mistake\n\nCreating a new `VNImageRequestHandler` per video frame discards temporal context. Pose landmarks jitter, segmentation masks flicker, and you lose the smoothing that sequence handling provides.\n\n```swift\n\u002F\u002F Wrong — loses temporal context every frame\nfunc processFrame(_ buffer: CVPixelBuffer) throws {\n    let handler = VNImageRequestHandler(cvPixelBuffer: buffer)\n    try handler.perform([poseRequest])\n}\n\n\u002F\u002F Right — maintains inter-frame state\nlet sequenceHandler = VNSequenceRequestHandler()\nfunc processFrame(_ buffer: CVPixelBuffer) throws {\n    try sequenceHandler.perform([poseRequest], on: buffer)\n}\n```\n\n## Subject Segmentation APIs\n\n### VNGenerateForegroundInstanceMaskRequest\n\n**Availability**: iOS 17+, macOS 14+, tvOS 17+, visionOS 1+\n\nGenerates class-agnostic instance mask of foreground objects (people, pets, buildings, food, shoes, etc.)\n\n#### Basic Usage\n\n```swift\nlet request = VNGenerateForegroundInstanceMaskRequest()\nlet handler = VNImageRequestHandler(cgImage: image)\n\ntry handler.perform([request])\n\nguard let observation = request.results?.first as? VNInstanceMaskObservation else {\n    return\n}\n```\n\n#### InstanceMaskObservation\n\n**allInstances**: `IndexSet` containing all foreground instance indices (excludes background 0)\n\n**instanceMask**: `CVPixelBuffer` with UInt8 labels (0 = background, 1+ = instance indices)\n\n**instanceAtPoint(_:)**: Returns instance index at normalized point\n\n```swift\nlet point = CGPoint(x: 0.5, y: 0.5)  \u002F\u002F Center of image\nlet instance = observation.instanceAtPoint(point)\n\nif instance == 0 {\n    print(\"Background tapped\")\n} else {\n    print(\"Instance \\(instance) tapped\")\n}\n```\n\n#### Generating Masks\n\n**createScaledMask(for:croppedToInstancesContent:)**\n\nParameters:\n- `for`: `IndexSet` of instances to include\n- `croppedToInstancesContent`:\n  - `false` = Output matches input resolution (for compositing)\n  - `true` = Tight crop around selected instances\n\nReturns: Single-channel floating-point `CVPixelBuffer` (soft segmentation mask)\n\n```swift\n\u002F\u002F All instances, full resolution\nlet mask = try observation.createScaledMask(\n    for: observation.allInstances,\n    croppedToInstancesContent: false\n)\n\n\u002F\u002F Single instance, cropped\nlet instances = IndexSet(integer: 1)\nlet croppedMask = try observation.createScaledMask(\n    for: instances,\n    croppedToInstancesContent: true\n)\n```\n\n#### Instance Mask Hit Testing\n\nAccess raw pixel buffer to map tap coordinates to instance labels:\n\n```swift\nlet instanceMask = observation.instanceMask\n\nCVPixelBufferLockBaseAddress(instanceMask, .readOnly)\ndefer { CVPixelBufferUnlockBaseAddress(instanceMask, .readOnly) }\n\nlet baseAddress = CVPixelBufferGetBaseAddress(instanceMask)\nlet width = CVPixelBufferGetWidth(instanceMask)\nlet bytesPerRow = CVPixelBufferGetBytesPerRow(instanceMask)\n\n\u002F\u002F Convert normalized tap to pixel coordinates\nlet pixelPoint = VNImagePointForNormalizedPoint(\n    CGPoint(x: normalizedX, y: normalizedY),\n    width: imageWidth,\n    height: imageHeight\n)\n\n\u002F\u002F Calculate byte offset\nlet offset = Int(pixelPoint.y) * bytesPerRow + Int(pixelPoint.x)\n\n\u002F\u002F Read instance label\nlet label = UnsafeRawPointer(baseAddress!).load(\n    fromByteOffset: offset,\n    as: UInt8.self\n)\n\nlet instances = label == 0 ? observation.allInstances : IndexSet(integer: Int(label))\n```\n\n## VisionKit Subject Lifting\n\n### ImageAnalysisInteraction (iOS)\n\n**Availability**: iOS 16+, iPadOS 16+\n\nAdds system-like subject lifting UI to views:\n\n```swift\nlet interaction = ImageAnalysisInteraction()\ninteraction.preferredInteractionTypes = .imageSubject  \u002F\u002F Or .automatic\nimageView.addInteraction(interaction)\n```\n\n**Interaction types**:\n- `.automatic`: Subject lifting + Live Text + data detectors\n- `.imageSubject`: Subject lifting only (no interactive text)\n\n### ImageAnalysisOverlayView (macOS)\n\n**Availability**: macOS 13+\n\n```swift\nlet overlayView = ImageAnalysisOverlayView()\noverlayView.preferredInteractionTypes = .imageSubject\nnsView.addSubview(overlayView)\n```\n\n### Programmatic Access\n\n#### ImageAnalyzer\n\n```swift\nlet analyzer = ImageAnalyzer()\nlet configuration = ImageAnalyzer.Configuration([.text, .visualLookUp])\n\nlet analysis = try await analyzer.analyze(image, configuration: configuration)\n```\n\n#### ImageAnalysis\n\n**subjects**: `[Subject]` - All subjects in image\n\n**highlightedSubjects**: `Set\u003CSubject>` - Currently highlighted (user long-pressed)\n\n**subject(at:)**: Async lookup of subject at normalized point (returns `nil` if none)\n\n```swift\n\u002F\u002F Get all subjects\nlet subjects = analysis.subjects\n\n\u002F\u002F Look up subject at tap\nif let subject = try await analysis.subject(at: tapPoint) {\n    \u002F\u002F Process subject\n}\n\n\u002F\u002F Change highlight state\nanalysis.highlightedSubjects = Set([subjects[0], subjects[1]])\n```\n\n#### Subject Struct\n\n**image**: `UIImage`\u002F`NSImage` - Extracted subject with transparency\n\n**bounds**: `CGRect` - Subject boundaries in image coordinates\n\n```swift\n\u002F\u002F Single subject image\nlet subjectImage = subject.image\n\n\u002F\u002F Composite multiple subjects\nlet compositeImage = try await analysis.image(for: [subject1, subject2])\n```\n\n**Out-of-process**: VisionKit analysis happens out-of-process (performance benefit, image size limited)\n\n## Person Segmentation APIs\n\n### VNGeneratePersonSegmentationRequest\n\n**Availability**: iOS 15+, macOS 12+\n\nReturns single mask containing **all people** in image:\n\n```swift\nlet request = VNGeneratePersonSegmentationRequest()\n\u002F\u002F Configure quality level if needed\ntry handler.perform([request])\n\nguard let observation = request.results?.first as? VNPixelBufferObservation else {\n    return\n}\n\nlet personMask = observation.pixelBuffer  \u002F\u002F CVPixelBuffer\n```\n\n### VNGeneratePersonInstanceMaskRequest\n\n**Availability**: iOS 17+, macOS 14+\n\nReturns **separate masks for up to 4 people**:\n\n```swift\nlet request = VNGeneratePersonInstanceMaskRequest()\ntry handler.perform([request])\n\nguard let observation = request.results?.first as? VNInstanceMaskObservation else {\n    return\n}\n\n\u002F\u002F Same InstanceMaskObservation API as foreground instance masks\nlet allPeople = observation.allInstances  \u002F\u002F Up to 4 people (1-4)\n\n\u002F\u002F Get mask for person 1\nlet person1Mask = try observation.createScaledMask(\n    for: IndexSet(integer: 1),\n    croppedToInstancesContent: false\n)\n```\n\n**Limitations**:\n- Segments up to 4 people\n- With >4 people: may miss people or combine them (typically background people)\n- Use `VNDetectFaceRectanglesRequest` to count faces if you need to handle crowded scenes\n\n## Hand Pose Detection\n\n### VNDetectHumanHandPoseRequest\n\n**Availability**: iOS 14+, macOS 11+\n\nDetects **21 hand landmarks** per hand:\n\n```swift\nlet request = VNDetectHumanHandPoseRequest()\nrequest.maximumHandCount = 2  \u002F\u002F Default: 2, increase if needed\n\nlet handler = VNImageRequestHandler(cgImage: image)\ntry handler.perform([request])\n\nfor observation in request.results as? [VNHumanHandPoseObservation] ?? [] {\n    \u002F\u002F Process each hand\n}\n```\n\n**Performance note**: `maximumHandCount` affects latency. Pose computed only for hands ≤ maximum. Set to lowest acceptable value.\n\n### Hand Landmarks (21 points)\n\n**Wrist**: 1 landmark\n\n**Thumb** (4 landmarks):\n- `.thumbTip`\n- `.thumbIP` (interphalangeal joint)\n- `.thumbMP` (metacarpophalangeal joint)\n- `.thumbCMC` (carpometacarpal joint)\n\n**Fingers** (4 landmarks each):\n- Tip (`.indexTip`, `.middleTip`, `.ringTip`, `.littleTip`)\n- DIP (distal interphalangeal joint)\n- PIP (proximal interphalangeal joint)\n- MCP (metacarpophalangeal joint)\n\n### Group Keys\n\nAccess landmark groups:\n\n| Group Key | Points |\n|-----------|--------|\n| `.all` | All 21 landmarks |\n| `.thumb` | 4 thumb joints |\n| `.indexFinger` | 4 index finger joints |\n| `.middleFinger` | 4 middle finger joints |\n| `.ringFinger` | 4 ring finger joints |\n| `.littleFinger` | 4 little finger joints |\n\n```swift\n\u002F\u002F Get all points\nlet allPoints = try observation.recognizedPoints(.all)\n\n\u002F\u002F Get index finger points only\nlet indexPoints = try observation.recognizedPoints(.indexFinger)\n\n\u002F\u002F Get specific point\nlet thumbTip = try observation.recognizedPoint(.thumbTip)\nlet indexTip = try observation.recognizedPoint(.indexTip)\n\n\u002F\u002F Check confidence\nguard thumbTip.confidence > 0.5 else { return }\n\n\u002F\u002F Access location (normalized coordinates, lower-left origin)\nlet location = thumbTip.location  \u002F\u002F CGPoint\n```\n\n### Gesture Recognition Example (Pinch)\n\n```swift\nlet thumbTip = try observation.recognizedPoint(.thumbTip)\nlet indexTip = try observation.recognizedPoint(.indexTip)\n\nguard thumbTip.confidence > 0.5, indexTip.confidence > 0.5 else {\n    return\n}\n\nlet distance = hypot(\n    thumbTip.location.x - indexTip.location.x,\n    thumbTip.location.y - indexTip.location.y\n)\n\nlet isPinching = distance \u003C 0.05  \u002F\u002F Normalized threshold\n```\n\n### Chirality (Handedness)\n\n```swift\nlet chirality = observation.chirality  \u002F\u002F .left or .right or .unknown\n```\n\n## Body Pose Detection\n\n### VNDetectHumanBodyPoseRequest (2D)\n\n**Availability**: iOS 14+, macOS 11+\n\nDetects **18 body landmarks** (2D normalized coordinates):\n\n```swift\nlet request = VNDetectHumanBodyPoseRequest()\ntry handler.perform([request])\n\nfor observation in request.results as? [VNHumanBodyPoseObservation] ?? [] {\n    \u002F\u002F Process each person\n}\n```\n\n### Body Landmarks (18 points)\n\n**Face** (5 landmarks):\n- `.nose`, `.leftEye`, `.rightEye`, `.leftEar`, `.rightEar`\n\n**Arms** (6 landmarks):\n- Left: `.leftShoulder`, `.leftElbow`, `.leftWrist`\n- Right: `.rightShoulder`, `.rightElbow`, `.rightWrist`\n\n**Torso** (7 landmarks):\n- `.neck` (between shoulders)\n- `.leftShoulder`, `.rightShoulder` (also in arm groups)\n- `.leftHip`, `.rightHip`\n- `.root` (between hips)\n\n**Legs** (6 landmarks):\n- Left: `.leftHip`, `.leftKnee`, `.leftAnkle`\n- Right: `.rightHip`, `.rightKnee`, `.rightAnkle`\n\n**Note**: Shoulders and hips appear in multiple groups\n\n### Group Keys (Body)\n\n| Group Key | Points |\n|-----------|--------|\n| `.all` | All 18 landmarks |\n| `.face` | 5 face landmarks |\n| `.leftArm` | shoulder, elbow, wrist |\n| `.rightArm` | shoulder, elbow, wrist |\n| `.torso` | neck, shoulders, hips, root |\n| `.leftLeg` | hip, knee, ankle |\n| `.rightLeg` | hip, knee, ankle |\n\n```swift\n\u002F\u002F Get all body points\nlet allPoints = try observation.recognizedPoints(.all)\n\n\u002F\u002F Get left arm only\nlet leftArmPoints = try observation.recognizedPoints(.leftArm)\n\n\u002F\u002F Get specific joint\nlet leftWrist = try observation.recognizedPoint(.leftWrist)\n```\n\n### VNDetectHumanBodyPose3DRequest (3D)\n\n**Availability**: iOS 17+, macOS 14+\n\nReturns **3D skeleton with 17 joints** in meters (real-world coordinates):\n\n```swift\nlet request = VNDetectHumanBodyPose3DRequest()\ntry handler.perform([request])\n\nguard let observation = request.results?.first as? VNHumanBodyPose3DObservation else {\n    return\n}\n\n\u002F\u002F Get 3D joint position\nlet leftWrist = try observation.recognizedPoint(.leftWrist)\nlet position = leftWrist.position  \u002F\u002F simd_float4x4 matrix\nlet localPosition = leftWrist.localPosition  \u002F\u002F Relative to parent joint\n```\n\n**3D Body Landmarks** (17 points): Same as 2D except no ears (15 vs 18 2D landmarks)\n\n#### 3D Observation Properties\n\n**bodyHeight**: Estimated height in meters\n- With depth data: Measured height\n- Without depth data: Reference height (1.8m)\n\n**heightEstimation**: `.measured` or `.reference`\n\n**cameraOriginMatrix**: `simd_float4x4` camera position\u002Forientation relative to subject\n\n**pointInImage(\\_:)**: Project 3D joint back to 2D image coordinates\n\n```swift\nlet wrist2D = try observation.pointInImage(leftWrist)\n```\n\n#### 3D Point Classes\n\n**VNPoint3D**: Base class with `simd_float4x4` position matrix\n\n**VNRecognizedPoint3D**: Adds identifier (joint name)\n\n**VNHumanBodyRecognizedPoint3D**: Adds `localPosition` and `parentJoint`\n\n```swift\n\u002F\u002F Position relative to skeleton root (center of hip)\nlet modelPosition = leftWrist.position\n\n\u002F\u002F Position relative to parent joint (left elbow)\nlet relativePosition = leftWrist.localPosition\n```\n\n#### Depth Input\n\nVision accepts depth data alongside images:\n\n```swift\n\u002F\u002F From AVDepthData\nlet handler = VNImageRequestHandler(\n    cvPixelBuffer: imageBuffer,\n    depthData: depthData,\n    orientation: orientation\n)\n\n\u002F\u002F From file (automatic depth extraction)\nlet handler = VNImageRequestHandler(url: imageURL)  \u002F\u002F Depth auto-fetched\n```\n\n**Depth formats**: Disparity or Depth (interchangeable via AVFoundation)\n\n**LiDAR**: Use in live capture sessions for accurate scale\u002Fmeasurement\n\n## Face Detection & Landmarks\n\n### VNDetectFaceRectanglesRequest\n\n**Availability**: iOS 11+\n\nDetects face bounding boxes:\n\n```swift\nlet request = VNDetectFaceRectanglesRequest()\ntry handler.perform([request])\n\nfor observation in request.results as? [VNFaceObservation] ?? [] {\n    let faceBounds = observation.boundingBox  \u002F\u002F Normalized rect\n}\n```\n\n### VNDetectFaceLandmarksRequest\n\n**Availability**: iOS 11+\n\nDetects face with detailed landmarks:\n\n```swift\nlet request = VNDetectFaceLandmarksRequest()\ntry handler.perform([request])\n\nfor observation in request.results as? [VNFaceObservation] ?? [] {\n    if let landmarks = observation.landmarks {\n        let leftEye = landmarks.leftEye\n        let nose = landmarks.nose\n        let leftPupil = landmarks.leftPupil  \u002F\u002F Revision 2+\n    }\n}\n```\n\n**Revisions**:\n- Revision 1: Basic landmarks\n- Revision 2: Detects upside-down faces\n- Revision 3+: Pupil locations\n\n## Person Detection\n\n### VNDetectHumanRectanglesRequest\n\n**Availability**: iOS 13+\n\nDetects human bounding boxes (torso detection):\n\n```swift\nlet request = VNDetectHumanRectanglesRequest()\ntry handler.perform([request])\n\nfor observation in request.results as? [VNHumanObservation] ?? [] {\n    let humanBounds = observation.boundingBox  \u002F\u002F Normalized rect\n}\n```\n\n**Use case**: Faster than pose detection when you only need location\n\n## CoreImage Integration\n\n### CIBlendWithMask Filter\n\nComposite subject on new background using Vision mask:\n\n```swift\n\u002F\u002F 1. Get mask from Vision\nlet observation = request.results?.first as? VNInstanceMaskObservation\nlet visionMask = try observation.createScaledMask(\n    for: observation.allInstances,\n    croppedToInstancesContent: false\n)\n\n\u002F\u002F 2. Convert to CIImage\nlet maskImage = CIImage(cvPixelBuffer: visionMask)\n\n\u002F\u002F 3. Apply filter\nlet filter = CIFilter(name: \"CIBlendWithMask\")!\nfilter.setValue(sourceImage, forKey: kCIInputImageKey)\nfilter.setValue(maskImage, forKey: kCIInputMaskImageKey)\nfilter.setValue(newBackground, forKey: kCIInputBackgroundImageKey)\n\nlet output = filter.outputImage  \u002F\u002F Composited result\n```\n\n**Parameters**:\n- **Input image**: Original image to mask\n- **Mask image**: Vision's soft segmentation mask\n- **Background image**: New background (or empty image for transparency)\n\n**HDR preservation**: CoreImage preserves high dynamic range from input (Vision\u002FVisionKit output is SDR)\n\n## Text Recognition APIs\n\n### VNRecognizeTextRequest\n\n**Availability**: iOS 13+, macOS 10.15+\n\nRecognizes text in images with configurable accuracy\u002Fspeed trade-off.\n\n#### Basic Usage\n\n```swift\nlet request = VNRecognizeTextRequest()\nrequest.recognitionLevel = .accurate  \u002F\u002F Or .fast\nrequest.recognitionLanguages = [\"en-US\", \"de-DE\"]  \u002F\u002F Order matters\nrequest.usesLanguageCorrection = true\n\nlet handler = VNImageRequestHandler(cgImage: image)\ntry handler.perform([request])\n\nfor observation in request.results as? [VNRecognizedTextObservation] ?? [] {\n    \u002F\u002F Get top candidates\n    let candidates = observation.topCandidates(3)\n    let bestText = candidates.first?.string ?? \"\"\n}\n```\n\n#### Recognition Levels\n\n| Level | Performance | Accuracy | Best For |\n|-------|-------------|----------|----------|\n| `.fast` | Real-time | Good | Camera feed, large text, signs |\n| `.accurate` | Slower | Excellent | Documents, receipts, handwriting |\n\n**Fast path**: Character-by-character recognition (Neural Network → Character Detection)\n\n**Accurate path**: Full-line ML recognition (Neural Network → Line\u002FWord Recognition)\n\n#### Properties\n\n| Property | Type | Description |\n|----------|------|-------------|\n| `recognitionLevel` | `VNRequestTextRecognitionLevel` | `.fast` or `.accurate` |\n| `recognitionLanguages` | `[String]` | BCP 47 language codes, order = priority |\n| `usesLanguageCorrection` | `Bool` | Use language model for correction |\n| `customWords` | `[String]` | Domain-specific vocabulary |\n| `automaticallyDetectsLanguage` | `Bool` | Auto-detect language (iOS 16+) |\n| `minimumTextHeight` | `Float` | Min text height as fraction of image (0-1) |\n| `revision` | `Int` | API version (affects supported languages) |\n\n#### Language Support\n\n```swift\n\u002F\u002F Check supported languages for current settings\nlet languages = try VNRecognizeTextRequest.supportedRecognitionLanguages(\n    for: .accurate,\n    revision: VNRecognizeTextRequestRevision3\n)\n```\n\n**Language correction**: Improves accuracy but takes processing time. Disable for codes\u002Fserial numbers.\n\n**Custom words**: Add domain-specific vocabulary for better recognition (medical terms, product codes).\n\n#### VNRecognizedTextObservation\n\n**boundingBox**: Normalized rect containing recognized text\n\n**topCandidates(_:)**: Returns `[VNRecognizedText]` ordered by confidence\n\n#### VNRecognizedText\n\n| Property | Type | Description |\n|----------|------|-------------|\n| `string` | `String` | Recognized text |\n| `confidence` | `VNConfidence` | 0.0-1.0 |\n| `boundingBox(for:)` | `VNRectangleObservation?` | Box for substring range |\n\n```swift\n\u002F\u002F Get bounding box for substring\nlet text = candidate.string\nif let range = text.range(of: \"invoice\") {\n    let box = try candidate.boundingBox(for: range)\n}\n```\n\n## Barcode Detection APIs\n\n### VNDetectBarcodesRequest\n\n**Availability**: iOS 11+, macOS 10.13+\n\nDetects and decodes barcodes and QR codes.\n\n#### Basic Usage\n\n```swift\nlet request = VNDetectBarcodesRequest()\nrequest.symbologies = [.qr, .ean13, .code128]  \u002F\u002F Specific codes\n\nlet handler = VNImageRequestHandler(cgImage: image)\ntry handler.perform([request])\n\nfor barcode in request.results as? [VNBarcodeObservation] ?? [] {\n    let payload = barcode.payloadStringValue\n    let type = barcode.symbology\n    let bounds = barcode.boundingBox\n}\n```\n\n#### Symbologies\n\n**1D Barcodes**:\n- `.codabar` (iOS 15+)\n- `.code39`, `.code39Checksum`, `.code39FullASCII`, `.code39FullASCIIChecksum`\n- `.code93`, `.code93i`\n- `.code128`\n- `.ean8`, `.ean13`\n- `.gs1DataBar`, `.gs1DataBarExpanded`, `.gs1DataBarLimited` (iOS 15+)\n- `.i2of5`, `.i2of5Checksum`\n- `.itf14`\n- `.upce`\n\n**2D Codes**:\n- `.aztec`\n- `.dataMatrix`\n- `.microPDF417` (iOS 15+)\n- `.microQR` (iOS 15+)\n- `.pdf417`\n- `.qr`\n\n**Performance**: Specifying fewer symbologies = faster detection\n\n#### Revisions\n\n| Revision | iOS | Features |\n|----------|-----|----------|\n| 1 | 11+ | Basic detection, one code at a time |\n| 2 | 15+ | Codabar, GS1, MicroPDF, MicroQR, better ROI |\n| 3 | 16+ | ML-based, multiple codes, better bounding boxes |\n\n#### VNBarcodeObservation\n\n| Property | Type | Description |\n|----------|------|-------------|\n| `payloadStringValue` | `String?` | Decoded content |\n| `symbology` | `VNBarcodeSymbology` | Barcode type |\n| `boundingBox` | `CGRect` | Normalized bounds |\n| `topLeft\u002FtopRight\u002FbottomLeft\u002FbottomRight` | `CGPoint` | Corner points |\n\n## VisionKit Scanner APIs\n\n### DataScannerViewController\n\n**Availability**: iOS 16+\n\nCamera-based live scanner with built-in UI for text and barcodes.\n\n#### Check Availability\n\n```swift\n\u002F\u002F Hardware support\nDataScannerViewController.isSupported\n\n\u002F\u002F Runtime availability (camera access, parental controls)\nDataScannerViewController.isAvailable\n```\n\n#### Configuration\n\n```swift\nimport VisionKit\n\nlet dataTypes: Set\u003CDataScannerViewController.RecognizedDataType> = [\n    .barcode(symbologies: [.qr, .ean13]),\n    .text(textContentType: .URL),  \u002F\u002F Or nil for all text\n    \u002F\u002F .text(languages: [\"ja\"])  \u002F\u002F Filter by language\n]\n\nlet scanner = DataScannerViewController(\n    recognizedDataTypes: dataTypes,\n    qualityLevel: .balanced,  \u002F\u002F .fast, .balanced, .accurate\n    recognizesMultipleItems: true,\n    isHighFrameRateTrackingEnabled: true,\n    isPinchToZoomEnabled: true,\n    isGuidanceEnabled: true,\n    isHighlightingEnabled: true\n)\n\nscanner.delegate = self\npresent(scanner, animated: true) {\n    try? scanner.startScanning()\n}\n```\n\n#### RecognizedDataType\n\n| Type | Description |\n|------|-------------|\n| `.barcode(symbologies:)` | Specific barcode types |\n| `.text()` | All text |\n| `.text(languages:)` | Text filtered by language |\n| `.text(textContentType:)` | Text filtered by type (URL, phone, email) |\n\n#### Delegate Protocol\n\n```swift\nprotocol DataScannerViewControllerDelegate {\n    func dataScanner(_ dataScanner: DataScannerViewController,\n                     didTapOn item: RecognizedItem)\n\n    func dataScanner(_ dataScanner: DataScannerViewController,\n                     didAdd addedItems: [RecognizedItem],\n                     allItems: [RecognizedItem])\n\n    func dataScanner(_ dataScanner: DataScannerViewController,\n                     didUpdate updatedItems: [RecognizedItem],\n                     allItems: [RecognizedItem])\n\n    func dataScanner(_ dataScanner: DataScannerViewController,\n                     didRemove removedItems: [RecognizedItem],\n                     allItems: [RecognizedItem])\n\n    func dataScanner(_ dataScanner: DataScannerViewController,\n                     becameUnavailableWithError error: DataScannerViewController.ScanningUnavailable)\n}\n```\n\n#### RecognizedItem\n\n```swift\nenum RecognizedItem {\n    case text(RecognizedItem.Text)\n    case barcode(RecognizedItem.Barcode)\n\n    var id: UUID { get }\n    var bounds: RecognizedItem.Bounds { get }\n}\n\n\u002F\u002F Text item\nstruct Text {\n    let transcript: String\n}\n\n\u002F\u002F Barcode item\nstruct Barcode {\n    let payloadStringValue: String?\n    let observation: VNBarcodeObservation\n}\n```\n\n#### Async Stream\n\n```swift\n\u002F\u002F Alternative to delegate\nfor await items in scanner.recognizedItems {\n    \u002F\u002F Current recognized items\n}\n```\n\n#### Custom Highlights\n\n```swift\n\u002F\u002F Add custom views over recognized items\nscanner.overlayContainerView.addSubview(customHighlight)\n\n\u002F\u002F Capture still photo\nlet photo = try await scanner.capturePhoto()\n```\n\n### VNDocumentCameraViewController\n\n**Availability**: iOS 13+\n\nDocument scanning with automatic edge detection, perspective correction, and lighting adjustment.\n\n#### Basic Usage\n\n```swift\nimport VisionKit\n\nlet camera = VNDocumentCameraViewController()\ncamera.delegate = self\npresent(camera, animated: true)\n```\n\n#### Delegate Protocol\n\n```swift\nprotocol VNDocumentCameraViewControllerDelegate {\n    func documentCameraViewController(_ controller: VNDocumentCameraViewController,\n                                       didFinishWith scan: VNDocumentCameraScan)\n\n    func documentCameraViewControllerDidCancel(_ controller: VNDocumentCameraViewController)\n\n    func documentCameraViewController(_ controller: VNDocumentCameraViewController,\n                                       didFailWithError error: Error)\n}\n```\n\n#### VNDocumentCameraScan\n\n| Property | Type | Description |\n|----------|------|-------------|\n| `pageCount` | `Int` | Number of scanned pages |\n| `imageOfPage(at:)` | `UIImage` | Get page image at index |\n| `title` | `String` | User-editable title |\n\n```swift\nfunc documentCameraViewController(_ controller: VNDocumentCameraViewController,\n                                   didFinishWith scan: VNDocumentCameraScan) {\n    controller.dismiss(animated: true)\n\n    for i in 0..\u003Cscan.pageCount {\n        let pageImage = scan.imageOfPage(at: i)\n        \u002F\u002F Process with VNRecognizeTextRequest\n    }\n}\n```\n\n## Document Analysis APIs\n\n### VNDetectDocumentSegmentationRequest\n\n**Availability**: iOS 15+, macOS 12+\n\nDetects document boundaries for custom camera UIs or post-processing.\n\n```swift\nlet request = VNDetectDocumentSegmentationRequest()\nlet handler = VNImageRequestHandler(ciImage: image)\ntry handler.perform([request])\n\nguard let observation = request.results?.first as? VNRectangleObservation else {\n    return  \u002F\u002F No document found\n}\n\n\u002F\u002F Get corner points (normalized)\nlet corners = [\n    observation.topLeft,\n    observation.topRight,\n    observation.bottomLeft,\n    observation.bottomRight\n]\n```\n\n**vs VNDetectRectanglesRequest**:\n- Document: ML-based, trained specifically on documents\n- Rectangle: Edge-based, finds any quadrilateral\n\n### RecognizeDocumentsRequest (iOS 26+)\n\n**Availability**: iOS 26+, macOS 26+\n\nStructured document understanding with semantic parsing.\n\n#### Basic Usage\n\n```swift\nlet request = RecognizeDocumentsRequest()\nlet observations = try await request.perform(on: imageData)\n\nguard let document = observations.first?.document else {\n    return\n}\n```\n\n#### DocumentObservation Hierarchy\n\n```\nDocumentObservation\n└── document: DocumentObservation.Document\n    ├── text: TextObservation\n    ├── tables: [Container.Table]\n    ├── lists: [Container.List]\n    └── barcodes: [Container.Barcode]\n```\n\n#### Table Extraction\n\n```swift\nfor table in document.tables {\n    for row in table.rows {\n        for cell in row {\n            let text = cell.content.text.transcript\n            let detectedData = cell.content.text.detectedData\n        }\n    }\n}\n```\n\n#### Detected Data Types\n\n```swift\nfor data in document.text.detectedData {\n    switch data.match.details {\n    case .emailAddress(let email):\n        let address = email.emailAddress\n    case .phoneNumber(let phone):\n        let number = phone.phoneNumber\n    case .link(let url):\n        let link = url\n    case .address(let address):\n        let components = address\n    case .date(let date):\n        let dateValue = date\n    default:\n        break\n    }\n}\n```\n\n#### TextObservation Hierarchy\n\n```\nTextObservation\n├── transcript: String\n├── lines: [TextObservation.Line]\n├── paragraphs: [TextObservation.Paragraph]\n├── words: [TextObservation.Word]\n└── detectedData: [DetectedDataObservation]\n```\n\n## Visual Intelligence Integration\n\nVisual Intelligence is a **system-level feature** (iOS 26+) that lets users point their camera at real-world objects and find matching content across apps. This is distinct from the Vision framework (VNRequest-based image analysis) covered above. Vision analyzes images within your app; Visual Intelligence lets the system invoke your app when users search with the camera or screenshots.\n\n### How It Works\n\n1. User activates Visual Intelligence camera or takes a screenshot\n2. System analyzes what the user is looking at\n3. System queries participating apps via `IntentValueQuery`\n4. Your app receives a `SemanticContentDescriptor` with labels and\u002For pixel data\n5. Your app searches its content and returns matching `AppEntity` results\n6. Results appear in the Visual Intelligence UI with your app's branding\n\n### Required Frameworks\n\n```swift\nimport VisualIntelligence\nimport AppIntents\n```\n\n### SemanticContentDescriptor\n\nThe core object the system provides to describe what the user is looking at.\n\n| Property | Type | Description |\n|----------|------|-------------|\n| `labels` | `[String]` | Classification labels for the detected item |\n| `pixelBuffer` | `CVReadOnlyPixelBuffer?` | Visual data of the detected item |\n\nUse labels for fast keyword matching against your content catalog. Use the pixel buffer for image-similarity search when labels are insufficient.\n\n### IntentValueQuery\n\nThe entry point for Visual Intelligence to communicate with your app. Implement `values(for:)` to receive search requests and return matching entities.\n\n```swift\nstruct LandmarkIntentValueQuery: IntentValueQuery {\n    @Dependency var modelData: ModelData\n\n    func values(for input: SemanticContentDescriptor) async throws -> [LandmarkEntity] {\n        if !input.labels.isEmpty {\n            return try await modelData.search(matching: input.labels)\n        }\n        guard let pixelBuffer = input.pixelBuffer else { return [] }\n        return try await modelData.search(matching: pixelBuffer)\n    }\n}\n```\n\n### Returning Multiple Result Types\n\nUse `@UnionValue` when your app can return different entity types from a single search.\n\n```swift\n@UnionValue\nenum VisualSearchResult {\n    case landmark(LandmarkEntity)\n    case collection(CollectionEntity)\n}\n```\n\n### Display Representation\n\nVisual Intelligence uses your entity's `DisplayRepresentation` to show results. Provide a title, subtitle, and image for each result.\n\n```swift\nstruct LandmarkEntity: AppEntity {\n    var id: String\n    var name: String\n    var location: String\n\n    static var typeDisplayRepresentation: TypeDisplayRepresentation {\n        TypeDisplayRepresentation(\n            name: LocalizedStringResource(\"Landmark\", table: \"AppIntents\"),\n            numericFormat: \"\\(placeholder: .int) landmarks\"\n        )\n    }\n\n    var displayRepresentation: DisplayRepresentation {\n        DisplayRepresentation(\n            title: \"\\(name)\",\n            subtitle: \"\\(location)\",\n            image: .init(named: thumbnailImageName)\n        )\n    }\n}\n```\n\n### Deep Linking from Results\n\nWhen a user taps a result, your app should open to the relevant content. Provide an `appLinkURL` on your entity.\n\n```swift\nvar appLinkURL: URL? {\n    URL(string: \"yourapp:\u002F\u002Flandmark\u002F\\(id)\")\n}\n```\n\n### \"More Results\" Intent\n\nFor large result sets, provide a `VisualIntelligenceSearchIntent` that opens your app's full search UI.\n\n```swift\nstruct ViewMoreLandmarksIntent: AppIntent, VisualIntelligenceSearchIntent {\n    static var title: LocalizedStringResource = \"View More Landmarks\"\n\n    @Parameter(title: \"Semantic Content\")\n    var semanticContent: SemanticContentDescriptor\n\n    func perform() async throws -> some IntentResult {\n        \u002F\u002F Open your app's search view with the semantic content\n        return .result()\n    }\n}\n```\n\n### Best Practices\n\n- **Return results quickly** — Visual Intelligence expects low-latency responses. Limit to 10-20 most relevant results\n- **Prefer labels first** — Label matching is faster than pixel buffer analysis. Fall back to pixel buffer when labels are empty or insufficient\n- **Localize everything** — Display representations appear in the system UI. Use `LocalizedStringResource` for all user-facing text\n- **Include images** — Results with thumbnails are more recognizable in the Visual Intelligence overlay\n\n### Testing\n\n1. Build and run on a physical device\n2. Activate Visual Intelligence camera or take a screenshot of relevant content\n3. Perform a visual search and verify your app's results appear\n4. Tap results to verify deep linking opens the correct content\n\n## API Quick Reference\n\n### Subject Segmentation\n\n| API | Platform | Purpose |\n|-----|----------|---------|\n| `VNGenerateForegroundInstanceMaskRequest` | iOS 17+ | Class-agnostic subject instances |\n| `VNGeneratePersonInstanceMaskRequest` | iOS 17+ | Up to 4 people separately |\n| `VNGeneratePersonSegmentationRequest` | iOS 15+ | All people (single mask) |\n| `ImageAnalysisInteraction` (VisionKit) | iOS 16+ | UI for subject lifting |\n\n### Pose Detection\n\n| API | Platform | Landmarks | Coordinates |\n|-----|----------|-----------|-------------|\n| `VNDetectHumanHandPoseRequest` | iOS 14+ | 21 per hand | 2D normalized |\n| `VNDetectHumanBodyPoseRequest` | iOS 14+ | 18 body joints | 2D normalized |\n| `VNDetectHumanBodyPose3DRequest` | iOS 17+ | 17 body joints | 3D meters |\n\n### Face & Person Detection\n\n| API | Platform | Purpose |\n|-----|----------|---------|\n| `VNDetectFaceRectanglesRequest` | iOS 11+ | Face bounding boxes |\n| `VNDetectFaceLandmarksRequest` | iOS 11+ | Face with detailed landmarks |\n| `VNDetectHumanRectanglesRequest` | iOS 13+ | Human torso bounding boxes |\n\n### Text & Barcode\n\n| API | Platform | Purpose |\n|-----|----------|---------|\n| `VNRecognizeTextRequest` | iOS 13+ | Text recognition (OCR) |\n| `VNDetectBarcodesRequest` | iOS 11+ | Barcode\u002FQR detection |\n| `DataScannerViewController` | iOS 16+ | Live camera scanner (text + barcodes) |\n| `VNDocumentCameraViewController` | iOS 13+ | Document scanning with perspective correction |\n| `VNDetectDocumentSegmentationRequest` | iOS 15+ | Programmatic document edge detection |\n| `RecognizeDocumentsRequest` | iOS 26+ | Structured document extraction |\n\n### Visual Intelligence\n\n| API | Platform | Purpose |\n|-----|----------|---------|\n| `SemanticContentDescriptor` | iOS 26+ | Describes what the user is looking at (labels + pixel buffer) |\n| `IntentValueQuery` | iOS 26+ | Entry point for receiving visual search requests |\n| `VisualIntelligenceSearchIntent` | iOS 26+ | \"More results\" deep link to your app |\n\n### Observation Types\n\n| Observation | Returned By |\n|-------------|-------------|\n| `VNInstanceMaskObservation` | Foreground\u002Fperson instance masks |\n| `VNPixelBufferObservation` | Person segmentation (single mask) |\n| `VNHumanHandPoseObservation` | Hand pose |\n| `VNHumanBodyPoseObservation` | Body pose (2D) |\n| `VNHumanBodyPose3DObservation` | Body pose (3D) |\n| `VNFaceObservation` | Face detection\u002Flandmarks |\n| `VNHumanObservation` | Human rectangles |\n| `VNRecognizedTextObservation` | Text recognition |\n| `VNBarcodeObservation` | Barcode detection |\n| `VNRectangleObservation` | Document segmentation |\n| `DocumentObservation` | Structured document (iOS 26+) |\n\n## Resources\n\n**WWDC**: 2019-234, 2021-10041, 2022-10024, 2022-10025, 2025-272, 2023-10176, 2023-111241, 2023-10048, 2020-10653, 2020-10043, 2020-10099\n\n**Docs**: \u002Fvision, \u002Fvisionkit, \u002Fvisualintelligence, \u002Fvisualintelligence\u002Fsemanticcontentdescriptor, \u002Fvision\u002Fvnrecognizetextrequest, \u002Fvision\u002Fvndetectbarcodesrequest\n\n**Skills**: axiom-vision, axiom-vision-diag\n\n","# Vision Framework API Reference\n\nComprehensive reference for Vision framework computer vision: subject segmentation, hand\u002Fbody pose detection, person detection, face analysis, text recognition (OCR), barcode detection, and document scanning.\n\n## When to Use This Reference\n\n- **Implementing subject lifting** using VisionKit or Vision\n- **Detecting hand\u002Fbody poses** for gesture recognition or fitness apps\n- **Segmenting people** from backgrounds or separating multiple individuals\n- **Face detection and landmarks** for AR effects or authentication\n- **Combining Vision APIs** to solve complex computer vision problems\n- **Looking up specific API signatures** and parameter meanings\n- **Recognizing text** in images (OCR) with VNRecognizeTextRequest\n- **Detecting barcodes** and QR codes with VNDetectBarcodesRequest\n- **Building live scanners** with DataScannerViewController\n- **Scanning documents** with VNDocumentCameraViewController\n- **Extracting structured document data** with RecognizeDocumentsRequest (iOS 26+)\n\n**Related skills**: See `axiom-vision` for decision trees and patterns, `axiom-vision-diag` for troubleshooting\n\n## Vision Framework Overview\n\nVision provides computer vision algorithms for still images and video:\n\n**Core workflow**:\n1. Create request (e.g., `VNDetectHumanHandPoseRequest()`)\n2. Create handler with image (`VNImageRequestHandler(cgImage: image)`)\n3. Perform request (`try handler.perform([request])`)\n4. Access observations from `request.results`\n\n**Coordinate system**: Lower-left origin, normalized (0.0-1.0) coordinates\n\n**Performance**: Run on background queue - resource intensive, blocks UI if on main thread\n\n## Request Handlers\n\nVision provides two request handlers for different scenarios.\n\n### VNImageRequestHandler\n\nAnalyzes a **single image**. Initialize with the image, perform requests against it, discard.\n\n```swift\nlet handler = VNImageRequestHandler(cgImage: image)\ntry handler.perform([request1, request2])  \u002F\u002F Multiple requests, one image\n```\n\n**Initialize with**: `CGImage`, `CIImage`, `CVPixelBuffer`, `Data`, or `URL`\n\n**Rule**: One handler per image. Reusing a handler with a different image is unsupported.\n\n### VNSequenceRequestHandler\n\nAnalyzes a **sequence of frames** (video, camera feed). Initialize empty, pass each frame to `perform()`. Maintains inter-frame state for temporal smoothing.\n\n```swift\nlet sequenceHandler = VNSequenceRequestHandler()\n\n\u002F\u002F In your camera\u002Fvideo frame callback:\nfunc processFrame(_ pixelBuffer: CVPixelBuffer) throws {\n    try sequenceHandler.perform([request], on: pixelBuffer)\n}\n```\n\n**Rule**: Create once, reuse across frames. The handler tracks state between calls.\n\n### When to Use Which\n\n| Use Case | Handler |\n|----------|---------|\n| Single photo or screenshot | `VNImageRequestHandler` |\n| Video stream or camera frames | `VNSequenceRequestHandler` |\n| Temporal smoothing (pose, segmentation) | `VNSequenceRequestHandler` |\n| One-off analysis of a CVPixelBuffer | `VNImageRequestHandler` |\n\n### Requests That Benefit from Sequence Handling\n\nThese requests use inter-frame state when run through `VNSequenceRequestHandler`:\n- `VNDetectHumanBodyPoseRequest` — Smoother joint tracking\n- `VNDetectHumanHandPoseRequest` — Smoother landmark tracking\n- `VNGeneratePersonSegmentationRequest` — Temporally consistent masks\n- `VNGeneratePersonInstanceMaskRequest` — Stable person identity across frames\n- `VNDetectDocumentSegmentationRequest` — Stable document edges\n- Any `VNStatefulRequest` subclass — Designed for sequences\n\n### Common Mistake\n\nCreating a new `VNImageRequestHandler` per video frame discards temporal context. Pose landmarks jitter, segmentation masks flicker, and you lose the smoothing that sequence handling provides.\n\n```swift\n\u002F\u002F Wrong — loses temporal context every frame\nfunc processFrame(_ buffer: CVPixelBuffer) throws {\n    let handler = VNImageRequestHandler(cvPixelBuffer: buffer)\n    try handler.perform([poseRequest])\n}\n\n\u002F\u002F Right — maintains inter-frame state\nlet sequenceHandler = VNSequenceRequestHandler()\nfunc processFrame(_ buffer: CVPixelBuffer) throws {\n    try sequenceHandler.perform([poseRequest], on: buffer)\n}\n```\n\n## Subject Segmentation APIs\n\n### VNGenerateForegroundInstanceMaskRequest\n\n**Availability**: iOS 17+, macOS 14+, tvOS 17+, visionOS 1+\n\nGenerates class-agnostic instance mask of foreground objects (people, pets, buildings, food, shoes, etc.)\n\n#### Basic Usage\n\n```swift\nlet request = VNGenerateForegroundInstanceMaskRequest()\nlet handler = VNImageRequestHandler(cgImage: image)\n\ntry handler.perform([request])\n\nguard let observation = request.results?.first as? VNInstanceMaskObservation else {\n    return\n}\n```\n\n#### InstanceMaskObservation\n\n**allInstances**: `IndexSet` containing all foreground instance indices (excludes background 0)\n\n**instanceMask**: `CVPixelBuffer` with UInt8 labels (0 = background, 1+ = instance indices)\n\n**instanceAtPoint(_:)**: Returns instance index at normalized point\n\n```swift\nlet point = CGPoint(x: 0.5, y: 0.5)  \u002F\u002F Center of image\nlet instance = observation.instanceAtPoint(point)\n\nif instance == 0 {\n    print(\"Background tapped\")\n} else {\n    print(\"Instance \\(instance) tapped\")\n}\n```\n\n#### Generating Masks\n\n**createScaledMask(for:croppedToInstancesContent:)**\n\nParameters:\n- `for`: `IndexSet` of instances to include\n- `croppedToInstancesContent`:\n  - `false` = Output matches input resolution (for compositing)\n  - `true` = Tight crop around selected instances\n\nReturns: Single-channel floating-point `CVPixelBuffer` (soft segmentation mask)\n\n```swift\n\u002F\u002F All instances, full resolution\nlet mask = try observation.createScaledMask(\n    for: observation.allInstances,\n    croppedToInstancesContent: false\n)\n\n\u002F\u002F Single instance, cropped\nlet instances = IndexSet(integer: 1)\nlet croppedMask = try observation.createScaledMask(\n    for: instances,\n    croppedToInstancesContent: true\n)\n```\n\n#### Instance Mask Hit Testing\n\nAccess raw pixel buffer to map tap coordinates to instance labels:\n\n```swift\nlet instanceMask = observation.instanceMask\n\nCVPixelBufferLockBaseAddress(instanceMask, .readOnly)\ndefer { CVPixelBufferUnlockBaseAddress(instanceMask, .readOnly) }\n\nlet baseAddress = CVPixelBufferGetBaseAddress(instanceMask)\nlet width = CVPixelBufferGetWidth(instanceMask)\nlet bytesPerRow = CVPixelBufferGetBytesPerRow(instanceMask)\n\n\u002F\u002F Convert normalized tap to pixel coordinates\nlet pixelPoint = VNImagePointForNormalizedPoint(\n    CGPoint(x: normalizedX, y: normalizedY),\n    width: imageWidth,\n    height: imageHeight\n)\n\n\u002F\u002F Calculate byte offset\nlet offset = Int(pixelPoint.y) * bytesPerRow + Int(pixelPoint.x)\n\n\u002F\u002F Read instance label\nlet label = UnsafeRawPointer(baseAddress!).load(\n    fromByteOffset: offset,\n    as: UInt8.self\n)\n\nlet instances = label == 0 ? observation.allInstances : IndexSet(integer: Int(label))\n```\n\n## VisionKit Subject Lifting\n\n### ImageAnalysisInteraction (iOS)\n\n**Availability**: iOS 16+, iPadOS 16+\n\nAdds system-like subject lifting UI to views:\n\n```swift\nlet interaction = ImageAnalysisInteraction()\ninteraction.preferredInteractionTypes = .imageSubject  \u002F\u002F Or .automatic\nimageView.addInteraction(interaction)\n```\n\n**Interaction types**:\n- `.automatic`: Subject lifting + Live Text + data detectors\n- `.imageSubject`: Subject lifting only (no interactive text)\n\n### ImageAnalysisOverlayView (macOS)\n\n**Availability**: macOS 13+\n\n```swift\nlet overlayView = ImageAnalysisOverlayView()\noverlayView.preferredInteractionTypes = .imageSubject\nnsView.addSubview(overlayView)\n```\n\n### Programmatic Access\n\n#### ImageAnalyzer\n\n```swift\nlet analyzer = ImageAnalyzer()\nlet configuration = ImageAnalyzer.Configuration([.text, .visualLookUp])\n\nlet analysis = try await analyzer.analyze(image, configuration: configuration)\n```\n\n#### ImageAnalysis\n\n**subjects**: `[Subject]` - All subjects in image\n\n**highlightedSubjects**: `Set\u003CSubject>` - Currently highlighted (user long-pressed)\n\n**subject(at:)**: Async lookup of subject at normalized point (returns `nil` if none)\n\n```swift\n\u002F\u002F Get all subjects\nlet subjects = analysis.subjects\n\n\u002F\u002F Look up subject at tap\nif let subject = try await analysis.subject(at: tapPoint) {\n    \u002F\u002F Process subject\n}\n\n\u002F\u002F Change highlight state\nanalysis.highlightedSubjects = Set([subjects[0], subjects[1]])\n```\n\n#### Subject Struct\n\n**image**: `UIImage`\u002F`NSImage` - Extracted subject with transparency\n\n**bounds**: `CGRect` - Subject boundaries in image coordinates\n\n```swift\n\u002F\u002F Single subject image\nlet subjectImage = subject.image\n\n\u002F\u002F Composite multiple subjects\nlet compositeImage = try await analysis.image(for: [subject1, subject2])\n```\n\n**Out-of-process**: VisionKit analysis happens out-of-process (performance benefit, image size limited)\n\n## Person Segmentation APIs\n\n### VNGeneratePersonSegmentationRequest\n\n**Availability**: iOS 15+, macOS 12+\n\nReturns single mask containing **all people** in image:\n\n```swift\nlet request = VNGeneratePersonSegmentationRequest()\n\u002F\u002F Configure quality level if needed\ntry handler.perform([request])\n\nguard let observation = request.results?.first as? VNPixelBufferObservation else {\n    return\n}\n\nlet personMask = observation.pixelBuffer  \u002F\u002F CVPixelBuffer\n```\n\n### VNGeneratePersonInstanceMaskRequest\n\n**Availability**: iOS 17+, macOS 14+\n\nReturns **separate masks for up to 4 people**:\n\n```swift\nlet request = VNGeneratePersonInstanceMaskRequest()\ntry handler.perform([request])\n\nguard let observation = request.results?.first as? VNInstanceMaskObservation else {\n    return\n}\n\n\u002F\u002F Same InstanceMaskObservation API as foreground instance masks\nlet allPeople = observation.allInstances  \u002F\u002F Up to 4 people (1-4)\n\n\u002F\u002F Get mask for person 1\nlet person1Mask = try observation.createScaledMask(\n    for: IndexSet(integer: 1),\n    croppedToInstancesContent: false\n)\n```\n\n**Limitations**:\n- Segments up to 4 people\n- With >4 people: may miss people or combine them (typically background people)\n- Use `VNDetectFaceRectanglesRequest` to count faces if you need to handle crowded scenes\n\n## Hand Pose Detection\n\n### VNDetectHumanHandPoseRequest\n\n**Availability**: iOS 14+, macOS 11+\n\nDetects **21 hand landmarks** per hand:\n\n```swift\nlet request = VNDetectHumanHandPoseRequest()\nrequest.maximumHandCount = 2  \u002F\u002F Default: 2, increase if needed\n\nlet handler = VNImageRequestHandler(cgImage: image)\ntry handler.perform([request])\n\nfor observation in request.results as? [VNHumanHandPoseObservation] ?? [] {\n    \u002F\u002F Process each hand\n}\n```\n\n**Performance note**: `maximumHandCount` affects latency. Pose computed only for hands ≤ maximum. Set to lowest acceptable value.\n\n### Hand Landmarks (21 points)\n\n**Wrist**: 1 landmark\n\n**Thumb** (4 landmarks):\n- `.thumbTip`\n- `.thumbIP` (interphalangeal joint)\n- `.thumbMP` (metacarpophalangeal joint)\n- `.thumbCMC` (carpometacarpal joint)\n\n**Fingers** (4 landmarks each):\n- Tip (`.indexTip`, `.middleTip`, `.ringTip`, `.littleTip`)\n- DIP (distal interphalangeal joint)\n- PIP (proximal interphalangeal joint)\n- MCP (metacarpophalangeal joint)\n\n### Group Keys\n\nAccess landmark groups:\n\n| Group Key | Points |\n|-----------|--------|\n| `.all` | All 21 landmarks |\n| `.thumb` | 4 thumb joints |\n| `.indexFinger` | 4 index finger joints |\n| `.middleFinger` | 4 middle finger joints |\n| `.ringFinger` | 4 ring finger joints |\n| `.littleFinger` | 4 little finger joints |\n\n```swift\n\u002F\u002F Get all points\nlet allPoints = try observation.recognizedPoints(.all)\n\n\u002F\u002F Get index finger points only\nlet indexPoints = try observation.recognizedPoints(.indexFinger)\n\n\u002F\u002F Get specific point\nlet thumbTip = try observation.recognizedPoint(.thumbTip)\nlet indexTip = try observation.recognizedPoint(.indexTip)\n\n\u002F\u002F Check confidence\nguard thumbTip.confidence > 0.5 else { return }\n\n\u002F\u002F Access location (normalized coordinates, lower-left origin)\nlet location = thumbTip.location  \u002F\u002F CGPoint\n```\n\n### Gesture Recognition Example (Pinch)\n\n```swift\nlet thumbTip = try observation.recognizedPoint(.thumbTip)\nlet indexTip = try observation.recognizedPoint(.indexTip)\n\nguard thumbTip.confidence > 0.5, indexTip.confidence > 0.5 else {\n    return\n}\n\nlet distance = hypot(\n    thumbTip.location.x - indexTip.location.x,\n    thumbTip.location.y - indexTip.location.y\n)\n\nlet isPinching = distance \u003C 0.05  \u002F\u002F Normalized threshold\n```\n\n### Chirality (Handedness)\n\n```swift\nlet chirality = observation.chirality  \u002F\u002F .left or .right or .unknown\n```\n\n## Body Pose Detection\n\n### VNDetectHumanBodyPoseRequest (2D)\n\n**Availability**: iOS 14+, macOS 11+\n\nDetects **18 body landmarks** (2D normalized coordinates):\n\n```swift\nlet request = VNDetectHumanBodyPoseRequest()\ntry handler.perform([request])\n\nfor observation in request.results as? [VNHumanBodyPoseObservation] ?? [] {\n    \u002F\u002F Process each person\n}\n```\n\n### Body Landmarks (18 points)\n\n**Face** (5 landmarks):\n- `.nose`, `.leftEye`, `.rightEye`, `.leftEar`, `.rightEar`\n\n**Arms** (6 landmarks):\n- Left: `.leftShoulder`, `.leftElbow`, `.leftWrist`\n- Right: `.rightShoulder`, `.rightElbow`, `.rightWrist`\n\n**Torso** (7 landmarks):\n- `.neck` (between shoulders)\n- `.leftShoulder`, `.rightShoulder` (also in arm groups)\n- `.leftHip`, `.rightHip`\n- `.root` (between hips)\n\n**Legs** (6 landmarks):\n- Left: `.leftHip`, `.leftKnee`, `.leftAnkle`\n- Right: `.rightHip`, `.rightKnee`, `.rightAnkle`\n\n**Note**: Shoulders and hips appear in multiple groups\n\n### Group Keys (Body)\n\n| Group Key | Points |\n|-----------|--------|\n| `.all` | All 18 landmarks |\n| `.face` | 5 face landmarks |\n| `.leftArm` | shoulder, elbow, wrist |\n| `.rightArm` | shoulder, elbow, wrist |\n| `.torso` | neck, shoulders, hips, root |\n| `.leftLeg` | hip, knee, ankle |\n| `.rightLeg` | hip, knee, ankle |\n\n```swift\n\u002F\u002F Get all body points\nlet allPoints = try observation.recognizedPoints(.all)\n\n\u002F\u002F Get left arm only\nlet leftArmPoints = try observation.recognizedPoints(.leftArm)\n\n\u002F\u002F Get specific joint\nlet leftWrist = try observation.recognizedPoint(.leftWrist)\n```\n\n### VNDetectHumanBodyPose3DRequest (3D)\n\n**Availability**: iOS 17+, macOS 14+\n\nReturns **3D skeleton with 17 joints** in meters (real-world coordinates):\n\n```swift\nlet request = VNDetectHumanBodyPose3DRequest()\ntry handler.perform([request])\n\nguard let observation = request.results?.first as? VNHumanBodyPose3DObservation else {\n    return\n}\n\n\u002F\u002F Get 3D joint position\nlet leftWrist = try observation.recognizedPoint(.leftWrist)\nlet position = leftWrist.position  \u002F\u002F simd_float4x4 matrix\nlet localPosition = leftWrist.localPosition  \u002F\u002F Relative to parent joint\n```\n\n**3D Body Landmarks** (17 points): Same as 2D except no ears (15 vs 18 2D landmarks)\n\n#### 3D Observation Properties\n\n**bodyHeight**: Estimated height in meters\n- With depth data: Measured height\n- Without depth data: Reference height (1.8m)\n\n**heightEstimation**: `.measured` or `.reference`\n\n**cameraOriginMatrix**: `simd_float4x4` camera position\u002Forientation relative to subject\n\n**pointInImage(\\_:)**: Project 3D joint back to 2D image coordinates\n\n```swift\nlet wrist2D = try observation.pointInImage(leftWrist)\n```\n\n#### 3D Point Classes\n\n**VNPoint3D**: Base class with `simd_float4x4` position matrix\n\n**VNRecognizedPoint3D**: Adds identifier (joint name)\n\n**VNHumanBodyRecognizedPoint3D**: Adds `localPosition` and `parentJoint`\n\n```swift\n\u002F\u002F Position relative to skeleton root (center of hip)\nlet modelPosition = leftWrist.position\n\n\u002F\u002F Position relative to parent joint (left elbow)\nlet relativePosition = leftWrist.localPosition\n```\n\n#### Depth Input\n\nVision accepts depth data alongside images:\n\n```swift\n\u002F\u002F From AVDepthData\nlet handler = VNImageRequestHandler(\n    cvPixelBuffer: imageBuffer,\n    depthData: depthData,\n    orientation: orientation\n)\n\n\u002F\u002F From file (automatic depth extraction)\nlet handler = VNImageRequestHandler(url: imageURL)  \u002F\u002F Depth auto-fetched\n```\n\n**Depth formats**: Disparity or Depth (interchangeable via AVFoundation)\n\n**LiDAR**: Use in live capture sessions for accurate scale\u002Fmeasurement\n\n## Face Detection & Landmarks\n\n### VNDetectFaceRectanglesRequest\n\n**Availability**: iOS 11+\n\nDetects face bounding boxes:\n\n```swift\nlet request = VNDetectFaceRectanglesRequest()\ntry handler.perform([request])\n\nfor observation in request.results as? [VNFaceObservation] ?? [] {\n    let faceBounds = observation.boundingBox  \u002F\u002F Normalized rect\n}\n```\n\n### VNDetectFaceLandmarksRequest\n\n**Availability**: iOS 11+\n\nDetects face with detailed landmarks:\n\n```swift\nlet request = VNDetectFaceLandmarksRequest()\ntry handler.perform([request])\n\nfor observation in request.results as? [VNFaceObservation] ?? [] {\n    if let landmarks = observation.landmarks {\n        let leftEye = landmarks.leftEye\n        let nose = landmarks.nose\n        let leftPupil = landmarks.leftPupil  \u002F\u002F Revision 2+\n    }\n}\n```\n\n**Revisions**:\n- Revision 1: Basic landmarks\n- Revision 2: Detects upside-down faces\n- Revision 3+: Pupil locations\n\n## Person Detection\n\n### VNDetectHumanRectanglesRequest\n\n**Availability**: iOS 13+\n\nDetects human bounding boxes (torso detection):\n\n```swift\nlet request = VNDetectHumanRectanglesRequest()\ntry handler.perform([request])\n\nfor observation in request.results as? [VNHumanObservation] ?? [] {\n    let humanBounds = observation.boundingBox  \u002F\u002F Normalized rect\n}\n```\n\n**Use case**: Faster than pose detection when you only need location\n\n## CoreImage Integration\n\n### CIBlendWithMask Filter\n\nComposite subject on new background using Vision mask:\n\n```swift\n\u002F\u002F 1. Get mask from Vision\nlet observation = request.results?.first as? VNInstanceMaskObservation\nlet visionMask = try observation.createScaledMask(\n    for: observation.allInstances,\n    croppedToInstancesContent: false\n)\n\n\u002F\u002F 2. Convert to CIImage\nlet maskImage = CIImage(cvPixelBuffer: visionMask)\n\n\u002F\u002F 3. Apply filter\nlet filter = CIFilter(name: \"CIBlendWithMask\")!\nfilter.setValue(sourceImage, forKey: kCIInputImageKey)\nfilter.setValue(maskImage, forKey: kCIInputMaskImageKey)\nfilter.setValue(newBackground, forKey: kCIInputBackgroundImageKey)\n\nlet output = filter.outputImage  \u002F\u002F Composited result\n```\n\n**Parameters**:\n- **Input image**: Original image to mask\n- **Mask image**: Vision's soft segmentation mask\n- **Background image**: New background (or empty image for transparency)\n\n**HDR preservation**: CoreImage preserves high dynamic range from input (Vision\u002FVisionKit output is SDR)\n\n## Text Recognition APIs\n\n### VNRecognizeTextRequest\n\n**Availability**: iOS 13+, macOS 10.15+\n\nRecognizes text in images with configurable accuracy\u002Fspeed trade-off.\n\n#### Basic Usage\n\n```swift\nlet request = VNRecognizeTextRequest()\nrequest.recognitionLevel = .accurate  \u002F\u002F Or .fast\nrequest.recognitionLanguages = [\"en-US\", \"de-DE\"]  \u002F\u002F Order matters\nrequest.usesLanguageCorrection = true\n\nlet handler = VNImageRequestHandler(cgImage: image)\ntry handler.perform([request])\n\nfor observation in request.results as? [VNRecognizedTextObservation] ?? [] {\n    \u002F\u002F Get top candidates\n    let candidates = observation.topCandidates(3)\n    let bestText = candidates.first?.string ?? \"\"\n}\n```\n\n#### Recognition Levels\n\n| Level | Performance | Accuracy | Best For |\n|-------|-------------|----------|----------|\n| `.fast` | Real-time | Good | Camera feed, large text, signs |\n| `.accurate` | Slower | Excellent | Documents, receipts, handwriting |\n\n**Fast path**: Character-by-character recognition (Neural Network → Character Detection)\n\n**Accurate path**: Full-line ML recognition (Neural Network → Line\u002FWord Recognition)\n\n#### Properties\n\n| Property | Type | Description |\n|----------|------|-------------|\n| `recognitionLevel` | `VNRequestTextRecognitionLevel` | `.fast` or `.accurate` |\n| `recognitionLanguages` | `[String]` | BCP 47 language codes, order = priority |\n| `usesLanguageCorrection` | `Bool` | Use language model for correction |\n| `customWords` | `[String]` | Domain-specific vocabulary |\n| `automaticallyDetectsLanguage` | `Bool` | Auto-detect language (iOS 16+) |\n| `minimumTextHeight` | `Float` | Min text height as fraction of image (0-1) |\n| `revision` | `Int` | API version (affects supported languages) |\n\n#### Language Support\n\n```swift\n\u002F\u002F Check supported languages for current settings\nlet languages = try VNRecognizeTextRequest.supportedRecognitionLanguages(\n    for: .accurate,\n    revision: VNRecognizeTextRequestRevision3\n)\n```\n\n**Language correction**: Improves accuracy but takes processing time. Disable for codes\u002Fserial numbers.\n\n**Custom words**: Add domain-specific vocabulary for better recognition (medical terms, product codes).\n\n#### VNRecognizedTextObservation\n\n**boundingBox**: Normalized rect containing recognized text\n\n**topCandidates(_:)**: Returns `[VNRecognizedText]` ordered by confidence\n\n#### VNRecognizedText\n\n| Property | Type | Description |\n|----------|------|-------------|\n| `string` | `String` | Recognized text |\n| `confidence` | `VNConfidence` | 0.0-1.0 |\n| `boundingBox(for:)` | `VNRectangleObservation?` | Box for substring range |\n\n```swift\n\u002F\u002F Get bounding box for substring\nlet text = candidate.string\nif let range = text.range(of: \"invoice\") {\n    let box = try candidate.boundingBox(for: range)\n}\n```\n\n## Barcode Detection APIs\n\n### VNDetectBarcodesRequest\n\n**Availability**: iOS 11+, macOS 10.13+\n\nDetects and decodes barcodes and QR codes.\n\n#### Basic Usage\n\n```swift\nlet request = VNDetectBarcodesRequest()\nrequest.symbologies = [.qr, .ean13, .code128]  \u002F\u002F Specific codes\n\nlet handler = VNImageRequestHandler(cgImage: image)\ntry handler.perform([request])\n\nfor barcode in request.results as? [VNBarcodeObservation] ?? [] {\n    let payload = barcode.payloadStringValue\n    let type = barcode.symbology\n    let bounds = barcode.boundingBox\n}\n```\n\n#### Symbologies\n\n**1D Barcodes**:\n- `.codabar` (iOS 15+)\n- `.code39`, `.code39Checksum`, `.code39FullASCII`, `.code39FullASCIIChecksum`\n- `.code93`, `.code93i`\n- `.code128`\n- `.ean8`, `.ean13`\n- `.gs1DataBar`, `.gs1DataBarExpanded`, `.gs1DataBarLimited` (iOS 15+)\n- `.i2of5`, `.i2of5Checksum`\n- `.itf14`\n- `.upce`\n\n**2D Codes**:\n- `.aztec`\n- `.dataMatrix`\n- `.microPDF417` (iOS 15+)\n- `.microQR` (iOS 15+)\n- `.pdf417`\n- `.qr`\n\n**Performance**: Specifying fewer symbologies = faster detection\n\n#### Revisions\n\n| Revision | iOS | Features |\n|----------|-----|----------|\n| 1 | 11+ | Basic detection, one code at a time |\n| 2 | 15+ | Codabar, GS1, MicroPDF, MicroQR, better ROI |\n| 3 | 16+ | ML-based, multiple codes, better bounding boxes |\n\n#### VNBarcodeObservation\n\n| Property | Type | Description |\n|----------|------|-------------|\n| `payloadStringValue` | `String?` | Decoded content |\n| `symbology` | `VNBarcodeSymbology` | Barcode type |\n| `boundingBox` | `CGRect` | Normalized bounds |\n| `topLeft\u002FtopRight\u002FbottomLeft\u002FbottomRight` | `CGPoint` | Corner points |\n\n## VisionKit Scanner APIs\n\n### DataScannerViewController\n\n**Availability**: iOS 16+\n\nCamera-based live scanner with built-in UI for text and barcodes.\n\n#### Check Availability\n\n```swift\n\u002F\u002F Hardware support\nDataScannerViewController.isSupported\n\n\u002F\u002F Runtime availability (camera access, parental controls)\nDataScannerViewController.isAvailable\n```\n\n#### Configuration\n\n```swift\nimport VisionKit\n\nlet dataTypes: Set\u003CDataScannerViewController.RecognizedDataType> = [\n    .barcode(symbologies: [.qr, .ean13]),\n    .text(textContentType: .URL),  \u002F\u002F Or nil for all text\n    \u002F\u002F .text(languages: [\"ja\"])  \u002F\u002F Filter by language\n]\n\nlet scanner = DataScannerViewController(\n    recognizedDataTypes: dataTypes,\n    qualityLevel: .balanced,  \u002F\u002F .fast, .balanced, .accurate\n    recognizesMultipleItems: true,\n    isHighFrameRateTrackingEnabled: true,\n    isPinchToZoomEnabled: true,\n    isGuidanceEnabled: true,\n    isHighlightingEnabled: true\n)\n\nscanner.delegate = self\npresent(scanner, animated: true) {\n    try? scanner.startScanning()\n}\n```\n\n#### RecognizedDataType\n\n| Type | Description |\n|------|-------------|\n| `.barcode(symbologies:)` | Specific barcode types |\n| `.text()` | All text |\n| `.text(languages:)` | Text filtered by language |\n| `.text(textContentType:)` | Text filtered by type (URL, phone, email) |\n\n#### Delegate Protocol\n\n```swift\nprotocol DataScannerViewControllerDelegate {\n    func dataScanner(_ dataScanner: DataScannerViewController,\n                     didTapOn item: RecognizedItem)\n\n    func dataScanner(_ dataScanner: DataScannerViewController,\n                     didAdd addedItems: [RecognizedItem],\n                     allItems: [RecognizedItem])\n\n    func dataScanner(_ dataScanner: DataScannerViewController,\n                     didUpdate updatedItems: [RecognizedItem],\n                     allItems: [RecognizedItem])\n\n    func dataScanner(_ dataScanner: DataScannerViewController,\n                     didRemove removedItems: [RecognizedItem],\n                     allItems: [RecognizedItem])\n\n    func dataScanner(_ dataScanner: DataScannerViewController,\n                     becameUnavailableWithError error: DataScannerViewController.ScanningUnavailable)\n}\n```\n\n#### RecognizedItem\n\n```swift\nenum RecognizedItem {\n    case text(RecognizedItem.Text)\n    case barcode(RecognizedItem.Barcode)\n\n    var id: UUID { get }\n    var bounds: RecognizedItem.Bounds { get }\n}\n\n\u002F\u002F Text item\nstruct Text {\n    let transcript: String\n}\n\n\u002F\u002F Barcode item\nstruct Barcode {\n    let payloadStringValue: String?\n    let observation: VNBarcodeObservation\n}\n```\n\n#### Async Stream\n\n```swift\n\u002F\u002F Alternative to delegate\nfor await items in scanner.recognizedItems {\n    \u002F\u002F Current recognized items\n}\n```\n\n#### Custom Highlights\n\n```swift\n\u002F\u002F Add custom views over recognized items\nscanner.overlayContainerView.addSubview(customHighlight)\n\n\u002F\u002F Capture still photo\nlet photo = try await scanner.capturePhoto()\n```\n\n### VNDocumentCameraViewController\n\n**Availability**: iOS 13+\n\nDocument scanning with automatic edge detection, perspective correction, and lighting adjustment.\n\n#### Basic Usage\n\n```swift\nimport VisionKit\n\nlet camera = VNDocumentCameraViewController()\ncamera.delegate = self\npresent(camera, animated: true)\n```\n\n#### Delegate Protocol\n\n```swift\nprotocol VNDocumentCameraViewControllerDelegate {\n    func documentCameraViewController(_ controller: VNDocumentCameraViewController,\n                                       didFinishWith scan: VNDocumentCameraScan)\n\n    func documentCameraViewControllerDidCancel(_ controller: VNDocumentCameraViewController)\n\n    func documentCameraViewController(_ controller: VNDocumentCameraViewController,\n                                       didFailWithError error: Error)\n}\n```\n\n#### VNDocumentCameraScan\n\n| Property | Type | Description |\n|----------|------|-------------|\n| `pageCount` | `Int` | Number of scanned pages |\n| `imageOfPage(at:)` | `UIImage` | Get page image at index |\n| `title` | `String` | User-editable title |\n\n```swift\nfunc documentCameraViewController(_ controller: VNDocumentCameraViewController,\n                                   didFinishWith scan: VNDocumentCameraScan) {\n    controller.dismiss(animated: true)\n\n    for i in 0..\u003Cscan.pageCount {\n        let pageImage = scan.imageOfPage(at: i)\n        \u002F\u002F Process with VNRecognizeTextRequest\n    }\n}\n```\n\n## Document Analysis APIs\n\n### VNDetectDocumentSegmentationRequest\n\n**Availability**: iOS 15+, macOS 12+\n\nDetects document boundaries for custom camera UIs or post-processing.\n\n```swift\nlet request = VNDetectDocumentSegmentationRequest()\nlet handler = VNImageRequestHandler(ciImage: image)\ntry handler.perform([request])\n\nguard let observation = request.results?.first as? VNRectangleObservation else {\n    return  \u002F\u002F No document found\n}\n\n\u002F\u002F Get corner points (normalized)\nlet corners = [\n    observation.topLeft,\n    observation.topRight,\n    observation.bottomLeft,\n    observation.bottomRight\n]\n```\n\n**vs VNDetectRectanglesRequest**:\n- Document: ML-based, trained specifically on documents\n- Rectangle: Edge-based, finds any quadrilateral\n\n### RecognizeDocumentsRequest (iOS 26+)\n\n**Availability**: iOS 26+, macOS 26+\n\nStructured document understanding with semantic parsing.\n\n#### Basic Usage\n\n```swift\nlet request = RecognizeDocumentsRequest()\nlet observations = try await request.perform(on: imageData)\n\nguard let document = observations.first?.document else {\n    return\n}\n```\n\n#### DocumentObservation Hierarchy\n\n```\nDocumentObservation\n└── document: DocumentObservation.Document\n    ├── text: TextObservation\n    ├── tables: [Container.Table]\n    ├── lists: [Container.List]\n    └── barcodes: [Container.Barcode]\n```\n\n#### Table Extraction\n\n```swift\nfor table in document.tables {\n    for row in table.rows {\n        for cell in row {\n            let text = cell.content.text.transcript\n            let detectedData = cell.content.text.detectedData\n        }\n    }\n}\n```\n\n#### Detected Data Types\n\n```swift\nfor data in document.text.detectedData {\n    switch data.match.details {\n    case .emailAddress(let email):\n        let address = email.emailAddress\n    case .phoneNumber(let phone):\n        let number = phone.phoneNumber\n    case .link(let url):\n        let link = url\n    case .address(let address):\n        let components = address\n    case .date(let date):\n        let dateValue = date\n    default:\n        break\n    }\n}\n```\n\n#### TextObservation Hierarchy\n\n```\nTextObservation\n├── transcript: String\n├── lines: [TextObservation.Line]\n├── paragraphs: [TextObservation.Paragraph]\n├── words: [TextObservation.Word]\n└── detectedData: [DetectedDataObservation]\n```\n\n## Visual Intelligence Integration\n\nVisual Intelligence is a **system-level feature** (iOS 26+) that lets users point their camera at real-world objects and find matching content across apps. This is distinct from the Vision framework (VNRequest-based image analysis) covered above. Vision analyzes images within your app; Visual Intelligence lets the system invoke your app when users search with the camera or screenshots.\n\n### How It Works\n\n1. User activates Visual Intelligence camera or takes a screenshot\n2. System analyzes what the user is looking at\n3. System queries participating apps via `IntentValueQuery`\n4. Your app receives a `SemanticContentDescriptor` with labels and\u002For pixel data\n5. Your app searches its content and returns matching `AppEntity` results\n6. Results appear in the Visual Intelligence UI with your app's branding\n\n### Required Frameworks\n\n```swift\nimport VisualIntelligence\nimport AppIntents\n```\n\n### SemanticContentDescriptor\n\nThe core object the system provides to describe what the user is looking at.\n\n| Property | Type | Description |\n|----------|------|-------------|\n| `labels` | `[String]` | Classification labels for the detected item |\n| `pixelBuffer` | `CVReadOnlyPixelBuffer?` | Visual data of the detected item |\n\nUse labels for fast keyword matching against your content catalog. Use the pixel buffer for image-similarity search when labels are insufficient.\n\n### IntentValueQuery\n\nThe entry point for Visual Intelligence to communicate with your app. Implement `values(for:)` to receive search requests and return matching entities.\n\n```swift\nstruct LandmarkIntentValueQuery: IntentValueQuery {\n    @Dependency var modelData: ModelData\n\n    func values(for input: SemanticContentDescriptor) async throws -> [LandmarkEntity] {\n        if !input.labels.isEmpty {\n            return try await modelData.search(matching: input.labels)\n        }\n        guard let pixelBuffer = input.pixelBuffer else { return [] }\n        return try await modelData.search(matching: pixelBuffer)\n    }\n}\n```\n\n### Returning Multiple Result Types\n\nUse `@UnionValue` when your app can return different entity types from a single search.\n\n```swift\n@UnionValue\nenum VisualSearchResult {\n    case landmark(LandmarkEntity)\n    case collection(CollectionEntity)\n}\n```\n\n### Display Representation\n\nVisual Intelligence uses your entity's `DisplayRepresentation` to show results. Provide a title, subtitle, and image for each result.\n\n```swift\nstruct LandmarkEntity: AppEntity {\n    var id: String\n    var name: String\n    var location: String\n\n    static var typeDisplayRepresentation: TypeDisplayRepresentation {\n        TypeDisplayRepresentation(\n            name: LocalizedStringResource(\"Landmark\", table: \"AppIntents\"),\n            numericFormat: \"\\(placeholder: .int) landmarks\"\n        )\n    }\n\n    var displayRepresentation: DisplayRepresentation {\n        DisplayRepresentation(\n            title: \"\\(name)\",\n            subtitle: \"\\(location)\",\n            image: .init(named: thumbnailImageName)\n        )\n    }\n}\n```\n\n### Deep Linking from Results\n\nWhen a user taps a result, your app should open to the relevant content. Provide an `appLinkURL` on your entity.\n\n```swift\nvar appLinkURL: URL? {\n    URL(string: \"yourapp:\u002F\u002Flandmark\u002F\\(id)\")\n}\n```\n\n### \"More Results\" Intent\n\nFor large result sets, provide a `VisualIntelligenceSearchIntent` that opens your app's full search UI.\n\n```swift\nstruct ViewMoreLandmarksIntent: AppIntent, VisualIntelligenceSearchIntent {\n    static var title: LocalizedStringResource = \"View More Landmarks\"\n\n    @Parameter(title: \"Semantic Content\")\n    var semanticContent: SemanticContentDescriptor\n\n    func perform() async throws -> some IntentResult {\n        \u002F\u002F Open your app's search view with the semantic content\n        return .result()\n    }\n}\n```\n\n### Best Practices\n\n- **Return results quickly** — Visual Intelligence expects low-latency responses. Limit to 10-20 most relevant results\n- **Prefer labels first** — Label matching is faster than pixel buffer analysis. Fall back to pixel buffer when labels are empty or insufficient\n- **Localize everything** — Display representations appear in the system UI. Use `LocalizedStringResource` for all user-facing text\n- **Include images** — Results with thumbnails are more recognizable in the Visual Intelligence overlay\n\n### Testing\n\n1. Build and run on a physical device\n2. Activate Visual Intelligence camera or take a screenshot of relevant content\n3. Perform a visual search and verify your app's results appear\n4. Tap results to verify deep linking opens the correct content\n\n## API Quick Reference\n\n### Subject Segmentation\n\n| API | Platform | Purpose |\n|-----|----------|---------|\n| `VNGenerateForegroundInstanceMaskRequest` | iOS 17+ | Class-agnostic subject instances |\n| `VNGeneratePersonInstanceMaskRequest` | iOS 17+ | Up to 4 people separately |\n| `VNGeneratePersonSegmentationRequest` | iOS 15+ | All people (single mask) |\n| `ImageAnalysisInteraction` (VisionKit) | iOS 16+ | UI for subject lifting |\n\n### Pose Detection\n\n| API | Platform | Landmarks | Coordinates |\n|-----|----------|-----------|-------------|\n| `VNDetectHumanHandPoseRequest` | iOS 14+ | 21 per hand | 2D normalized |\n| `VNDetectHumanBodyPoseRequest` | iOS 14+ | 18 body joints | 2D normalized |\n| `VNDetectHumanBodyPose3DRequest` | iOS 17+ | 17 body joints | 3D meters |\n\n### Face & Person Detection\n\n| API | Platform | Purpose |\n|-----|----------|---------|\n| `VNDetectFaceRectanglesRequest` | iOS 11+ | Face bounding boxes |\n| `VNDetectFaceLandmarksRequest` | iOS 11+ | Face with detailed landmarks |\n| `VNDetectHumanRectanglesRequest` | iOS 13+ | Human torso bounding boxes |\n\n### Text & Barcode\n\n| API | Platform | Purpose |\n|-----|----------|---------|\n| `VNRecognizeTextRequest` | iOS 13+ | Text recognition (OCR) |\n| `VNDetectBarcodesRequest` | iOS 11+ | Barcode\u002FQR detection |\n| `DataScannerViewController` | iOS 16+ | Live camera scanner (text + barcodes) |\n| `VNDocumentCameraViewController` | iOS 13+ | Document scanning with perspective correction |\n| `VNDetectDocumentSegmentationRequest` | iOS 15+ | Programmatic document edge detection |\n| `RecognizeDocumentsRequest` | iOS 26+ | Structured document extraction |\n\n### Visual Intelligence\n\n| API | Platform | Purpose |\n|-----|----------|---------|\n| `SemanticContentDescriptor` | iOS 26+ | Describes what the user is looking at (labels + pixel buffer) |\n| `IntentValueQuery` | iOS 26+ | Entry point for receiving visual search requests |\n| `VisualIntelligenceSearchIntent` | iOS 26+ | \"More results\" deep link to your app |\n\n### Observation Types\n\n| Observation | Returned By |\n|-------------|-------------|\n| `VNInstanceMaskObservation` | Foreground\u002Fperson instance masks |\n| `VNPixelBufferObservation` | Person segmentation (single mask) |\n| `VNHumanHandPoseObservation` | Hand pose |\n| `VNHumanBodyPoseObservation` | Body pose (2D) |\n| `VNHumanBodyPose3DObservation` | Body pose (3D) |\n| `VNFaceObservation` | Face detection\u002Flandmarks |\n| `VNHumanObservation` | Human rectangles |\n| `VNRecognizedTextObservation` | Text recognition |\n| `VNBarcodeObservation` | Barcode detection |\n| `VNRectangleObservation` | Document segmentation |\n| `DocumentObservation` | Structured document (iOS 26+) |\n\n## Resources\n\n**WWDC**: 2019-234, 2021-10041, 2022-10024, 2022-10025, 2025-272, 2023-10176, 2023-111241, 2023-10048, 2020-10653, 2020-10043, 2020-10099\n\n**Docs**: \u002Fvision, \u002Fvisionkit, \u002Fvisualintelligence, \u002Fvisualintelligence\u002Fsemanticcontentdescriptor, \u002Fvision\u002Fvnrecognizetextrequest, \u002Fvision\u002Fvndetectbarcodesrequest\n\n**Skills**: axiom-vision, axiom-vision-diag\n\n",{"name":5,"license":15,"metadata":47,"description":7,"compatibility":50},{"version":48,"last-updated":49},"1.1.0","2026-01-03","iOS 11+, iPadOS 11+, macOS 10.13+, tvOS 11+, visionOS 1+","main","def8531e65114c0fca8fb8551c1871ee0eed705c","skills\u002FCharlesWiltgen\u002FAxiom\u002Faxiom-vision-ref",24,"https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub","https:\u002F\u002Fskillshub.wtf","https:\u002F\u002Fgithub.com\u002FComeOnOliver","AI & Blockchain Engineer\r\n","2026-06-24 22:07:19",{"source":8,"skillName":5,"commands":61,"prompt":71,"zipAvailable":72},[62,65,68],{"tool":63,"command":64},"npx","npx skills add ComeOnOliver\u002Fskillshub --skill axiom-vision-ref",{"tool":66,"command":67},"bunx","bunx skills add ComeOnOliver\u002Fskillshub --skill axiom-vision-ref",{"tool":69,"command":70},"pnpm","pnpm dlx skills add ComeOnOliver\u002Fskillshub --skill axiom-vision-ref","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002FCharlesWiltgen\u002FAxiom\u002Faxiom-vision-ref\u002FSKILL.md",true,[74,80,84,88],{"path":75,"resourceType":76,"resourceTypeDesc":77,"sizeBytes":78,"sourceHtmlUrl":79},"scripts\u002Fedit.ts","SCRIPT","脚本",2443,"https:\u002F\u002Fgithub.com\u002Fclawdsolana\u002FOpenClawd\u002Fblob\u002Fmain\u002Fopen-router-skills\u002Fopenrouter-images\u002Fscripts\u002Fedit.ts",{"path":81,"resourceType":76,"resourceTypeDesc":77,"sizeBytes":82,"sourceHtmlUrl":83},"scripts\u002Fgenerate.ts",2117,"https:\u002F\u002Fgithub.com\u002Fclawdsolana\u002FOpenClawd\u002Fblob\u002Fmain\u002Fopen-router-skills\u002Fopenrouter-images\u002Fscripts\u002Fgenerate.ts",{"path":85,"resourceType":76,"resourceTypeDesc":77,"sizeBytes":86,"sourceHtmlUrl":87},"scripts\u002Flib.ts",3154,"https:\u002F\u002Fgithub.com\u002Fclawdsolana\u002FOpenClawd\u002Fblob\u002Fmain\u002Fopen-router-skills\u002Fopenrouter-images\u002Fscripts\u002Flib.ts",{"path":89,"resourceType":76,"resourceTypeDesc":77,"sizeBytes":90,"sourceHtmlUrl":91},"scripts\u002Fpackage.json",129,"https:\u002F\u002Fgithub.com\u002Fclawdsolana\u002FOpenClawd\u002Fblob\u002Fmain\u002Fopen-router-skills\u002Fopenrouter-images\u002Fscripts\u002Fpackage.json",[93,107,117,126,132,139],{"skillNo":94,"name":95,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":96,"categories":97,"keywords":103,"publishedAt":42},"01M6FKJN13GMG4KY57J3QD8GY5","model-hierarchy-skill","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzscole\u002Fmodel-hierarchy-skill\u002Fmodel-hierarchy-skill\u002FSKILL.md",[98],{"categoryNo":99,"categoryName":100,"taxonomyType":101,"taxonomyTypeDesc":102},"01JBSEEDCAT000000000000023","Skill与智能体开发","SCENARIO","使用场景",[104,105,106],"model","model hierarchy","model hierarchy skill",{"skillNo":108,"name":109,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":110,"categories":111,"keywords":113,"publishedAt":42},"01M6FKJJJ6GCAMR4PPPRD12M5X","zoom-mcp","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fzoom-mcp\u002FSKILL.md",[112],{"categoryNo":99,"categoryName":100,"taxonomyType":101,"taxonomyTypeDesc":102},[114,115,116],"MCP","zoom","zoom mcp",{"skillNo":118,"name":119,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":120,"categories":121,"keywords":122,"publishedAt":42},"01M6FKJE3KYT3KPEZMEEHYKA6K","zoom-apps-sdk","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fzoom-apps-sdk\u002FSKILL.md",[],[123,124,125,115],"sdk","zoom apps sdk","apps",{"skillNo":127,"name":128,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":129,"categories":130,"keywords":131,"publishedAt":42},"01M6FKJ9EDH9Q5VWDF8HAJRSP0","windows","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fwindows\u002FSKILL.md",[],[128],{"skillNo":133,"name":134,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":135,"categories":136,"keywords":138,"publishedAt":42},"01M6FKJ666BEEFC3AE9GJ72Q93","whiteboard","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fwhiteboard\u002FSKILL.md",[137],{"categoryNo":99,"categoryName":100,"taxonomyType":101,"taxonomyTypeDesc":102},[134],{"skillNo":140,"name":141,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":142,"categories":143,"keywords":144,"publishedAt":42},"01M6FKJ21WFCDGTJQ2Q91T9DVW","websockets","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fwebsockets\u002FSKILL.md",[],[141]]