Exemplo n.º 1
0
        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
            }));
        }
Exemplo n.º 2
0
		/// <summary>
		/// Renders a triangle portion of a control.
		/// </summary>
		protected virtual void FillTriangle(Coord size, HitState hitState, AnchorLocation triDirection, AnchorLocation gradDirection)
		{
			var point = Context.Push();
			
			// Create the gradient
			Cairo.LinearGradient grad = GenerateGradient(point.Coord(), size / 2.0, gradDirection, 
			                                             GetColor(ColorType.BackgroundStart, hitState),
			                                             GetColor(ColorType.BackgroundStop, hitState));
			// draw the triangle
			Context.Cairo.Operator = Cairo.Operator.Source;
			Context.Cairo.Pattern = grad;
			switch (triDirection)
			{
			case AnchorLocation.NE:
				Context.Cairo.RelLineTo(size.X, 0);
				Context.Cairo.RelLineTo(0, size.Y);
				break;
			case AnchorLocation.NW:
				Context.Cairo.RelLineTo(size.X, 0);
				Context.Cairo.RelLineTo(-size.X, size.Y);
				break;
			case AnchorLocation.SE:
				Context.Cairo.MoveTo(size.X, 0);
				Context.Cairo.RelLineTo(0, size.Y);
				Context.Cairo.RelLineTo(-size.X, 0);
				break;
			case AnchorLocation.SW:
				Context.Cairo.RelLineTo(0, size.Y);
				Context.Cairo.RelLineTo(size.X, 0);
				break;
			case AnchorLocation.N:
				Context.Cairo.RelMoveTo(0, size.Y);
				Context.Cairo.RelLineTo(size.X, 0);
				Context.Cairo.RelLineTo(-size.X/2.0, size.Y);
				break;
			case AnchorLocation.E:
				Context.Cairo.RelLineTo(0, size.Y);
				Context.Cairo.RelLineTo(size.X, -size.Y/2.0);
				break;
			case AnchorLocation.S:
				Context.Cairo.RelLineTo(size.X, 0);
				Context.Cairo.RelLineTo(-size.X/2.0, size.Y);
				break;
			case AnchorLocation.W:
				Context.Cairo.RelMoveTo(size.X, 0);
				Context.Cairo.RelLineTo(0, size.Y);
				Context.Cairo.RelLineTo(-size.X, -size.Y/2.0);
				break;
			default:
				throw new Exception(triDirection.ToString() + " is currently not a valid triangle location");
			}
			Context.Cairo.Fill();
			
			Context.Pop();
		}