32 lines
1.5 KiB
Python
32 lines
1.5 KiB
Python
|
|
from __future__ import annotations
|
|||
|
|
from dataclasses import dataclass
|
|||
|
|
import numpy as np
|
|||
|
|
|
|||
|
|
from entities.block_grid8 import BlockGrid8
|
|||
|
|
from entities.lsb_row8 import LsbRow8
|
|||
|
|
from entities.label64 import Label64
|
|||
|
|
from entities.sequence8 import Sequence8
|
|||
|
|
|
|||
|
|
|
|||
|
|
@dataclass(frozen=True)
|
|||
|
|
class Embedder:
|
|||
|
|
"""Встраивание метки в 2D-компоненту Y/Cb/Cr через LSB верхней строки блоков 8×8."""
|
|||
|
|
|
|||
|
|
def embed_component(self, component: np.ndarray, label: Label64, seq: Sequence8) -> np.ndarray:
|
|||
|
|
"""Вернуть новую компоненту с вшитой меткой."""
|
|||
|
|
if component.ndim != 2:
|
|||
|
|
raise ValueError("Ожидается 2D-компонента.")
|
|||
|
|
h, w = component.shape
|
|||
|
|
if h % 8 != 0 or w % 8 != 0:
|
|||
|
|
raise ValueError("Размеры компоненты должны быть кратны 8.")
|
|||
|
|
blocks = BlockGrid8.split(component)
|
|||
|
|
bits = label.to_vector() # 4096
|
|||
|
|
if blocks.shape[0] != bits.size:
|
|||
|
|
raise ValueError("Количество блоков должно равняться 4096.")
|
|||
|
|
out_blocks = blocks.copy()
|
|||
|
|
# Для каждого бита берём 8-битную сигнатуру и встраиваем в верхнюю строку блока
|
|||
|
|
for i in range(bits.size):
|
|||
|
|
pattern = seq.for_bit(int(bits[i]))
|
|||
|
|
out_blocks[i] = LsbRow8.embed(out_blocks[i], pattern)
|
|||
|
|
return BlockGrid8.merge(out_blocks, h, w)
|