Utilities
Images and test pages
- manuscript.utils.read_image(img_or_path)[source]
Universal image reading with support for multiple input types.
- Parameters:
img_or_path (str, Path, bytes, np.ndarray, or PIL.Image) – Image source in one of the following formats: - File path (str or Path) - supports Unicode paths (e.g., Cyrillic) - Bytes buffer (e.g., from HTTP response) - NumPy array (already loaded image) - PIL Image object
- Returns:
RGB image as numpy array with shape (H, W, 3) and dtype uint8.
- Return type:
np.ndarray
- Raises:
FileNotFoundError – If the image file cannot be read with either OpenCV or PIL.
TypeError – If the input type is not supported.
ValueError – If bytes cannot be decoded into an image.
Examples
>>> img = read_image("path/to/image.jpg") >>> img.shape (480, 640, 3)
>>> with open("image.jpg", "rb") as f: ... img = read_image(f.read())
>>> pil_img = Image.open("image.jpg") >>> img = read_image(pil_img)
>>> img = read_image(existing_array)
- manuscript.utils.create_page_from_image(image, confidence=1.0, gap=8, return_image=False, *, region_type='word')[source]
Wrap each crop as a flat text region in the document-tree Page.
Multiple images are stacked vertically in input order on a white RGB canvas. region_type defaults to word (TRBA); use line for PPOCRRec/TrOCR line crops, or block for a cropped text block. Page dimensions and crop polygons refer to the returned canvas. Single file inputs retain file_name.
- Return type:
- Parameters:
>>> page, pixels = create_page_from_image(np.zeros((32, 100, 3), np.uint8), ... region_type="line", return_image=True) >>> page.children[0].type 'line' >>> (page.image_width, page.image_height) (100, 32)
- manuscript.utils.create_page_from_text(lines, confidence=1.0)[source]
Create a block → lines → words tree with synthetic pixel coordinates.
Accepts a list of lines or a multiline string. Whitespace splits words; empty lines reserve vertical space without creating empty text regions. Geometry is illustrative, useful for testing text processing without OCR.
>>> page = create_page_from_text(["Hello world"]) >>> page.children[0].children[0].children[0].text 'Hello'
Grouping and ordering
- manuscript.utils.group_regions(regions, *, type, geometry='bbox', concavity=0.3)[source]
Create a higher-level text parent and move existing siblings into it.
Defaults to a bounding rectangle. Other geometry modes are convex_hull, concave_hull and None. A callable receives copied polygon lists and returns a polygon or None. For concave_hull, concavity is Shapely’s ratio: 0 gives the most concave outline, 1 the convex hull (requires Shapely 2 / GEOS 3.11). Child order follows the input. The group replaces the first selected sibling in its parent’s list. Detached regions may also be grouped. All validation and geometry computation happen before any tree links change.
- Return type:
- Parameters:
Collapsing text regions
- manuscript.utils.merge_text_spans(text_spans, method='bbox', *, type='word')[source]
Merge detached text regions into one region; inputs remain unchanged.
- Return type:
- Parameters:
text_spans (Sequence[TextRegion])
Geometry
- manuscript.utils.polygon_to_bbox(polygon, image_shape=None, pad=0.0)[source]
Convert a polygon with any number of vertices to a clipped axis-aligned bounding box.
- Parameters:
- Returns:
Bounding box as
(x1, y1, x2, y2)orNoneif invalid.- Return type:
tuple or None
- manuscript.utils.crop_axis_aligned(image, polygon, pad=0.0)[source]
Crop an axis-aligned rectangle covering the polygon.
- Parameters:
image (numpy.ndarray) – Source image.
polygon (array-like of shape (N, 2)) – Polygon vertices in image coordinates.
pad (float, optional) – Extra padding in pixels around the polygon. Default is
0.
- Returns:
Image crop, or
Noneif the bounding box is invalid.- Return type:
numpy.ndarray or None
- manuscript.utils.crop_polygon_mask(image, polygon, pad=0.0, background=255)[source]
Crop the polygon bounding box and mask pixels outside the polygon.
Works with arbitrary polygons of shape
(N, 2).- Parameters:
image (numpy.ndarray) – Source image.
polygon (array-like of shape (N, 2)) – Polygon vertices in image coordinates.
pad (float, optional) – Extra padding in pixels around the polygon. Default is
0.background (int, optional) – Background pixel value outside the polygon. Default is
255.
- Returns:
Masked image crop, or
Noneif the bounding box is invalid.- Return type:
numpy.ndarray or None
- manuscript.utils.order_quad_points(points)[source]
Order exactly 4 polygon points as top-left, top-right, bottom-right, bottom-left.
- Parameters:
points (array-like of shape (4, 2)) – Quadrilateral vertices.
- Returns:
Ordered vertices as float32.
- Return type:
- Raises:
ValueError – If exactly four points are not provided.
- manuscript.utils.warp_quad(image, polygon, output_size=None, background=255)[source]
Perspective-warp a quadrilateral polygon into a rectified crop.
This helper is intentionally quad-specific. For non-quad polygons it returns
Noneso callers may choose a fallback strategy.- Parameters:
image (numpy.ndarray) – Source image.
polygon (array-like of shape (4, 2)) – Quadrilateral vertices in image coordinates.
output_size (tuple of int, optional) – Crop size
(width, height). IfNone, estimate it from polygon edges.background (int)
- Returns:
Rectified image crop, or
Nonefor an invalid quadrilateral.- Return type:
numpy.ndarray or None
- manuscript.utils.merge_polygons(polygons, method='bbox')[source]
Merge multiple polygons into a single polygon.
- Parameters:
polygons (sequence of array-like polygons) – Input polygons with shape
(N, 2).method ({"bbox", "convex_hull"}, optional) – Merge strategy.
"bbox"returns an axis-aligned rectangle covering all points."convex_hull"returns a convex hull over all points.
- Returns:
Merged polygon, or
Nonewhenpolygonsis empty.- Return type:
Visualization
- manuscript.utils.visualize_page(image, page, thickness=3, numbers_levels=(1, 2), connections_levels=(), line_color=(255, 165, 0), number_bg=(255, 255, 255), number_color=(0, 0, 0), max_size=4096, upscale=False, show_tables=True, show_cells=True, show_cell_indices=False, show_orientation=False, show_labels=False)[source]
Render hierarchy depth with alternating brightness and cold-color layers.
The background darkens by 30%. Level one restores original brightness, adding 15% per extra overlap. Even levels blend translucent cold colors, contrasting consecutive siblings. Odd levels from three onward lighten accumulated colors by 25% per overlap. Three-pixel dark contours share a color throughout each first-level subtree. numbers_levels and connections_levels select tree depths; empty lists disable their markers. Numbers default to levels one and two. Markers follow depth-first order among visible polygons at that depth. Overlap contributions are capped at two regions per depth. show_labels draws the original model label (or element type) on each region.
- Return type:
Image- Parameters:
image (str | Path | numpy.ndarray | Image)
page (Page)