Skip to content

Commit 04517cd

Browse files
committed
Add GAPIC support for face detection.
1 parent 885397b commit 04517cd

File tree

13 files changed

+388
-135
lines changed

13 files changed

+388
-135
lines changed

system_tests/vision.py

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -62,8 +62,8 @@ class BaseVisionTestCase(unittest.TestCase):
6262
def _assert_coordinate(self, coordinate):
6363
if coordinate is None:
6464
return
65+
self.assertIsNotNone(coordinate)
6566
self.assertIsInstance(coordinate, (int, float))
66-
self.assertNotEqual(coordinate, 0.0)
6767

6868
def _assert_likelihood(self, likelihood):
6969
from google.cloud.vision.likelihood import Likelihood
@@ -73,8 +73,8 @@ def _assert_likelihood(self, likelihood):
7373
Likelihood.VERY_UNLIKELY]
7474
self.assertIn(likelihood, levels)
7575

76-
def _maybe_http_skip(self, message):
77-
if not Config.CLIENT._use_gax:
76+
def _pb_not_implemented_skip(self, message):
77+
if Config.CLIENT._use_gax:
7878
self.skipTest(message)
7979

8080

@@ -150,7 +150,7 @@ def _assert_landmarks(self, landmarks):
150150

151151
for landmark in LandmarkTypes:
152152
if landmark is not LandmarkTypes.UNKNOWN_LANDMARK:
153-
feature = getattr(landmarks, landmark.value.lower())
153+
feature = getattr(landmarks, landmark.name.lower())
154154
self.assertIsInstance(feature, Landmark)
155155
self.assertIsInstance(feature.position, Position)
156156
self._assert_coordinate(feature.position.x_coordinate)
@@ -194,7 +194,6 @@ def _assert_face(self, face):
194194

195195
def test_detect_faces_content(self):
196196
client = Config.CLIENT
197-
self._maybe_http_skip('gRPC is required for face detection.')
198197
with open(FACE_FILE, 'rb') as image_file:
199198
image = client.image(content=image_file.read())
200199
faces = image.detect_faces()
@@ -203,7 +202,6 @@ def test_detect_faces_content(self):
203202
self._assert_face(face)
204203

205204
def test_detect_faces_gcs(self):
206-
self._maybe_http_skip('gRPC is required for face detection.')
207205
bucket_name = Config.TEST_BUCKET.name
208206
blob_name = 'faces.jpg'
209207
blob = Config.TEST_BUCKET.blob(blob_name)
@@ -220,7 +218,6 @@ def test_detect_faces_gcs(self):
220218
self._assert_face(face)
221219

222220
def test_detect_faces_filename(self):
223-
self._maybe_http_skip('gRPC is required for face detection.')
224221
client = Config.CLIENT
225222
image = client.image(filename=FACE_FILE)
226223
faces = image.detect_faces()
@@ -367,7 +364,8 @@ def _assert_safe_search(self, safe_search):
367364
self._assert_likelihood(safe_search.violence)
368365

369366
def test_detect_safe_search_content(self):
370-
self._maybe_http_skip('gRPC is required for safe search detection.')
367+
self._pb_not_implemented_skip(
368+
'gRPC not implemented for safe search detection.')
371369
client = Config.CLIENT
372370
with open(FACE_FILE, 'rb') as image_file:
373371
image = client.image(content=image_file.read())
@@ -377,7 +375,8 @@ def test_detect_safe_search_content(self):
377375
self._assert_safe_search(safe_search)
378376

379377
def test_detect_safe_search_gcs(self):
380-
self._maybe_http_skip('gRPC is required for safe search detection.')
378+
self._pb_not_implemented_skip(
379+
'gRPC not implemented for safe search detection.')
381380
bucket_name = Config.TEST_BUCKET.name
382381
blob_name = 'faces.jpg'
383382
blob = Config.TEST_BUCKET.blob(blob_name)
@@ -395,7 +394,8 @@ def test_detect_safe_search_gcs(self):
395394
self._assert_safe_search(safe_search)
396395

397396
def test_detect_safe_search_filename(self):
398-
self._maybe_http_skip('gRPC is required for safe search detection.')
397+
self._pb_not_implemented_skip(
398+
'gRPC not implemented for safe search detection.')
399399
client = Config.CLIENT
400400
image = client.image(filename=FACE_FILE)
401401
safe_searches = image.detect_safe_search()
@@ -493,7 +493,8 @@ def _assert_properties(self, image_property):
493493
self.assertNotEqual(color_info.score, 0.0)
494494

495495
def test_detect_properties_content(self):
496-
self._maybe_http_skip('gRPC is required for text detection.')
496+
self._pb_not_implemented_skip(
497+
'gRPC not implemented for image properties detection.')
497498
client = Config.CLIENT
498499
with open(FACE_FILE, 'rb') as image_file:
499500
image = client.image(content=image_file.read())
@@ -503,7 +504,8 @@ def test_detect_properties_content(self):
503504
self._assert_properties(image_property)
504505

505506
def test_detect_properties_gcs(self):
506-
self._maybe_http_skip('gRPC is required for text detection.')
507+
self._pb_not_implemented_skip(
508+
'gRPC not implemented for image properties detection.')
507509
client = Config.CLIENT
508510
bucket_name = Config.TEST_BUCKET.name
509511
blob_name = 'faces.jpg'
@@ -521,7 +523,8 @@ def test_detect_properties_gcs(self):
521523
self._assert_properties(image_property)
522524

523525
def test_detect_properties_filename(self):
524-
self._maybe_http_skip('gRPC is required for text detection.')
526+
self._pb_not_implemented_skip(
527+
'gRPC not implemented for image properties detection.')
525528
client = Config.CLIENT
526529
image = client.image(filename=FACE_FILE)
527530
properties = image.detect_properties()

vision/google/cloud/vision/_gax.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,6 @@
1717
from google.cloud.gapic.vision.v1 import image_annotator_client
1818
from google.cloud.grpc.vision.v1 import image_annotator_pb2
1919

20-
from google.cloud._helpers import _to_bytes
21-
2220
from google.cloud.vision.annotations import Annotations
2321

2422

@@ -85,7 +83,7 @@ def _to_gapic_image(image):
8583
:class:`~google.cloud.vision.image.Image`.
8684
"""
8785
if image.content is not None:
88-
return image_annotator_pb2.Image(content=_to_bytes(image.content))
86+
return image_annotator_pb2.Image(content=image.content)
8987
if image.source is not None:
9088
return image_annotator_pb2.Image(
9189
source=image_annotator_pb2.ImageSource(

vision/google/cloud/vision/annotations.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ def _process_image_annotations(image):
119119
:returns: Dictionary populated with entities from response.
120120
"""
121121
return {
122+
'faces': _make_faces_from_pb(image.face_annotations),
122123
'labels': _make_entity_from_pb(image.label_annotations),
123124
'landmarks': _make_entity_from_pb(image.landmark_annotations),
124125
'logos': _make_entity_from_pb(image.logo_annotations),
@@ -139,6 +140,19 @@ def _make_entity_from_pb(annotations):
139140
return [EntityAnnotation.from_pb(annotation) for annotation in annotations]
140141

141142

143+
def _make_faces_from_pb(faces):
144+
"""Create face objects from a gRPC response.
145+
146+
:type faces:
147+
:class:`~google.cloud.grpc.vision.v1.image_annotator_pb2.FaceAnnotation`
148+
:param faces: Protobuf instance of ``FaceAnnotation``.
149+
150+
:rtype: list
151+
:returns: List of ``Face``.
152+
"""
153+
return [Face.from_pb(face) for face in faces]
154+
155+
142156
def _entity_from_response_type(feature_type, results):
143157
"""Convert a JSON result to an entity type based on the feature.
144158

vision/google/cloud/vision/client.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ class Client(JSONClient):
5858
_vision_api_internal = None
5959

6060
def __init__(self, project=None, credentials=None, http=None,
61-
use_gax=False):
61+
use_gax=None):
6262
super(Client, self).__init__(
6363
project=project, credentials=credentials, http=http)
6464
self._connection = Connection(

0 commit comments

Comments
 (0)