public static BattleUnit AnalyzeParameter(PredictedInfo image, IEnumerable <Tag> tags) { // TODO 重複排除とか色々再考する // TODO HPが低すぎてバトルがすぐ終わるので数値の重みづけを再考する var elements = image.Result.Predictions.Join( tags, x => x.TagName, y => y.TagName, (x, y) => new BattleElement() { Name = x.TagName, HP = (int)Math.Floor(y.HP * x.Probability), Attack = (int)Math.Floor(y.Attack * x.Probability), Mobility = (int)Math.Floor(y.Mobility * x.Probability), Remark = $"{x.TagName}: {x.Probability}" }); return(new BattleUnit() { Id = Guid.NewGuid(), PredictedInfoKey = image.RowKey, Name = image.ModelName, HP = elements.Sum(x => x.HP), Attack = elements.Sum(x => x.Attack), Mobility = elements.Sum(x => x.Mobility), Attributes = elements.Select(x => x.Name).ToList(), Remark = string.Join(",", elements.Select(x => x.Remark)) }); }
public static async Task <HttpResponseMessage> ImageUpload( [HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = "images/upload")] HttpRequestMessage req, [Table("Users")] IQueryable <User> users, [Table("CreateImageFromUrls")] IQueryable <CreateImageFromUrlsEntity> imageUrls, [Queue("create-image-from-urls")] ICollector <CreateImageFromUrlsRequest> queueItems, [Table("CreateImageFromUrls")] ICollector <CreateImageFromUrlsEntity> outImageUrlTable, [Table("PredictedInfo")] ICollector <PredictedInfo> outPredictedTable, TraceWriter log, Microsoft.Azure.WebJobs.ExecutionContext context) { log.Info("C# HTTP trigger function processed a request."); // collect input dynamic data = await req.Content.ReadAsAsync <object>(); string imageData = data.image; ICollection <string> tags = data.tags.ToObject <List <string> >(); string modelName = data.modelName; log.Info($"modelName={modelName}tags={string.Join(",", tags)}, image={imageData}"); var dataUrlReg = Regex.Match(imageData, @"data:image/(?<type>.+?);base64,(?<data>.+)"); var image = Convert.FromBase64String(dataUrlReg.Groups["data"].Value); var extension = dataUrlReg.Groups["type"].Value; // client var CV_ProjectId = Environment.GetEnvironmentVariable("CV_ProjectId"); var CV_TrainingKey = Environment.GetEnvironmentVariable("CV_TrainingKey"); var CV_PredictionKey = Environment.GetEnvironmentVariable("CV_PredictionKey"); var trainingApi = new TrainingApi() { ApiKey = CV_TrainingKey }; var predictionEndpoint = new PredictionEndpoint() { ApiKey = CV_PredictionKey }; var projectId = Guid.Parse(CV_ProjectId); // collect user var user = User.FromRequest(users, req, Thread.CurrentPrincipal); var iuser = user as IUser; // 既存のタグのみを受け付ける var existTags = await trainingApi.GetTagsAsync(projectId); tags = tags.Intersect(existTags.Select(x => x.Name)).ToList(); // setup blob // https://docs.microsoft.com/ja-jp/azure/cosmos-db/table-storage-design-guide#log-tail-pattern var invertedTicks = string.Format("{0:D19}", DateTime.MaxValue.Ticks - DateTime.UtcNow.Ticks); var blobName = invertedTicks + "-" + Guid.NewGuid().ToString(); var blockBlob = CommonHelper.PhotoBlobReference(blobName); var blockBlobThumbnail = CommonHelper.PhotoThumbnailBlobReference(blobName); blockBlob.Properties.ContentType = "image/jpeg"; blockBlobThumbnail.Properties.ContentType = "image/jpeg"; var url = blockBlob.Uri.ToString(); var source = "Upload"; var key = blockBlob.Name; log.Info($"pre upload. blobUri={url}"); // XXX この辺りの一連の手続きをいい感じに関数分割してフロー処理できると可用性と変更影響範囲が良くなりそう // ただ、この程度の規模のサービスで1関数で同期的に処理する平易さ以上のメリットを得られるかは疑問 // normalize image MemoryStream normalizedImage = NormalizeImage(image); AnchorLocation anchor = DetectFocusAnchor(log, normalizedImage, context.FunctionAppDirectory); log.Info($"Anchor: {anchor.ToString()}"); MemoryStream thumbnailImage = ToThumbnailImage(image, anchor); // upload image normalizedImage.Position = 0; thumbnailImage.Position = 0; await blockBlob.UploadFromStreamAsync(normalizedImage); await blockBlobThumbnail.UploadFromStreamAsync(thumbnailImage); log.Info($"after upload."); // queue image for training // 使用しているAPIの都合上、BLOBがアップロード後である必要がある TrainingImageLogic.AddImage( imageUrls, queueItems, outImageUrlTable, log, source, url, key, tags, user, modelName ); log.Info($"after queue image data."); // predict image // https://docs.microsoft.com/ja-jp/azure/cognitive-services/custom-vision-service/csharp-tutorial var imageUrl = new ImageUrl() { Url = url }; // XXX Storage emurator で通すならNgrock等の工夫が必要。単にDevelop用のStorage Accountを取ってしまった方が楽かも。 var predictResult = await predictionEndpoint.PredictImageUrlAsync(projectId, imageUrl); log.Info($"after prediction."); var predicted = new PredictedInfo() { PartitionKey = source, RowKey = key, Result = predictResult, User = user, ModelName = modelName }; outPredictedTable.Add(predicted); return(req.CreateJsonResponse(HttpStatusCode.OK, new { name = blockBlob.Name, url, result = predictResult })); }