Skip to content

Commit 0d340aa

Browse files
committed
[F] Fix jsonable test differs on multiple platform
1 parent b00ae15 commit 0d340aa

5 files changed

Lines changed: 464 additions & 1607 deletions

File tree

pyface/face_service.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ def _fill_results_to_faces_list(
115115
dep_result = dep_results[i]
116116
face.tddfa = TDDFA(
117117
param=dep_result["param"],
118-
lmk68pt=dep_result["lmk3d68pt"],
118+
lmk3d68pt=dep_result["lmk3d68pt"],
119119
depth_img=dep_result["depth_img"],
120120
yaw=dep_result["pose_degree"][0],
121121
roll=dep_result["pose_degree"][1],

pyface/object.py

Lines changed: 93 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,19 +29,41 @@ class Eye(cb.DataclassToJsonMixin, cb.DataclassCopyMixin):
2929
is_open: Optional[bool] = field(default=None)
3030
score: Optional[float] = field(default=None)
3131

32+
@classmethod
33+
def from_json(cls, data) -> "Eye":
34+
return cls(
35+
is_open=data.get("is_open"),
36+
score=data.get("score"),
37+
)
38+
3239

3340
@dataclass()
3441
class Mouth(cb.DataclassToJsonMixin, cb.DataclassCopyMixin):
3542
is_open: Optional[bool] = field(default=None)
3643
score: Optional[float] = field(default=None)
3744

45+
@classmethod
46+
def from_json(cls, data) -> "Mouth":
47+
return cls(
48+
is_open=data.get("is_open"),
49+
score=data.get("score"),
50+
)
51+
3852

3953
@dataclass()
4054
class WhetherOrNot(cb.DataclassToJsonMixin, cb.DataclassCopyMixin):
4155
is_true: Optional[bool] = field(default=None)
4256
value: Optional[float] = field(default=None)
4357
threshold: Optional[float] = field(default=None)
4458

59+
@classmethod
60+
def from_json(cls, data) -> "WhetherOrNot":
61+
return cls(
62+
is_true=data.get("is_true"),
63+
value=data.get("value"),
64+
threshold=data.get("threshold"),
65+
)
66+
4567

4668
@dataclass()
4769
class Liveness(cb.DataclassToJsonMixin, cb.DataclassCopyMixin):
@@ -50,29 +72,64 @@ class Liveness(cb.DataclassToJsonMixin, cb.DataclassCopyMixin):
5072
threshold: Optional[Union[float, np.number]] = field(default=None)
5173
fake_type: Optional[FakeType] = field(default=None)
5274

75+
@classmethod
76+
def from_json(cls, data):
77+
return cls(
78+
is_true=data.get("is_true"),
79+
value=data.get("value"),
80+
threshold=data.get("threshold"),
81+
fake_type=FakeType(data["fake_type"]) if data.get("fake_type") is not None else None,
82+
)
83+
5384

5485
@dataclass()
5586
class TDDFA(cb.DataclassToJsonMixin, cb.DataclassCopyMixin):
5687
param: Optional[np.ndarray] = field(default=None)
57-
lmk68pt: Optional[np.ndarray] = field(default=None)
88+
lmk3d68pt: Optional[np.ndarray] = field(default=None)
5889
depth_img: Optional[np.ndarray] = field(default=None)
5990
yaw: Optional[float] = field(default=None)
6091
roll: Optional[float] = field(default=None)
6192
pitch: Optional[float] = field(default=None)
6293

94+
@classmethod
95+
def from_json(cls, data) -> "TDDFA":
96+
return cls(
97+
param=cb.b64str_to_npy(data["param"]) if data.get("param") is not None else None,
98+
lmk3d68pt=np.array(data["lmk3d68pt"]) if data.get("lmk3d68pt") is not None else None,
99+
depth_img=cb.b64str_to_img(data["depth_img"]) if data.get("depth_img") is not None else None,
100+
yaw=data.get("yaw"),
101+
roll=data.get("roll"),
102+
pitch=data.get("pitch"),
103+
)
104+
63105

64106
@dataclass()
65107
class Encode(cb.DataclassToJsonMixin, cb.DataclassCopyMixin):
66108
vector: Optional[np.ndarray] = field(default=None)
67109
version: Optional[str] = field(default=None)
68110

111+
@classmethod
112+
def from_json(cls, data) -> "Encode":
113+
return cls(
114+
vector=cb.b64str_to_npy(data["vector"]) if data.get("vector") is not None else None,
115+
version=data.get("version"),
116+
)
117+
69118

70119
@dataclass()
71120
class Who(cb.DataclassToJsonMixin, cb.DataclassCopyMixin):
72121
name: Optional[str] = field(default="?")
73122
confidence: Optional[float] = field(default=None)
74123
recognized_level: Optional[int] = field(default=None)
75124

125+
@classmethod
126+
def from_json(cls, data) -> "Who":
127+
return cls(
128+
name=data.get("name", "?"),
129+
confidence=data.get("confidence"),
130+
recognized_level=data.get("recognized_level"),
131+
)
132+
76133

77134
@dataclass()
78135
class Attribute(cb.DataclassToJsonMixin, cb.DataclassCopyMixin):
@@ -84,6 +141,18 @@ class Attribute(cb.DataclassToJsonMixin, cb.DataclassCopyMixin):
84141
right_eye: Optional[Eye] = field(default=None)
85142
mouth: Optional[Mouth] = field(default=None)
86143

144+
@classmethod
145+
def from_json(cls, data) -> "Attribute":
146+
return cls(
147+
age=data.get("age"),
148+
gender=data.get("gender"),
149+
race=data.get("race"),
150+
pose=FacePose.obj_to_enum(data["pose"]) if data.get("pose") is not None else None,
151+
left_eye=Eye.from_json(data["left_eye"]) if data.get("left_eye") is not None else None,
152+
right_eye=Eye.from_json(data["right_eye"]) if data.get("right_eye") is not None else None,
153+
mouth=Mouth.from_json(data["mouth"]) if data.get("mouth") is not None else None,
154+
)
155+
87156

88157
@dataclass()
89158
class Face(cb.DataclassToJsonMixin, cb.DataclassCopyMixin):
@@ -107,9 +176,24 @@ class Face(cb.DataclassToJsonMixin, cb.DataclassCopyMixin):
107176
# pose: Optional[FacePose] = field(default=None)
108177
# blur: Optional[WhetherOrNot] = field(default=None)
109178
# occlusion: Optional[Occlusion] = field(default=None)
110-
# lmk68pt: Optional[cb.Keypoints] = field(default=None)
179+
# lmk3d68pt: Optional[cb.Keypoints] = field(default=None)
111180
# analysis_infos: Optional[dict] = field(default=None)
112181

182+
@classmethod
183+
def from_json(cls, data: dict) -> "Face":
184+
return cls(
185+
box=cb.Box(data["box"]),
186+
score=data["score"],
187+
lmk5pt=cb.Keypoints(np.array(data["lmk5pt"])) if data.get("lmk5pt") is not None else None,
188+
norm_img=cb.b64str_to_img(data["norm_img"]) if data.get("norm_img") is not None else None,
189+
tddfa=TDDFA.from_json(data["tddfa"]) if data.get("tddfa") is not None else None,
190+
encoding=Encode.from_json(data["encoding"]) if data.get("encoding") is not None else None,
191+
who=Who.from_json(data["who"]) if data.get("who") is not None else None,
192+
lmk106pt=cb.Keypoints(np.array(data["lmk106pt"])) if data.get("lmk106pt") is not None else None,
193+
liveness=Liveness.from_json(data["liveness"]) if data.get("liveness") is not None else None,
194+
attribute=Attribute.from_json(data["attribute"]) if data.get("attribute") is not None else None,
195+
)
196+
113197

114198
ATTR_NAMES = [f.name for f in fields(Face)]
115199

@@ -260,6 +344,13 @@ def be_jsonable(self):
260344
"faces": [x.be_jsonable() for x in self.faces],
261345
}
262346

347+
@classmethod
348+
def from_json(cls, data: dict) -> "Faces":
349+
return cls(
350+
raw_image=cb.b64str_to_img(data["raw_image"]) if data.get("raw_image") is not None else None,
351+
faces=[Face.from_json(x) for x in data.get("faces", [])],
352+
)
353+
263354

264355
# def _remove_none_in_jsonized_face(jsonized_face: dict) -> dict:
265356
# outs = {}

tests/resources/answer/EmmaWatson1_jsonable.json

Lines changed: 183 additions & 795 deletions
Large diffs are not rendered by default.

tests/resources/answer/JohnnyDepp1_jsonable.json

Lines changed: 183 additions & 795 deletions
Large diffs are not rendered by default.

tests/test_jsonable.py

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
import capybara as cb
2-
import numpy as np
32
import pytest
43

54
import pyface as pf
6-
from tests.tools import assert_allclose
75

86
RESOURCE_DIR = cb.get_curdir(__file__) / "resources"
97
ANSWER_DIR = RESOURCE_DIR / "answer"
@@ -12,28 +10,20 @@
1210
TEST_DATA = [
1311
{
1412
"img_fpath": RESOURCE_DIR / "EmmaWatson1.jpg",
15-
"expected": ANSWER_DIR / "EmmaWatson1_jsonable.json",
13+
"json_fpath": ANSWER_DIR / "EmmaWatson1_jsonable.json",
1614
},
1715
{
1816
"img_fpath": RESOURCE_DIR / "JohnnyDepp1.jpg",
19-
"expected": ANSWER_DIR / "JohnnyDepp1_jsonable.json",
17+
"json_fpath": ANSWER_DIR / "JohnnyDepp1_jsonable.json",
2018
},
2119
]
2220

2321

2422
@pytest.mark.parametrize("data", TEST_DATA)
2523
def test_jsonable(data):
26-
face_service = pf.FaceService(
27-
enable_depth=True,
28-
enable_landmark=True,
29-
enable_recognition=True,
30-
enable_gender=True,
31-
face_bank=RESOURCE_DIR / "face_bank",
32-
)
33-
img = cb.imread(data["img_fpath"])
34-
faces = face_service([img], do_1n=True)[0]
24+
expected = cb.load_json(data["json_fpath"])
25+
faces = pf.Faces.from_json(expected)
3526
output = faces.be_jsonable()
36-
expected = cb.load_json(data["expected"])
3727
assert output == expected
3828

3929

0 commit comments

Comments
 (0)