Source code for cv3.io

"""Input/Output operations for image handling.

This module provides functions and classes for reading, writing, and displaying images
with automatic color space conversion and enhanced error handling.

Functions:
    is_ascii: Check if a string contains only ASCII characters.
    imdecode: Decode an image from a buffer.
    imread: Read an image from a file.
    imwrite: Write an image to a file.
    imshow: Display an image in a window.
    wait_key: Wait for a keyboard event.
    destroy_windows: Destroy all windows.
    destroy_window: Destroy a specific window.

Classes:
    Window: Manage a single display window.
    Windows: Manage multiple display windows.
"""
from itertools import cycle
from pathlib import Path
import warnings
import cv2
import numpy as np

from .color_spaces import rgb, rgba
from . import opt
from ._private._utils import typeit, type_decorator
from ._private._io import _imread_flag_match, _is_ascii

__all__ = [
    'imread',
    'imdecode',
    'imwrite',
    'imshow',
    'Window',
    'Windows',
    'wait_key', 'waitKey',
    'destroy_windows', 'destroyAllWindows',
    'destroy_window', 'destroyWindow'
]


[docs] def is_ascii(s): """Check if a string contains only ASCII characters. Args: s (str): String to check. Returns: bool: True if all characters in the string are ASCII, False otherwise. """ return _is_ascii(s)
[docs] def imdecode(buf, flag): """Decode an image from a buffer. Args: buf (numpy.ndarray): Buffer containing the image data. flag (int or str): Flag specifying the color type of the decoded image. Can be one of: 'color', 'gray', 'alpha', 'unchanged' or OpenCV flags. Returns: numpy.ndarray: Decoded image. Example: >>> import cv3 >>> import numpy as np >>> # Read image file as bytes >>> with open('image.jpg', 'rb') as f: ... buf = np.frombuffer(f.read(), dtype=np.uint8) >>> # Decode image >>> img = cv3.imdecode(buf, 'color') """ if isinstance(flag, str): flag = _imread_flag_match(flag) img = cv2.imdecode(buf, flag) return img
[docs] def imread(img_path, flag=cv2.IMREAD_COLOR): """Read an image from a file. Args: img_path (str or Path): Path to the image file. flag (int or str, optional): Flag specifying the color type of the loaded image. Can be one of: 'color', 'gray', 'alpha', 'unchanged' or OpenCV flags. Defaults to cv2.IMREAD_COLOR. Returns: numpy.ndarray: Loaded image. Raises: IsADirectoryError: If img_path is a directory. FileNotFoundError: If img_path does not exist. OSError: If the image file cannot be read. Note: This function automatically handles RGB/BGR color space conversion based on the opt.RGB setting. When opt.RGB is True (default), the image is converted from BGR to RGB. Example: >>> import cv3 >>> # Read a color image >>> img = cv3.imread('image.jpg') >>> # Read a grayscale image >>> img = cv3.imread('image.jpg', 'gray') >>> # Read an image with alpha channel >>> img = cv3.imread('image.png', 'unchanged') """ if Path(img_path).is_dir(): raise IsADirectoryError(str(img_path)) if not Path(img_path).is_file(): raise FileNotFoundError(str(img_path)) if isinstance(img_path, Path): img_path = str(img_path) if isinstance(flag, str): flag = _imread_flag_match(flag) img = cv2.imread(img_path, flag) if img is None: if not _is_ascii(img_path): img = cv2.imdecode(np.fromfile(img_path, dtype=np.uint8), flag) if img is None: raise OSError('File was not read: {}'.format(img_path)) if img.ndim == 2: return img if opt.RGB: if img.shape[-1] == 4: img = rgba(img) else: img = rgb(img) return img
[docs] def imwrite(img_path, img, mkdir=False, ascii=True): """Write an image to a file. Args: img_path (str or Path): Path to the image file to write. img (numpy.ndarray): Image to write. mkdir (bool, optional): If True, create parent directories if they don't exist. Defaults to False. ascii (bool, optional): If True, use ASCII filename handling. If False, use non-ASCII filename handling with numpy's tofile method. Defaults to True. Raises: OSError: If the image cannot be written to the file. Note: This function automatically handles RGB/BGR color space conversion based on the opt.RGB setting. When opt.RGB is True (default), the image is converted from RGB to BGR before writing. When ascii=False, the function uses numpy's tofile method to handle non-ASCII filenames, which is useful for international characters in filenames. Example: >>> import cv3 >>> import numpy as np >>> # Create a simple image >>> img = np.zeros((100, 100, 3), dtype=np.uint8) >>> img[:, :] = [255, 0, 0] # Blue image (BGR) >>> # Write image to file >>> cv3.imwrite('output.jpg', img) >>> # Write image with automatic directory creation >>> cv3.imwrite('output_dir/output.jpg', img, mkdir=True) """ if mkdir: Path(img_path).parent.mkdir(parents=True, exist_ok=True) if isinstance(img_path, Path): img_path = str(img_path) if opt.RGB: img = rgb(img) # includes typeit else: img = typeit(img) if not ascii: # if is_ascii(img_path): # warnings.warn('Passed ascii filename but `ascii`=True') ext = Path(img_path).suffix ret2, buf = cv2.imencode(ext=ext, img=img) if not ret2: raise OSError('Something went wrong when writing image (non-ascii filename)') buf.tofile(img_path) return ret = cv2.imwrite(img_path, img) if not ret: raise OSError('Something went wrong when writing image')
[docs] def imshow(window_name, img): """Display an image in a window. Args: window_name (str): Name of the window to display the image in. img (numpy.ndarray): Image to display. Note: This function automatically handles RGB/BGR color space conversion based on the opt.RGB setting. When opt.RGB is True (default), the image is converted from RGB to BGR before displaying. Example: >>> import cv3 >>> import numpy as np >>> # Create a simple image >>> img = np.zeros((100, 100, 3), dtype=np.uint8) >>> img[:, :] = [255, 0, 0] # Blue image (BGR) >>> # Display the image >>> cv3.imshow('My Image', img) >>> cv3.waitKey(0) """ if opt.RGB: img = rgb(img) else: img = typeit(img) cv2.imshow(window_name, img)
[docs] def wait_key(t): """Wait for a keyboard event. Args: t (int): Delay in milliseconds. If 0, it waits indefinitely for a key stroke. Returns: int: The code of the pressed key, or -1 if no key was pressed before the timeout. Note: This function is a wrapper around cv2.waitKey() that masks the return value with 0xFF to ensure consistent behavior across different platforms. Example: >>> import cv3 >>> # Wait for a key press for 1 second >>> key = cv3.wait_key(1000) >>> if key != -1: ... print(f'Key pressed: {key}') """ return cv2.waitKey(t) & 0xFF
[docs] class Window: """A class to manage a single display window. This class provides a convenient way to create and manage OpenCV windows with additional features like automatic naming and context manager support. Attributes: window_name (str): The name of the window. """ __window_count = 0
[docs] def __init__(self, window_name=None, pos=None, flag=cv2.WINDOW_AUTOSIZE): """Initialize a Window object. Args: window_name (str, optional): Name of the window. If None, a name will be automatically generated. Defaults to None. pos (tuple, optional): Starting position of the window as (x, y). Defaults to None. flag (int, optional): Window flag. Defaults to cv2.WINDOW_AUTOSIZE. Example: >>> import cv3 >>> import numpy as np >>> # Create a window with automatic naming >>> window = cv3.Window() >>> # Create a window with a specific name and position >>> window = cv3.Window('My Window', pos=(100, 100)) """ if window_name is None: window_name = 'window{}'.format(Window.__window_count) window_name = str(window_name) cv2.namedWindow(window_name, flag) if pos is not None: cv2.moveWindow(window_name, *pos) self.window_name = window_name Window.__window_count += 1
[docs] def imshow(self, img): """Display an image in this window. Args: img (numpy.ndarray): Image to display. Note: This function automatically handles RGB/BGR color space conversion based on the opt.RGB setting. When opt.RGB is True (default), the image is converted from RGB to BGR before displaying. Example: >>> import cv3 >>> import numpy as np >>> # Create a window >>> window = cv3.Window('My Window') >>> # Create an image >>> img = np.zeros((100, 100, 3), dtype=np.uint8) >>> img[:, :] = [255, 0, 0] # Blue image (BGR) >>> # Display the image >>> window.imshow(img) """ if opt.RGB: img = rgb(img) else: img = typeit(img) cv2.imshow(self.window_name, img)
[docs] def move(self, x, y): """Move the window to a new position. Args: x (int): New x-coordinate of the window. y (int): New y-coordinate of the window. Example: >>> import cv3 >>> # Create a window >>> window = cv3.Window('My Window') >>> # Move the window to position (200, 200) >>> window.move(200, 200) """ cv2.moveWindow(self.window_name, x, y)
[docs] def close(self): """Close this window and free associated resources. Example: >>> import cv3 >>> # Create a window >>> window = cv3.Window('My Window') >>> # Close the window >>> window.close() """ cv2.destroyWindow(self.window_name)
[docs] @staticmethod def wait_key(t): """Wait for a keyboard event. This is a static method that calls the module-level wait_key function. Args: t (int): Delay in milliseconds. If 0, it waits indefinitely for a key stroke. Returns: int: The code of the pressed key, or -1 if no key was pressed before the timeout. Example: >>> import cv3 >>> # Create a window >>> window = cv3.Window('My Window') >>> # Wait for a key press for 1 second >>> key = window.wait_key(1000) """ return wait_key(t)
[docs] def __enter__(self): """Enter the runtime context for the window. Returns: Window: This window instance. Example: >>> import cv3 >>> # Use window as a context manager >>> with cv3.Window('My Window') as window: ... # Window is automatically closed when exiting the context ... pass """ return self
[docs] def __exit__(self, exc_type, exc_val, exc_tb): """Exit the runtime context for the window. This method ensures the window is closed when exiting the context manager. """ self.close()
[docs] class Windows: """A class to manage multiple display windows. This class provides a convenient way to create and manage multiple OpenCV windows with additional features like context manager support. Attributes: windows (dict): A dictionary mapping window names to Window objects. """
[docs] def __init__(self, window_names, poses=None): """Initialize a Windows object. Args: window_names (list): List of window names. poses (list, optional): List of positions for each window as (x, y) tuples. If None, windows will use default positions. Defaults to None. Example: >>> import cv3 >>> # Create multiple windows >>> windows = cv3.Windows(['Window1', 'Window2']) >>> # Create multiple windows with specific positions >>> windows = cv3.Windows(['Window1', 'Window2'], poses=[(100, 100), (200, 200)]) """ if poses is None: poses = (None,) * len(window_names) self.windows = {} for window_name, pos in zip(window_names, poses): self.windows[window_name] = Window(window_name, pos=pos)
[docs] def __getitem__(self, name): """Get a specific window by name. Args: name (str): Name of the window to retrieve. Returns: Window: The requested window object. Example: >>> import cv3 >>> # Create multiple windows >>> windows = cv3.Windows(['Window1', 'Window2']) >>> # Access a specific window >>> window1 = windows['Window1'] """ return self.windows[name]
[docs] def close(self): """Close all windows and free associated resources. Example: >>> import cv3 >>> # Create multiple windows >>> windows = cv3.Windows(['Window1', 'Window2']) >>> # Close all windows >>> windows.close() """ for window_name in self.windows: self.windows[window_name].close()
[docs] @staticmethod def wait_key(t): """Wait for a keyboard event. This is a static method that calls the module-level wait_key function. Args: t (int): Delay in milliseconds. If 0, it waits indefinitely for a key stroke. Returns: int: The code of the pressed key, or -1 if no key was pressed before the timeout. Example: >>> import cv3 >>> # Create multiple windows >>> windows = cv3.Windows(['Window1', 'Window2']) >>> # Wait for a key press for 1 second >>> key = windows.wait_key(1000) """ return wait_key(t)
[docs] def __enter__(self): """Enter the runtime context for the windows. Returns: Windows: This windows instance. Example: >>> import cv3 >>> # Use windows as a context manager >>> with cv3.Windows(['Window1', 'Window2']) as windows: ... # All windows are automatically closed when exiting the context ... pass """ return self
[docs] def __exit__(self, exc_type, exc_val, exc_tb): """Exit the runtime context for the windows. This method ensures all windows are closed when exiting the context manager. """ self.close()
[docs] def destroy_windows(): """Destroy all windows. This function destroys all windows that were created with imshow or Window. Note: This is a wrapper around cv2.destroyAllWindows(). Example: >>> import cv3 >>> # Create and display an image >>> import numpy as np >>> img = np.zeros((100, 100, 3), dtype=np.uint8) >>> cv3.imshow('Window1', img) >>> cv3.imshow('Window2', img) >>> # Destroy all windows >>> cv3.destroy_windows() """ cv2.destroyAllWindows()
[docs] def destroy_window(winname: str): """Destroy a specific window. Args: winname (str): Name of the window to destroy. Note: This is a wrapper around cv2.destroyWindow(). Example: >>> import cv3 >>> # Create and display an image >>> import numpy as np >>> img = np.zeros((100, 100, 3), dtype=np.uint8) >>> cv3.imshow('My Window', img) >>> # Destroy the specific window >>> cv3.destroy_window('My Window') """ cv2.destroyWindow(winname)
# Aliases waitKey = wait_key """Alias for :func:`wait_key`.""" destroyAllWindows = destroy_windows """Alias for :func:`destroy_windows`.""" destroyWindow = destroy_window """Alias for :func:`destroy_window`."""