File size: 2,324 Bytes
7a397ad | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 | # cxr-agent/tools/encode_image.py
"""
CXR Image Encoding Tool
=======================
Prepares a CXR image for submission to the NV-Reason-CXR-3B MCP server.
Resizes to a specified maximum side length and encodes as base64 PNG.
The default of 1280px prevents garbled output from Qwen2.5-VL's smart_resize,
but the agent can pass a smaller value for faster inference or a larger value
if fine detail is required.
Data classes are defined in models/pipeline.py — none are declared here.
"""
from __future__ import annotations
import base64
import io
from pathlib import Path
from PIL import Image
DEFAULT_MAX_SIDE = 1280
def encode_image_for_reasoning(
image_path: str,
max_side: int = DEFAULT_MAX_SIDE,
) -> tuple[str, str]:
"""
Load, resize, and base64-encode a CXR image for the reasoning MCP tool.
Resizes the image so the longest side is at most max_side pixels, converts
to RGB PNG, and returns the base64 string alongside the image_id (filename
stem), ready to pass directly to reason_cxr or analyze_cxr.
Args:
image_path: Path to the image file (JPEG or PNG).
max_side: Maximum pixels on the longest side. Default 1280.
Use smaller values (e.g. 512, 768) for faster inference.
Use larger values (e.g. 1536) only if fine detail is needed
and the model version supports it.
Returns:
(image_b64, image_id) where image_b64 is a base64-encoded PNG string
and image_id is the filename stem (e.g. "cxr_demo").
Raises:
FileNotFoundError: If the image file does not exist.
ValueError: If max_side is less than 64 or greater than 2048.
"""
if not 64 <= max_side <= 2048:
raise ValueError(f"max_side must be between 64 and 2048, got {max_side}")
path = Path(image_path)
if not path.exists():
raise FileNotFoundError(f"Image not found: {image_path}")
img = Image.open(path).convert("RGB")
w, h = img.size
if max(w, h) > max_side:
scale = max_side / max(w, h)
img = img.resize((int(w * scale), int(h * scale)), Image.LANCZOS)
buf = io.BytesIO()
img.save(buf, format="PNG")
image_b64 = base64.b64encode(buf.getvalue()).decode("ascii")
image_id = path.stem
return image_b64, image_id
|