File size: 2,186 Bytes
14e9a9f | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | import json
from pathlib import Path
import numpy as np
class HapticFeatureExtractor:
def __init__(self, config):
self.config = config
self.window_size = int(config["window_size"])
self.padding_value = float(config.get("padding_value", 0.0))
self.return_attention_mask = bool(config.get("return_attention_mask", True))
normalization = config.get("normalization", {})
self.mean = np.asarray(normalization.get("mean", []), dtype=np.float32)
self.std = np.asarray(normalization.get("std", []), dtype=np.float32)
@classmethod
def from_pretrained(cls, root):
root_path = Path(root)
config_path = root_path / "preprocessor" / "preprocessor_config.json"
with config_path.open("r", encoding="utf-8") as handle:
config = json.load(handle)
return cls(config)
def _normalize(self, values):
if not self.config.get("normalize", True):
return values
if self.mean.size == 0 or self.std.size == 0:
return values
denom = np.where(self.std == 0, 1.0, self.std)
return (values - self.mean) / denom
def __call__(self, values):
values = np.asarray(values, dtype=np.float32)
if values.ndim != 2:
raise ValueError("Expected input shape [sequence_length, num_channels].")
values = self._normalize(values)
length, channels = values.shape
if length >= self.window_size:
trimmed = values[: self.window_size]
attention_mask = np.ones(self.window_size, dtype=np.int64)
else:
pad_amount = self.window_size - length
padding = np.full((pad_amount, channels), self.padding_value, dtype=np.float32)
trimmed = np.concatenate([values, padding], axis=0)
attention_mask = np.concatenate(
[
np.ones(length, dtype=np.int64),
np.zeros(pad_amount, dtype=np.int64),
]
)
result = {"input_values": trimmed}
if self.return_attention_mask:
result["attention_mask"] = attention_mask
return result
|