Skip to main content

gsv-ocr-check

A Python library for verifying Google Street View panorama existence and calibrating OCR bounding boxes through perspective re-projection.

Features

  • Panorama Existence Check: Verify whether a Google Street View panorama ID is still accessible
  • Panorama Download: Download panoramas to disk or into memory as PIL Images
  • OCR Bounding Box Calibration: Refine OCR coordinates by re-running OCR on perspective crops at multiple fields of view
  • Engine Agnostic: Works with any panoocr-compatible OCR engine
  • Async Support: Both sync and async APIs for panorama operations

Installation

Install the base package:

pip install gsv-ocr-check

Install with macOS OCR support:

pip install "gsv-ocr-check[macocr]"

Using uv (recommended):

uv add gsv-ocr-check
uv add "gsv-ocr-check[macocr]"

Quick Start

from gsv_ocr_check import check_panorama_exists, calibrate_ocr, download_panorama
from panoocr.engines.macocr import MacOCREngine

# 1. Check if a panorama still exists on Google Street View
exists = check_panorama_exists("abc123")

# 2. Download the panorama
image = download_panorama("abc123", output_path="pano.jpg")

# 3. Calibrate an OCR bounding box
engine = MacOCREngine()
result = calibrate_ocr(
    panorama="pano.jpg",
    target_text="LOVE",
    yaw=38.5,
    pitch=-2.4,
    engine=engine,
)

if result:
    print(f"Text: {result.text}")
    print(f"Position: yaw={result.yaw:.2f}°, pitch={result.pitch:.2f}°")
    print(f"Size: {result.width:.2f}° x {result.height:.2f}°")
    print(f"Confidence: {result.confidence}")
    print(f"FOV used: {result.fov_used}°")

API

Panorama Operations

check_panorama_exists(panorama_id) -> bool

Check if a Google Street View panorama still exists. Returns True if accessible, False otherwise.

from gsv_ocr_check import check_panorama_exists

if check_panorama_exists("UVfBLpzNhpZdImXJqozDmg"):
    print("Panorama is still available")

download_panorama(panorama_id, output_path=None, zoom=5, quality=95) -> Image | None

Download a panorama image. Returns a PIL Image, or None if the panorama is not found.

from gsv_ocr_check import download_panorama

# Download to memory only
image = download_panorama("abc123")

# Download and save to disk
image = download_panorama("abc123", output_path="panoramas/abc123.jpg")

# Download at lower resolution (zoom 0-5)
image = download_panorama("abc123", zoom=2)

Async Variants

Both functions have async counterparts for use in async contexts:

from gsv_ocr_check import check_panorama_exists_async, download_panorama_async

exists = await check_panorama_exists_async("abc123")
image = await download_panorama_async("abc123", output_path="pano.jpg")

OCR Calibration

calibrate_ocr(panorama, target_text, yaw, pitch, engine, **kwargs) -> CalibrationResult | None

Refine an OCR bounding box by generating perspective views centered on the original detection, re-running OCR, and returning the best match in spherical coordinates.

from gsv_ocr_check import calibrate_ocr
from panoocr.engines.macocr import MacOCREngine

engine = MacOCREngine()
result = calibrate_ocr(
    panorama="pano.jpg",       # path or PIL Image
    target_text="LOVE",        # exact match, case-insensitive
    yaw=38.5,                  # original detection yaw
    pitch=-2.4,                # original detection pitch
    engine=engine,             # any panoocr-compatible engine
)

Parameters:

Parameter Type Default Description
panorama str | Path | Image required Path to equirectangular panorama or PIL Image
target_text str required Text to match (exact, case-insensitive)
yaw float required Original detection yaw in degrees
pitch float required Original detection pitch in degrees
engine object required panoocr-compatible OCR engine
panorama_id str None ID for naming saved perspective files
fovs list[float] [45, 90, 120] FOVs to try in order
resolution int 2048 Perspective image resolution in pixels
save_perspectives str | Path None Directory to save perspective crops

CalibrationResult

Dataclass returned by calibrate_ocr with the refined detection:

@dataclass
class CalibrationResult:
    text: str              # Matched text
    confidence: float      # OCR confidence score
    yaw: float             # Refined yaw in degrees
    pitch: float           # Refined pitch in degrees
    width: float           # Angular width in degrees
    height: float          # Angular height in degrees
    engine: str            # OCR engine class name
    match_type: str        # "exact"
    original_yaw: float    # Input yaw (preserved)
    original_pitch: float  # Input pitch (preserved)
    fov_used: float        # FOV that produced the match
    resolution_used: int   # Resolution used

How Calibration Works

  1. Load the equirectangular panorama image
  2. Generate a perspective view centered on the original yaw/pitch coordinates
  3. Try multiple FOVs in sequence (default: 45° → 90° → 120°) — narrow FOV gives better resolution, wider FOV captures more context
  4. Run OCR on each perspective image
  5. Filter for exact text matches (case-insensitive)
  6. Select the match closest to the image center
  7. Transform pixel coordinates back to spherical using panoocr.geometry.perspective_to_sphere
  8. Return the first successful match, or None if no match at any FOV

Advanced Usage

Custom OCR Engine

Any object with a recognize(pil_image) method returning results with .text, .confidence, and .bounding_box attributes works:

from panoocr.engines.easyocr import EasyOCREngine

engine = EasyOCREngine(config={"language_preference": ["en"]})
result = calibrate_ocr("pano.jpg", "HELLO", yaw=0, pitch=0, engine=engine)

Saving Perspective Crops

Save the perspective images generated during calibration for debugging:

result = calibrate_ocr(
    panorama="pano.jpg",
    target_text="LOVE",
    yaw=38.5,
    pitch=-2.4,
    engine=engine,
    save_perspectives="debug/perspectives/",
)
# Saves: debug/perspectives/<pano_id>_fov45.jpg, etc.

Custom FOVs and Resolution

result = calibrate_ocr(
    panorama="pano.jpg",
    target_text="LOVE",
    yaw=38.5,
    pitch=-2.4,
    engine=engine,
    fovs=[30.0, 60.0, 90.0],  # custom FOV sequence
    resolution=4096,            # higher resolution perspective
)

Using PIL Images Directly

from PIL import Image

image = Image.open("pano.jpg")
result = calibrate_ocr(
    panorama=image,
    target_text="LOVE",
    yaw=38.5,
    pitch=-2.4,
    engine=engine,
    panorama_id="my_pano",  # required when passing PIL Image
)

Coordinate System

All coordinates use spherical (yaw, pitch) format:

  • Yaw: Horizontal angle in degrees, normalized to [-180, 180]
  • Pitch: Vertical angle in degrees (-90 to 90)
  • Width/Height: Angular dimensions in degrees

Dependencies

  • streetlevel — Google Street View panorama access
  • panoocr — Perspective projection, coordinate transforms, OCR engines
  • Pillow — Image handling

License

MIT License — see LICENSE for details.

Metadata

Release files for gsv-ocr-check 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for gsv-ocr-check 0.1.0
File Size Uploaded Provenance Actions
gsv_ocr_check-0.1.0.tar.gz 11.9 kB With provenance Details for gsv_ocr_check-0.1.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for gsv-ocr-check 0.1.0
File Interpreter ABI Platform Actions
gsv_ocr_check-0.1.0-py3-none-any.whl Python 3 none any Details for gsv_ocr_check-0.1.0-py3-none-any.whl

Total release size: 20.0 kB

Release files / gsv_ocr_check-0.1.0.tar.gz

Download URL gsv_ocr_check-0.1.0.tar.gz
Size 11.9 kB
Tags Source
SHA-256 checksum
How to use checksums
55e765e4ed6e1aa289d137dfb864757770ff96d83182d1680b2b2e17508a0edc
BLAKE2b-256 checksum
How to use checksums
0350a7345c0a5cdab1b2c3db382f25b12d57e0817bf7605df05839b7699d3b6d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Mar 7, 2026.

Transparency log

Release files / gsv_ocr_check-0.1.0-py3-none-any.whl

Download URL gsv_ocr_check-0.1.0-py3-none-any.whl
Size 8.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
5cb44382c6539673c841521bc1150f2a33c1fe79601d363329e8b5385b83fcef
BLAKE2b-256 checksum
How to use checksums
dfed60ebba28a6cbcd386442e4ee6c0c46b6da2bcf581d6fbb4c9354c00abc03
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Mar 7, 2026.

Transparency log

Security for gsv-ocr-check 0.1.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for gsv_ocr_check-0.1.0.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Mar 7, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files Full provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page