from __future__ import annotations from dataclasses import dataclass import numpy as np @dataclass(frozen=True) class BlockGrid8: """Разбиение и сборка блоков 8×8.""" @staticmethod def split(component: np.ndarray) -> np.ndarray: """Разбить 2D-компоненту на блоки (N,8,8).""" if component.ndim != 2: raise ValueError("Ожидается 2D-массив компоненты.") h, w = component.shape if h % 8 != 0 or w % 8 != 0: raise ValueError("Размеры должны быть кратны 8.") # Перестановка осей даёт (nH, nW, 8, 8) -> (N, 8, 8) arr = np.asarray(component) nH, nW = h // 8, w // 8 blocks = arr.reshape(nH, 8, nW, 8).transpose( 0, 2, 1, 3).reshape(nH * nW, 8, 8) return blocks @staticmethod def merge(blocks: np.ndarray, height: int, width: int) -> np.ndarray: """Собрать 2D-компоненту из блоков (N,8,8).""" if blocks.ndim != 3 or blocks.shape[1:] != (8, 8): raise ValueError("Ожидается массив блоков формы (N,8,8).") if height % 8 != 0 or width % 8 != 0: raise ValueError("Размеры должны быть кратны 8.") nH, nW = height // 8, width // 8 if blocks.shape[0] != nH * nW: raise ValueError( "Количество блоков не соответствует размеру выходной матрицы.") # Обратная перестановка из (N,8,8) -> (nH, nW, 8, 8) -> (H, W) arr = np.asarray(blocks) comp = arr.reshape(nH, nW, 8, 8).transpose( 0, 2, 1, 3).reshape(height, width) return comp