Google Cloud Vision 分析图像并告诉你其中有什么:它返回描述性标签,读取印刷和手写文本(OCR),检测人脸,识别著名地标和徽标,等等。sgcWebSockets Enterprise 提供了一个位于 TsgcGRPCClient 之上的强类型 Vision gRPC 客户端,因此你可以从 Delphi 和 C++Builder 发送图像并读回它的标注,无需任何外部运行时或手写的 protobuf。
工作原理
Cloud Vision 提供一个 ImageAnnotator gRPC 服务。一个请求是一批一个或多个图像,每个图像都配上你想要检测的特征列表,而响应是一批与之对应的标注。整个交换都是通过 HTTP/2 封帧的 Protocol Buffers 消息。
sgcWebSockets 已经提供了完整的 HTTP/2 栈,因此传输是一个指向 vision.googleapis.com:443、基于 TLS 的 TsgcHTTP2Client。TsgcGRPCClient 位于其之上,完成 gRPC 封帧、请求头、超时和尾部解析。sgcGRPC_Google_Vision 中的 Vision 消息类是强类型的 protobuf 辅助类:你填充请求对象,调用 ToBytes 将其序列化,用通用客户端发送,然后用 LoadFromBytes 将回复字节加载回一个强类型响应对象。
身份验证是标准的 Google 服务账号流程。一个自签名的 JWT 被换取为一个 bearer 令牌,并作为 gRPC 元数据随每个调用一起发送。由于该 JWT 是受众绑定的,因此该令牌以 Vision 端点为目标,以便 vision.googleapis.com 接受它。
设置客户端
创建 HTTP/2 传输,将 gRPC 客户端附加到它上面,并告诉通道使用二进制 protobuf 内容类型。Vision 使用 application/grpc+proto。
uses
sgcHTTP2_Client, sgcGRPC_Types, sgcGRPC_Client,
sgcGRPC_Google_Vision;
var
HTTP2: TsgcHTTP2Client;
GRPC: TsgcGRPCClient;
begin
HTTP2 := TsgcHTTP2Client.Create(nil);
HTTP2.Host := 'vision.googleapis.com';
HTTP2.Port := 443;
HTTP2.TLS := True;
GRPC := TsgcGRPCClient.Create(nil);
GRPC.Client := HTTP2;
GRPC.ChannelOptions.ContentType := grpcProto;
GRPC.ChannelOptions.Compression := grpcNoCompression;
end;
身份验证
bearer 令牌来自你的服务账号凭据。用下载的 JSON 密钥中的值配置 JWT 选项,将受众指向 Vision 端点,并将得到的令牌添加到 DefaultMetadata 中,以便它随每个 gRPC 调用一起传递。
// configure the service-account JWT (values from the JSON key file)
CloudClient.GoogleCloudOptions.Authentication := gcaJWT;
CloudClient.GoogleCloudOptions.JWT.ClientEmail := ClientEmail;
CloudClient.GoogleCloudOptions.JWT.PrivateKeyId := PrivateKeyId;
CloudClient.GoogleCloudOptions.JWT.PrivateKey.Text := PrivateKey;
CloudClient.GoogleCloudOptions.JWT.ProjectId := ProjectId;
// the self-signed JWT is audience-bound to the Vision endpoint
CloudClient.GoogleCloudOptions.JWT.API_Endpoint :=
'https://vision.googleapis.com/';
// once the token is acquired, send it as gRPC metadata
GRPC.DefaultMetadata.Clear;
GRPC.DefaultMetadata.Add('authorization', 'Bearer ' + Token);
标注图像
要分析一张图像,你构建一个 TsgcGRPCVisionBatchAnnotateImagesRequest,添加一个图像请求,将它指向该图像(这里是一个 Google Cloud Storage URI,但你也可以发送原始字节),并添加一个或多个特征。每个特征都有一个 FeatureType 和一个可选的 MaxResults。用 ToBytes 序列化,并调用 ImageAnnotator 服务的 BatchAnnotateImages 方法。
var
oRequest: TsgcGRPCVisionBatchAnnotateImagesRequest;
oImgReq: TsgcGRPCVisionAnnotateImageRequest;
oFeature: TsgcGRPCVisionFeature;
oResponse: TsgcGRPCResponse;
begin
oRequest := TsgcGRPCVisionBatchAnnotateImagesRequest.Create;
try
oImgReq := oRequest.AddRequest;
oImgReq.Image.Source.GcsImageUri :=
'gs://cloud-samples-data/vision/demo-image.jpg';
oFeature := oImgReq.AddFeature;
oFeature.FeatureType := 4; // LABEL_DETECTION
oFeature.MaxResults := 10;
oResponse := GRPC.Call('google.cloud.vision.v1.ImageAnnotator',
'BatchAnnotateImages', oRequest.ToBytes);
finally
oRequest.Free;
end;
end;
FeatureType 的值遵循 Vision API 的枚举:1 FACE_DETECTION、2 LANDMARK_DETECTION、3 LOGO_DETECTION、4 LABEL_DETECTION、5 TEXT_DETECTION、6 DOCUMENT_TEXT_DETECTION,以及其余的。要在一次往返中对同一张图像运行多种检测,请添加多个特征。
读取标注
回复字节直接加载到一个强类型批量响应中。批次中的每张图像都携带用于标签、地标、徽标和文本标注的独立列表。每个条目是一个带有 Description 的 TsgcGRPCVisionEntityAnnotation,对于标签还带有一个置信度 Score。
var
oResponse: TsgcGRPCVisionBatchAnnotateImagesResponse;
oImgResp: TsgcGRPCVisionAnnotateImageResponse;
i, j: Integer;
begin
oResponse := TsgcGRPCVisionBatchAnnotateImagesResponse.Create;
try
oResponse.LoadFromBytes(aData);
for i := 0 to oResponse.ResponseCount - 1 do
begin
oImgResp := oResponse.Response(i);
for j := 0 to oImgResp.LabelAnnotationCount - 1 do
Memo1.Lines.Add('Label: ' + oImgResp.LabelAnnotation(j).Description +
' (score: ' + FloatToStr(oImgResp.LabelAnnotation(j).Score) + ')');
for j := 0 to oImgResp.TextAnnotationCount - 1 do
Memo1.Lines.Add('Text: ' + oImgResp.TextAnnotation(j).Description);
for j := 0 to oImgResp.LandmarkAnnotationCount - 1 do
Memo1.Lines.Add('Landmark: ' + oImgResp.LandmarkAnnotation(j).Description);
end;
finally
oResponse.Free;
end;
end;
来自存储或来自字节的图像
图像来源是灵活的。为 Google Cloud Storage 中的对象设置 Image.Source.GcsImageUri,或为一个公开的 HTTP(S) URL 设置 Image.Source.ImageUri。要标注一个本地文件,请将它读入一个 TBytes 并改为赋给 Image.Content,这样图片就会内联随请求一起传输。同一套请求和响应类可处理每一种来源。
同步或异步
上面的示例使用了阻塞式的 Call,它返回一个带有 StatusCode、原始 Data 字节和尾部的 TsgcGRPCResponse。为了保持 UI 响应,请使用 CallAsync 并在 OnGRPCResponse 事件中处理回复,在那里你以完全相同的方式解析 aResponse.Data。非 OK 状态会通过 OnGRPCError 浮现,而传输故障则通过 OnGRPCException 浮现。
可用性
强类型 Vision gRPC 客户端是 sgcWebSockets Enterprise 版本的一部分,可运行于 Windows、macOS、Linux、iOS 和 Android。一个开箱即用的示例位于 Demos\21.GRPC\13.Vision,完整参考资料请见gRPC Client 产品页面。
有问题或反馈?联系我们。你会收到来自编写这段代码的人的回复。
