在这个文件夹中,我们需要添加以下文件:
名人服务.cs
名人服务.cs
名人结果.cs
ILandmarkService.cs
地标服务 .cs
地标结果 .cs
ICelebrityService.cs – 包装多个串行的认知服务来实现名人识别的中间服务层的接口定义,需要依赖注入
using System.Threading.Tasks;
namespace CognitiveMiddlewareService.MiddlewareService
{
public interface ICelebrityService
{
Task<CelebrityResult> Do(byte[] imgData);
}
}
CelebrityService.cs – 包装多个串行的认知服务来实现名人识别中间服务层的逻辑代码
using CognitiveMiddlewareService.CognitiveServices;
using Newtonsoft.Json;
using System.Threading.Tasks;
namespace CognitiveMiddlewareService.MiddlewareService
{
public class CelebrityService : ICelebrityService
{
private readonly IVisionService visionService;
private readonly IEntitySearchService entityService;
public CelebrityService(IVisionService vs, IEntitySearchService ess)
{
this.visionService = vs;
this.entityService = ess;
}
public async Task<CelebrityResult> Do(byte[] imgData)
{
// get original recognized result
var stream = Helper.GetStream(imgData);
Celebrity celebrity = await this.visionService.RecognizeCelebrityAsync(stream);
if (celebrity != null)
{
// get entity search result
string entityName = celebrity.name;
string jsonResult = await this.entityService.SearchEntityAsync(entityName);
EntityResult er = JsonConvert.DeserializeObject<EntityResult>(jsonResult);
if (er?.entities?.value.Length > 0)
{
// isolation layer: decouple data structure then return abstract result
CelebrityResult cr = new CelebrityResult()
{
Name = er.entities.value[0].name,
Description = er.entities.value[0].description,
Url = er.entities.value[0].url,
ThumbnailUrl = er.entities.value[0].image.thumbnailUrl,
Confidence = celebrity.confidence
};
return cr;
}
}
return null;
}
}
}
小提示:上面的代码中,用CelebrityResult接管了实体搜索结果和名人识别结果的部分有效字段,以达到解耦/隔离的作用,后面的代码只关心CelebrityResult如何定义的即可。
CelebrityResult.cs – 抽象出来的名人识别服务的返回结果
namespace CognitiveMiddlewareService.MiddlewareService
{
public class CelebrityResult
{
public string Name { get; set; }
public double Confidence { get; set; }
public string Url { get; set; }
public string Description { get; set; }
public string ThumbnailUrl { get; set; }
}
}
ILandmarkService.cs – 包装多个串行的认知服务来实现地标识别的中间服务层的接口定义,需要依赖注入
using CognitiveMiddlewareService.CognitiveServices;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace CognitiveMiddlewareService.MiddlewareService
{
public interface ILandmarkService
{
Task<LandmarkResult> Do(byte[] imgData);
}
}
LandmarkService.cs – 包装多个串行的认知服务来实现地标识别的中间服务层的逻辑代码
using CognitiveMiddlewareService.CognitiveServices;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace CognitiveMiddlewareService.MiddlewareService
{
public class LandmarkService : ILandmarkService
{
private readonly IVisionService visionService;
private readonly IEntitySearchService entityService;
public LandmarkService(IVisionService vs, IEntitySearchService ess)
{
this.visionService = vs;
this.entityService = ess;
}
public async Task<LandmarkResult> Do(byte[] imgData)
{
// get original recognized result
var streamLandmark = Helper.GetStream(imgData);
Landmark landmark = await this.visionService.RecognizeLandmarkAsync(streamLandmark);
if (landmark != null)
{
// get entity search result
string entityName = landmark.name;
string jsonResult = await this.entityService.SearchEntityAsync(entityName);
EntityResult er = JsonConvert.DeserializeObject<EntityResult>(jsonResult);
// isolation layer: decouple data structure then return abstract result
LandmarkResult lr = new LandmarkResult()
{
Name = er.entities.value[0].name,
Description = er.entities.value[0].description,
Url = er.entities.value[0].url,
ThumbnailUrl = er.entities.value[0].image.thumbnailUrl,
Confidence = landmark.confidence
};
return lr;
}
return null;
}
}
}
小提示:上面的代码中,用LandmarkResult接管了实体搜索结果和地标识别结果的部分有效字段,以达到解耦/隔离的作用,后面的代码只关心LandmarkResult如何定义的即可。
LandmarkResult.cs – 抽象出来的地标识别服务的返回结果
namespace CognitiveMiddlewareService.MiddlewareService
{
public class LandmarkResult
{
public string Name { get; set; }
public double Confidence { get; set; }
public string Url { get; set; }
public string Description { get; set; }
public string ThumbnailUrl { get; set; }
}
}
在这个文件夹中,我们需要添加以下文件:
IProcessService.cs
进程服务 .cs
聚合结果.cs
IProcessService.cs – 任务调度层服务的接口定义,需要依赖注入
using System.Threading.Tasks;
namespace CognitiveMiddlewareService.Processors
{
public interface IProcessService
{
Task<AggregatedResult> Process(byte[] imgData);
}
}
ProcessService.cs – 任务调度层服务的逻辑代码
using CognitiveMiddlewareService.MiddlewareService;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace CognitiveMiddlewareService.Processors
{
public class ProcessService : IProcessService
{
private readonly ILandmarkService landmarkService;
private readonly ICelebrityService celebrityService;
public ProcessService(ILandmarkService ls, ICelebrityService cs)
{
this.landmarkService = ls;
this.celebrityService = cs;
}
public async Task<AggregatedResult> Process(byte[] imgData)
{
// preprocess
// todo: create screening image classifier to get a rough category, then decide call which service
// task dispatcher: parallelized run 'Do'
// todo: put this logic into Dispatcher service
List<Task> listTask = new List<Task>();
var taskLandmark = this.landmarkService.Do(imgData);
listTask.Add(taskLandmark);
var taskCelebrity = this.celebrityService.Do(imgData);
listTask.Add(taskCelebrity);
await Task.WhenAll(listTask);
LandmarkResult lmResult = taskLandmark.Result;
CelebrityResult cbResult = taskCelebrity.Result;
// aggregator
// todo: put this logic into Aggregator service
AggregatedResult ar = new AggregatedResult()
{
Landmark = lmResult,
Celebrity = cbResult
};
return ar;
// ranker
// todo: if there have more than one result in AgregatedResult, need give them a ranking
// output generator
// todo: generate specified JSON data, such as Adptive Card
}
}
}
小提示:大家可以看到上面这个文件中有很多绿色的注释,带有todo文字的,对于一个更复杂的系统,可以用这些todo中的描述来设计独立的模块。
AggregatedResult.cs – 任务调度层服务的最终聚合结果定义
using CognitiveMiddlewareService.MiddlewareService;
namespace CognitiveMiddlewareService.Processors
{
public class AggregatedResult
{
public LandmarkResult Landmark { get; set; }
public CelebrityResult Celebrity { get; set; }
}
}