35 lines
1.5 KiB
Python
35 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 Extractor:
|
|||
|
|
"""Извлечение метки из 2D-компоненты через LSB верхней строки блоков 8×8."""
|
|||
|
|
|
|||
|
|
def extract_label(self, component: np.ndarray, seq: Sequence8) -> Label64:
|
|||
|
|
"""Вернуть Label64, восстановленную из компоненты."""
|
|||
|
|
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)
|
|||
|
|
if blocks.shape[0] != 4096:
|
|||
|
|
raise ValueError("Для метки 64x64 требуется 4096 блоков 8x8.")
|
|||
|
|
bits = np.empty(4096, dtype=np.uint8)
|
|||
|
|
s0 = seq.seq0
|
|||
|
|
s1 = seq.seq1
|
|||
|
|
# Поблочный выбор по минимальной хэмминговой дистанции
|
|||
|
|
for i, blk in enumerate(blocks):
|
|||
|
|
b = LsbRow8.extract(blk)
|
|||
|
|
d0 = np.count_nonzero(b != s0)
|
|||
|
|
d1 = np.count_nonzero(b != s1)
|
|||
|
|
bits[i] = 0 if d0 <= d1 else 1
|
|||
|
|
return Label64.from_vector(bits)
|