构建图像标注与翻译的WebAPI服务

本教程分为两个部分:第一部分是构建一个处理图像标注和翻译成不同语言的WebAPI服务;第二部分是从Android应用中调用这个RESTful服务。

创建WebAPI项目

将从创建一个新的WebAPI项目开始。在Visual Studio中选择新建项目 -> C# -> Web -> ASP.NET Web应用程序 - 空。勾选WebAPI,并选择云托管,以便稍后能够发布这个项目。

配置项目依赖

项目所需的所有库将包含在packages.config文件中。

XML配置示例:

<?xml version="1.0" encoding="utf-8"?> <packages> <package id="BouncyCastle" version="1.7.0" targetFramework="net45"/> <package id="Google.Apis" version="1.19.0" targetFramework="net45"/> <package id="Google.Apis.Auth" version="1.19.0" targetFramework="net45"/> <package id="Google.Apis.Core" version="1.19.0" targetFramework="net45"/> <package id="Google.Apis.Translate.v2" version="1.19.0.543" targetFramework="net45"/> <package id="Google.Apis.Vision.v1" version="1.19.0.683" targetFramework="net45"/> <package id="GoogleApi" version="2.0.13" targetFramework="net45"/> <package id="log4net" version="2.0.3" targetFramework="net45"/> <package id="Microsoft.AspNet.WebApi" version="5.2.3" targetFramework="net45"/> <package id="Microsoft.AspNet.WebApi.Client" version="5.2.3" targetFramework="net45"/> <package id="Microsoft.AspNet.WebApi.Core" version="5.2.3" targetFramework="net45"/> <package id="Microsoft.AspNet.WebApi.WebHost" version="5.2.3" targetFramework="net45"/> <package id="Microsoft.CodeDom.Providers.DotNetCompilerPlatform" version="1.0.0" targetFramework="net45"/> <package id="Microsoft.Net.Compilers" version="1.0.0" targetFramework="net45" developmentDependency="true"/> <package id="Newtonsoft.Json" version="7.0.1" targetFramework="net45"/> <package id="Zlib.Portable.Signed" version="1.11.0" targetFramework="net45"/> </packages>

设置API密钥

由于将使用Google API,因此需要先设置一个Google云视觉API项目。

1. 对于Google视觉API,下载VisionAPI-xxxxxx.json文件并保存在项目根目录。

2. 对于翻译API,在同一页面获取API密钥。

在代码中,首先调用这些API变量。将值替换为上面获取的密钥。

配置全局配置

Global类中配置全局变量和环境变量。

using System; using System.Configuration; using System.Diagnostics; using System.IO; using System.Web.Http; namespace ThingTranslatorAPI2 { public class Global : System.Web.HttpApplication { public static String apiKey; protected void Application_Start() { GlobalConfiguration.Configure(WebApiConfig.Register); apiKey = "API-KEY"; createEnvVar(); } private static void createEnvVar() { var GAC = Environment.GetEnvironmentVariable("GOOGLE_APPLICATION_CREDENTIALS"); if (GAC == null) { var VisionApiKey = ConfigurationManager.AppSettings["VisionApiKey"]; if (VisionApiKey != null) { var path = System.Web.Hosting.HostingEnvironment.MapPath("~/") + "YOUR-API-KEY.json"; Trace.TraceError("path: " + path); File.WriteAllText(path, VisionApiKey); Environment.SetEnvironmentVariable("GOOGLE_APPLICATION_CREDENTIALS", path); } } } } }

配置WebApi路由

WebApiConfig中配置路由,使用属性路由而不是默认路由配置。

using System.Web.Http; namespace ThingTranslatorAPI2 { public static class WebApiConfig { public static void Register(HttpConfiguration config) { config.MapHttpAttributeRoutes(); } } }

创建API控制器

需要一个API控制器来处理请求并处理它们。请求应包含图像文件和想要翻译成的目标语言的语言代码。图像将在内存中处理,因此无需将其保存在磁盘上。

using System; using System.Linq; using System.Net; using System.Net.Http; using System.Threading.Tasks; using System.Web.Http; using System.Web.Http.Results; using GoogleApi; using GoogleApi.Entities.Translate.Translate.Request; using TranslationsResource = Google.Apis.Translate.v2.Data.TranslationsResource; namespace ThingTranslatorAPI2.Controllers { [RoutePrefix("api")] public class TranslatorController : ApiController { [Route("upload")] [HttpPost] public async Task> Upload() { if (!Request.Content.IsMimeMultipartContent()) throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType); String langCode = string.Empty; var response = new Response(); byte[] buffer = null; var provider = new MultipartMemoryStreamProvider(); await Request.Content.ReadAsMultipartAsync(provider); foreach (var content in provider.Contents) { if (content.Headers.ContentType != null && content.Headers.ContentType.MediaType.Contains("image")) buffer = await content.ReadAsByteArrayAsync(); else langCode = await content.ReadAsStringAsync(); } var labels = LabelDetector.GetLabels(buffer); try { var bestMatch = labels[0].LabelAnnotations.FirstOrDefault()?.Description; String translateText; if (langCode == "en") translateText = bestMatch; else translateText = TranslateText(bestMatch, "en", langCode); response.Original = bestMatch; response.Translation = translateText; } catch (Exception ex) { response.Error = ex.Message; return Json(response); } return Json(response); } private String TranslateText(String text, String source, String target) { var _request = new TranslateRequest { Source = source, Target = target, Qs = new[] { text }, Key = Global.apiKey }; try { var _result = GoogleTranslate.Translate.Query(_request); return _result.Data.Translations.First().TranslatedText; } catch (Exception ex) { return ex.Message; } } } }

图像标注

对于图像标注,需要这个类LabelDetector.cs

using Google.Apis.Auth.OAuth2; using Google.Apis.Services; using Google.Apis.Vision.v1; using Google.Apis.Vision.v1.Data; using System; using System.Collections.Generic; using System.Diagnostics; namespace ThingTranslatorAPI2 { public class LabelDetector { public static IList GetLabels(byte[] imageArray) { try { VisionService vision = CreateAuthorizedClient(); string imageContent = Convert.ToBase64String(imageArray); var responses = vision.Images.Annotate(new BatchAnnotateImagesRequest() { Requests = new[] { new AnnotateImageRequest() { Features = new[] { new Feature() { Type = "LABEL_DETECTION" } }, Image = new Image() { Content = imageContent } } } }).Execute(); return responses.Responses; } catch (Exception ex) { Trace.TraceError(ex.StackTrace); } return null; } public static VisionService CreateAuthorizedClient() { try { GoogleCredential credential = GoogleCredential.GetApplicationDefaultAsync().Result; if (credential.IsCreateScopedRequired) { credential = credential.CreateScoped(new[] { VisionService.Scope.CloudPlatform }); } return new VisionService(new BaseClientService.Initializer { HttpClientInitializer = credential, GZipEnabled = false }); } catch (Exception ex) { Trace.TraceError("CreateAuthorizedClient: " + ex.StackTrace); } return null; } } }

响应类

Response.cs将如下所示:

namespace ThingTranslatorAPI2.Controllers { public class Response { public string Original { get; set; } public string Translation { get; set; } public string Error { get; set; } } }

发布到Azure云

现在可以将这个项目发布到Azure云。转到“构建”->“发布”,并填写所有4个输入框以匹配Azure设置。

使用Postman测试

使用Postman测试响应:

{"Original":"mouse","Translation":"miš","Error":null}

收到了包含图像标签的英文和指定语言的翻译版本的响应。

目前有几种API可以处理图像标注。其中一个发现非常奇特的叫做CloudSight。尽管它比其他的更准确,但它依赖于人类标记。这的缺点是它比机器完成工作需要更多的时间。通常在10-30秒后收到响应。

可以想象如果应用程序运行并且发生了超时。该如何称呼它为连接超时还是咖啡休息超时;-)?

沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485