2828
2929_SYS_TESTS_DIR = os .path .abspath (os .path .dirname (__file__ ))
3030LOGO_FILE = os .path .join (_SYS_TESTS_DIR , 'data' , 'logo.png' )
31+ FACE_FILE = os .path .join (_SYS_TESTS_DIR , 'data' , 'faces.jpg' )
3132
3233
3334class Config (object ):
@@ -53,7 +54,7 @@ def tearDownModule():
5354 bucket_retry (Config .TEST_BUCKET .delete )(force = True )
5455
5556
56- class TestVisionClient (unittest .TestCase ):
57+ class TestVisionClientLogo (unittest .TestCase ):
5758 def setUp (self ):
5859 self .to_delete_by_case = []
5960
@@ -108,3 +109,109 @@ def test_detect_logos_gcs(self):
108109 self .assertEqual (len (logos ), 1 )
109110 logo = logos [0 ]
110111 self ._assert_logo (logo )
112+
113+
114+ class TestVisionClientFace (unittest .TestCase ):
115+ def setUp (self ):
116+ self .to_delete_by_case = []
117+
118+ def tearDown (self ):
119+ for value in self .to_delete_by_case :
120+ value .delete ()
121+
122+ def _assert_coordinate (self , coordinate ):
123+ if coordinate is None :
124+ return
125+ self .assertIsInstance (coordinate , (int , float ))
126+ self .assertGreater (abs (coordinate ), 0.0 )
127+
128+ def _assert_likelihood (self , likelihood ):
129+ from google .cloud .vision .likelihood import Likelihood
130+
131+ levels = [Likelihood .UNKNOWN , Likelihood .VERY_LIKELY ,
132+ Likelihood .UNLIKELY , Likelihood .POSSIBLE , Likelihood .LIKELY ,
133+ Likelihood .VERY_UNLIKELY ]
134+ self .assertIn (likelihood , levels )
135+
136+ def _assert_landmarks (self , landmarks ):
137+ from google .cloud .vision .face import Landmark
138+ from google .cloud .vision .face import LandmarkTypes
139+ from google .cloud .vision .face import Position
140+
141+ for landmark in LandmarkTypes :
142+ if landmark is not LandmarkTypes .UNKNOWN_LANDMARK :
143+ feature = getattr (landmarks , landmark .value .lower ())
144+ self .assertIsInstance (feature , Landmark )
145+ self .assertIsInstance (feature .position , Position )
146+ self ._assert_coordinate (feature .position .x_coordinate )
147+ self ._assert_coordinate (feature .position .y_coordinate )
148+ self ._assert_coordinate (feature .position .z_coordinate )
149+
150+ def _assert_face (self , face ):
151+ from google .cloud .vision .face import Bounds
152+ from google .cloud .vision .face import FDBounds
153+ from google .cloud .vision .face import Face
154+ from google .cloud .vision .face import Landmarks
155+ from google .cloud .vision .geometry import Vertex
156+
157+ self .assertIsInstance (face , Face )
158+ self .assertGreater (face .detection_confidence , 0.0 )
159+ self ._assert_likelihood (face .anger )
160+ self ._assert_likelihood (face .joy )
161+ self ._assert_likelihood (face .sorrow )
162+ self ._assert_likelihood (face .surprise )
163+ self ._assert_likelihood (face .image_properties .blurred )
164+ self ._assert_likelihood (face .image_properties .underexposed )
165+ self ._assert_likelihood (face .headwear )
166+ self .assertNotEqual (face .angles .roll , 0.0 )
167+ self .assertNotEqual (face .angles .pan , 0.0 )
168+ self .assertNotEqual (face .angles .tilt , 0.0 )
169+
170+ self .assertIsInstance (face .bounds , Bounds )
171+ for vertex in face .bounds .vertices :
172+ self .assertIsInstance (vertex , Vertex )
173+ self ._assert_coordinate (vertex .x_coordinate )
174+ self ._assert_coordinate (vertex .y_coordinate )
175+
176+ self .assertIsInstance (face .fd_bounds , FDBounds )
177+ for vertex in face .fd_bounds .vertices :
178+ self .assertIsInstance (vertex , Vertex )
179+ self ._assert_coordinate (vertex .x_coordinate )
180+ self ._assert_coordinate (vertex .y_coordinate )
181+
182+ self .assertIsInstance (face .landmarks , Landmarks )
183+ self ._assert_landmarks (face .landmarks )
184+
185+ def test_detect_faces_content (self ):
186+ client = Config .CLIENT
187+ with open (FACE_FILE , 'rb' ) as image_file :
188+ image = client .image (content = image_file .read ())
189+ faces = image .detect_faces ()
190+ self .assertEqual (len (faces ), 5 )
191+ for face in faces :
192+ self ._assert_face (face )
193+
194+ def test_detect_faces_gcs (self ):
195+ bucket_name = Config .TEST_BUCKET .name
196+ blob_name = 'faces.jpg'
197+ blob = Config .TEST_BUCKET .blob (blob_name )
198+ self .to_delete_by_case .append (blob ) # Clean-up.
199+ with open (FACE_FILE , 'rb' ) as file_obj :
200+ blob .upload_from_file (file_obj )
201+
202+ source_uri = 'gs://%s/%s' % (bucket_name , blob_name )
203+
204+ client = Config .CLIENT
205+ image = client .image (source_uri = source_uri )
206+ faces = image .detect_faces ()
207+ self .assertEqual (len (faces ), 5 )
208+ for face in faces :
209+ self ._assert_face (face )
210+
211+ def test_detect_faces_filename (self ):
212+ client = Config .CLIENT
213+ image = client .image (filename = FACE_FILE )
214+ faces = image .detect_faces ()
215+ self .assertEqual (len (faces ), 5 )
216+ for face in faces :
217+ self ._assert_face (face )
0 commit comments