1// Copyright 2016 Google LLC
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//      http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package vision
16
17import (
18	"log"
19
20	pb "google.golang.org/genproto/googleapis/cloud/vision/v1"
21)
22
23// FaceLandmarks contains the positions of facial features detected by the service.
24type FaceLandmarks struct {
25	Eyebrows Eyebrows
26	Eyes     Eyes
27	Ears     Ears
28	Nose     Nose
29	Mouth    Mouth
30	Chin     Chin
31	Forehead *pb.Position
32}
33
34// Eyebrows represents a face's eyebrows.
35type Eyebrows struct {
36	Left, Right Eyebrow
37}
38
39// Eyebrow represents a face's eyebrow.
40type Eyebrow struct {
41	Top, Left, Right *pb.Position
42}
43
44// Eyes represents a face's eyes.
45type Eyes struct {
46	Left, Right Eye
47}
48
49// Eye represents a face's eye.
50type Eye struct {
51	Left, Right, Top, Bottom, Center, Pupil *pb.Position
52}
53
54// Ears represents a face's ears.
55type Ears struct {
56	Left, Right *pb.Position
57}
58
59// Nose represents a face's nose.
60type Nose struct {
61	Left, Right, Top, Bottom, Tip *pb.Position
62}
63
64// Mouth represents a face's mouth.
65type Mouth struct {
66	Left, Center, Right, UpperLip, LowerLip *pb.Position
67}
68
69// Chin represents a face's chin.
70type Chin struct {
71	Left, Center, Right *pb.Position
72}
73
74// FaceFromLandmarks converts the list of face landmarks returned by the service
75// to a FaceLandmarks struct.
76func FaceFromLandmarks(landmarks []*pb.FaceAnnotation_Landmark) *FaceLandmarks {
77	face := &FaceLandmarks{}
78	for _, lm := range landmarks {
79		switch lm.Type {
80		case pb.FaceAnnotation_Landmark_LEFT_OF_LEFT_EYEBROW:
81			face.Eyebrows.Left.Left = lm.Position
82		case pb.FaceAnnotation_Landmark_RIGHT_OF_LEFT_EYEBROW:
83			face.Eyebrows.Left.Right = lm.Position
84		case pb.FaceAnnotation_Landmark_LEFT_OF_RIGHT_EYEBROW:
85			face.Eyebrows.Right.Left = lm.Position
86		case pb.FaceAnnotation_Landmark_RIGHT_OF_RIGHT_EYEBROW:
87			face.Eyebrows.Right.Right = lm.Position
88		case pb.FaceAnnotation_Landmark_LEFT_EYEBROW_UPPER_MIDPOINT:
89			face.Eyebrows.Left.Top = lm.Position
90		case pb.FaceAnnotation_Landmark_RIGHT_EYEBROW_UPPER_MIDPOINT:
91			face.Eyebrows.Right.Top = lm.Position
92		case pb.FaceAnnotation_Landmark_MIDPOINT_BETWEEN_EYES:
93			face.Nose.Top = lm.Position
94		case pb.FaceAnnotation_Landmark_NOSE_TIP:
95			face.Nose.Tip = lm.Position
96		case pb.FaceAnnotation_Landmark_UPPER_LIP:
97			face.Mouth.UpperLip = lm.Position
98		case pb.FaceAnnotation_Landmark_LOWER_LIP:
99			face.Mouth.LowerLip = lm.Position
100		case pb.FaceAnnotation_Landmark_MOUTH_LEFT:
101			face.Mouth.Left = lm.Position
102		case pb.FaceAnnotation_Landmark_MOUTH_RIGHT:
103			face.Mouth.Right = lm.Position
104		case pb.FaceAnnotation_Landmark_MOUTH_CENTER:
105			face.Mouth.Center = lm.Position
106		case pb.FaceAnnotation_Landmark_NOSE_BOTTOM_RIGHT:
107			face.Nose.Right = lm.Position
108		case pb.FaceAnnotation_Landmark_NOSE_BOTTOM_LEFT:
109			face.Nose.Left = lm.Position
110		case pb.FaceAnnotation_Landmark_NOSE_BOTTOM_CENTER:
111			face.Nose.Bottom = lm.Position
112		case pb.FaceAnnotation_Landmark_LEFT_EYE:
113			face.Eyes.Left.Center = lm.Position
114		case pb.FaceAnnotation_Landmark_RIGHT_EYE:
115			face.Eyes.Right.Center = lm.Position
116		case pb.FaceAnnotation_Landmark_LEFT_EYE_TOP_BOUNDARY:
117			face.Eyes.Left.Top = lm.Position
118		case pb.FaceAnnotation_Landmark_LEFT_EYE_RIGHT_CORNER:
119			face.Eyes.Left.Right = lm.Position
120		case pb.FaceAnnotation_Landmark_LEFT_EYE_BOTTOM_BOUNDARY:
121			face.Eyes.Left.Bottom = lm.Position
122		case pb.FaceAnnotation_Landmark_LEFT_EYE_LEFT_CORNER:
123			face.Eyes.Left.Left = lm.Position
124		case pb.FaceAnnotation_Landmark_RIGHT_EYE_TOP_BOUNDARY:
125			face.Eyes.Right.Top = lm.Position
126		case pb.FaceAnnotation_Landmark_RIGHT_EYE_RIGHT_CORNER:
127			face.Eyes.Right.Right = lm.Position
128		case pb.FaceAnnotation_Landmark_RIGHT_EYE_BOTTOM_BOUNDARY:
129			face.Eyes.Right.Bottom = lm.Position
130		case pb.FaceAnnotation_Landmark_RIGHT_EYE_LEFT_CORNER:
131			face.Eyes.Right.Left = lm.Position
132		case pb.FaceAnnotation_Landmark_LEFT_EYE_PUPIL:
133			face.Eyes.Left.Pupil = lm.Position
134		case pb.FaceAnnotation_Landmark_RIGHT_EYE_PUPIL:
135			face.Eyes.Right.Pupil = lm.Position
136		case pb.FaceAnnotation_Landmark_LEFT_EAR_TRAGION:
137			face.Ears.Left = lm.Position
138		case pb.FaceAnnotation_Landmark_RIGHT_EAR_TRAGION:
139			face.Ears.Right = lm.Position
140		case pb.FaceAnnotation_Landmark_FOREHEAD_GLABELLA:
141			face.Forehead = lm.Position
142		case pb.FaceAnnotation_Landmark_CHIN_GNATHION:
143			face.Chin.Center = lm.Position
144		case pb.FaceAnnotation_Landmark_CHIN_LEFT_GONION:
145			face.Chin.Left = lm.Position
146		case pb.FaceAnnotation_Landmark_CHIN_RIGHT_GONION:
147			face.Chin.Right = lm.Position
148		default:
149			log.Printf("vision: ignoring unknown face annotation landmark %s", lm.Type)
150		}
151	}
152	return face
153}
154