| from enum import IntEnum |
| from pathlib import Path |
|
|
| import cv2 |
| import numpy as np |
|
|
| from core.cv2ex import * |
| from facelib import LandmarksProcessor |
| from core import imagelib |
| from core.imagelib import SegIEPolys |
|
|
| class SampleType(IntEnum): |
| IMAGE = 0 |
|
|
| FACE_BEGIN = 1 |
| FACE = 1 |
| FACE_PERSON = 2 |
| FACE_TEMPORAL_SORTED = 3 |
| FACE_END = 3 |
|
|
| QTY = 4 |
|
|
| class Sample(object): |
| __slots__ = ['sample_type', |
| 'filename', |
| 'face_type', |
| 'shape', |
| 'landmarks', |
| 'seg_ie_polys', |
| 'xseg_mask', |
| 'xseg_mask_compressed', |
| 'eyebrows_expand_mod', |
| 'source_filename', |
| 'person_name', |
| 'pitch_yaw_roll', |
| '_filename_offset_size', |
| ] |
|
|
| def __init__(self, sample_type=None, |
| filename=None, |
| face_type=None, |
| shape=None, |
| landmarks=None, |
| seg_ie_polys=None, |
| xseg_mask=None, |
| xseg_mask_compressed=None, |
| eyebrows_expand_mod=None, |
| source_filename=None, |
| person_name=None, |
| pitch_yaw_roll=None, |
| **kwargs): |
|
|
| self.sample_type = sample_type if sample_type is not None else SampleType.IMAGE |
| self.filename = filename |
| self.face_type = face_type |
| self.shape = shape |
| self.landmarks = np.array(landmarks) if landmarks is not None else None |
| |
| if isinstance(seg_ie_polys, SegIEPolys): |
| self.seg_ie_polys = seg_ie_polys |
| else: |
| self.seg_ie_polys = SegIEPolys.load(seg_ie_polys) |
| |
| self.xseg_mask = xseg_mask |
| self.xseg_mask_compressed = xseg_mask_compressed |
| |
| if self.xseg_mask_compressed is None and self.xseg_mask is not None: |
| xseg_mask = np.clip( imagelib.normalize_channels(xseg_mask, 1)*255, 0, 255 ).astype(np.uint8) |
| ret, xseg_mask_compressed = cv2.imencode('.png', xseg_mask) |
| if not ret: |
| raise Exception("Sample(): unable to generate xseg_mask_compressed") |
| self.xseg_mask_compressed = xseg_mask_compressed |
| self.xseg_mask = None |
| |
| self.eyebrows_expand_mod = eyebrows_expand_mod if eyebrows_expand_mod is not None else 1.0 |
| self.source_filename = source_filename |
| self.person_name = person_name |
| self.pitch_yaw_roll = pitch_yaw_roll |
|
|
| self._filename_offset_size = None |
|
|
| def has_xseg_mask(self): |
| return self.xseg_mask is not None or self.xseg_mask_compressed is not None |
| |
| def get_xseg_mask(self): |
| if self.xseg_mask_compressed is not None: |
| xseg_mask = cv2.imdecode(self.xseg_mask_compressed, cv2.IMREAD_UNCHANGED) |
| if len(xseg_mask.shape) == 2: |
| xseg_mask = xseg_mask[...,None] |
| return xseg_mask.astype(np.float32) / 255.0 |
| return self.xseg_mask |
| |
| def get_pitch_yaw_roll(self): |
| if self.pitch_yaw_roll is None: |
| self.pitch_yaw_roll = LandmarksProcessor.estimate_pitch_yaw_roll(self.landmarks, size=self.shape[1]) |
| return self.pitch_yaw_roll |
|
|
| def set_filename_offset_size(self, filename, offset, size): |
| self._filename_offset_size = (filename, offset, size) |
|
|
| def read_raw_file(self, filename=None): |
| if self._filename_offset_size is not None: |
| filename, offset, size = self._filename_offset_size |
| with open(filename, "rb") as f: |
| f.seek( offset, 0) |
| return f.read (size) |
| else: |
| with open(filename, "rb") as f: |
| return f.read() |
|
|
| def load_bgr(self): |
| img = cv2_imread (self.filename, loader_func=self.read_raw_file).astype(np.float32) / 255.0 |
| return img |
|
|
| def get_config(self): |
| return {'sample_type': self.sample_type, |
| 'filename': self.filename, |
| 'face_type': self.face_type, |
| 'shape': self.shape, |
| 'landmarks': self.landmarks.tolist(), |
| 'seg_ie_polys': self.seg_ie_polys.dump(), |
| 'xseg_mask' : self.xseg_mask, |
| 'xseg_mask_compressed' : self.xseg_mask_compressed, |
| 'eyebrows_expand_mod': self.eyebrows_expand_mod, |
| 'source_filename': self.source_filename, |
| 'person_name': self.person_name |
| } |
|
|