Photogrammetry Pipeline

Create 3D models from photographs using the Reality Capture API.

Workflow Overview

Photo Capture
Camera/Phone
Drone
Scanner
Photo Set
20-200+ Images
RAPS Upload
Create Photoscene
Upload Photos
RC Processing
Feature Detection
Point Cloud
Mesh Generation
Texture Mapping
Outputs
OBJ Mesh
Point Cloud
Orthophoto

CLI Approach

Step 1: Create Photoscene

# Create a new photoscene for an object
SCENE=$(raps rc photoscene create --name "Product Scan" --type "object" --output json)
SCENE_ID=$(echo "$SCENE" | jq -r '.id')
echo "Created photoscene: $SCENE_ID"

Step 2: Upload Photos

# Upload all photos (minimum 20-30 recommended)
for photo in ./product-photos/*.jpg; do
  raps rc photoscene upload "$SCENE_ID" "$photo"
  echo "Uploaded: $photo"
done

# Or batch upload
raps rc photoscene upload "$SCENE_ID" ./product-photos/*.jpg --batch

Step 3: Start Processing

# Start the reconstruction
raps rc photoscene process "$SCENE_ID"

Step 4: Monitor Progress

# Check status
raps rc photoscene status "$SCENE_ID"

# Wait for completion
raps rc photoscene status "$SCENE_ID" --wait

# Or poll manually
while true; do
  STATUS=$(raps rc photoscene status "$SCENE_ID" --output json | jq -r '.status')
  PROGRESS=$(raps rc photoscene status "$SCENE_ID" --output json | jq -r '.progress // 0')

  echo "Status: $STATUS - Progress: $PROGRESS%"

  [ "$STATUS" = "done" ] && break
  [ "$STATUS" = "failed" ] && { echo "Processing failed"; exit 1; }

  sleep 30
done

Step 5: Download Results

# Download OBJ mesh
raps rc photoscene download "$SCENE_ID" --format obj --output ./output/

# Download point cloud
raps rc photoscene download "$SCENE_ID" --format rcm --output ./output/

# List available outputs
raps rc photoscene download "$SCENE_ID" --list

CI/CD Pipeline

# .github/workflows/photogrammetry.yml
name: Photogrammetry Processing

on:
  workflow_dispatch:
    inputs:
      photos_path:
        description: 'Path to photos folder'
        required: true
      scene_name:
        description: 'Name for the photoscene'
        required: true
      scene_type:
        description: 'Type (object or aerial)'
        default: 'object'

jobs:
  process-photogrammetry:
    runs-on: ubuntu-latest
    timeout-minutes: 120
    steps:
      - uses: actions/checkout@v4

      - name: Install RAPS
        run: cargo install raps

      - name: Create photoscene
        env:
          APS_CLIENT_ID: ${{ secrets.APS_CLIENT_ID }}
          APS_CLIENT_SECRET: ${{ secrets.APS_CLIENT_SECRET }}
        run: |
          SCENE=$(raps rc photoscene create \
            --name "${{ inputs.scene_name }}" \
            --type "${{ inputs.scene_type }}" \
            --output json)
          SCENE_ID=$(echo "$SCENE" | jq -r '.id')
          echo "SCENE_ID=$SCENE_ID" >> $GITHUB_ENV

      - name: Upload photos
        env:
          APS_CLIENT_ID: ${{ secrets.APS_CLIENT_ID }}
          APS_CLIENT_SECRET: ${{ secrets.APS_CLIENT_SECRET }}
        run: |
          PHOTO_COUNT=0
          for photo in ${{ inputs.photos_path }}/*.{jpg,jpeg,png}; do
            [ -f "$photo" ] || continue
            raps rc photoscene upload "$SCENE_ID" "$photo"
            PHOTO_COUNT=$((PHOTO_COUNT + 1))
            echo "Uploaded: $PHOTO_COUNT - $(basename "$photo")"
          done
          echo "Total photos: $PHOTO_COUNT"

      - name: Process photoscene
        env:
          APS_CLIENT_ID: ${{ secrets.APS_CLIENT_ID }}
          APS_CLIENT_SECRET: ${{ secrets.APS_CLIENT_SECRET }}
        run: |
          raps rc photoscene process "$SCENE_ID"

      - name: Wait for completion
        env:
          APS_CLIENT_ID: ${{ secrets.APS_CLIENT_ID }}
          APS_CLIENT_SECRET: ${{ secrets.APS_CLIENT_SECRET }}
        run: |
          MAX_WAIT=7200  # 2 hours
          ELAPSED=0

          while [ $ELAPSED -lt $MAX_WAIT ]; do
            STATUS=$(raps rc photoscene status "$SCENE_ID" --output json | jq -r '.status')
            PROGRESS=$(raps rc photoscene status "$SCENE_ID" --output json | jq -r '.progress // 0')

            echo "Status: $STATUS - Progress: $PROGRESS%"

            [ "$STATUS" = "done" ] && break
            [ "$STATUS" = "failed" ] && exit 1

            sleep 60
            ELAPSED=$((ELAPSED + 60))
          done

      - name: Download results
        env:
          APS_CLIENT_ID: ${{ secrets.APS_CLIENT_ID }}
          APS_CLIENT_SECRET: ${{ secrets.APS_CLIENT_SECRET }}
        run: |
          mkdir -p ./photogrammetry-output
          raps rc photoscene download "$SCENE_ID" --format obj --output ./photogrammetry-output/
          raps rc photoscene download "$SCENE_ID" --format rcm --output ./photogrammetry-output/

      - name: Upload results
        uses: actions/upload-artifact@v4
        with:
          name: photogrammetry-${{ inputs.scene_name }}
          path: ./photogrammetry-output/

Pipeline Flow

Manual Trigger
photos_path + name
Setup
Create Photoscene
Upload
Upload Photos
Processing
Start Processing
Wait for Completion
Output
Download OBJ
Download Point Cloud

MCP Integration

Create Scan

User: "Create a 3D model from the photos in the product-shoot folder"
User
AI Assistant
RAPS MCP
Reality Capture
UserAICreate 3D model from photos
AIMCPaps_rc_photoscene_create(name, type)
MCPRCCreate photoscene
RCMCPScene ID
AIAIFind photos in folder
loopAIMCPaps_rc_photoscene_upload(scene_id, photo)
loopMCPRCUpload
AIUser45 photos uploaded
AIMCPaps_rc_photoscene_process(scene_id)
MCPRCStart processing
loopAIMCPaps_rc_photoscene_status(scene_id)
loopMCPRCCheck status
AIMCPaps_rc_photoscene_download(scene_id, format=“obj”)
MCPAIOBJ file
AIUser3D model ready

AI Response:

Created 3D model from product photos:

Photoscene: Product Scan Photos processed: 45 Processing time: 12 minutes

Output Files:

  • product_scan.obj (12.4 MB)
  • product_scan.mtl
  • product_scan_texture.jpg (8.2 MB)

Quality Metrics:

  • Reconstruction quality: High
  • Coverage: 98%
  • Polygons: 245,000

Download ready at: ./output/product_scan.obj

Check Status

User: "What's the status of my photogrammetry job?"

AI Response:

Photoscene: Site Survey 2024-02-15

  • Status: Processing
  • Progress: 67%
  • Stage: Mesh Generation
  • Estimated time remaining: ~8 minutes

Photos: 124 / 124 processed Point cloud: 2.3 million points


Best Practices

Photo Capture Guidelines

For Objects:
- 30-100 photos from all angles
- 60-80% overlap between shots
- Consistent lighting
- Plain background

For Sites/Aerial:
- 100-500 photos
- 70%+ overlap
- Nadir (straight down) shots
- Include oblique angles

Quality Settings

# High quality (slower, more detail)
raps rc photoscene process "$SCENE_ID" --quality high

# Standard quality (balanced)
raps rc photoscene process "$SCENE_ID" --quality medium

# Draft (quick preview)
raps rc photoscene process "$SCENE_ID" --quality draft

Error Handling

# Check for failed photos
raps rc photoscene status "$SCENE_ID" --output json | jq '.failedPhotos'

# Retry with adjusted settings
raps rc photoscene cancel "$SCENE_ID"
raps rc photoscene process "$SCENE_ID" --quality medium