Пример #1
0
        /// <summary>
        /// Uses Cognitive Services Custom Vision API to determine whether an object was found in an image
        /// with some degree of certainty
        /// </summary>
        /// <param name="imageUrl"></param>
        /// <returns>Boolean</returns>
        private static async Task <bool> ObjectFound(string imageUrl, double minimumScore = 0.5)
        {
            bool objectFound = false;

            try
            {
                // Initialize prediction endpoint
                PredictionEndpoint predictionEndpoint = new PredictionEndpoint()
                {
                    ApiKey = ConfigurationManager.AppSettings["CustomVisionApiKey"]
                };

                // Call custom vision prediction API to predict image
                ImagePredictionResultModel predictionResult = await predictionEndpoint.PredictImageUrlAsync(
                    new Guid(ConfigurationManager.AppSettings["CustomVisionProjectId"]),
                    new ImageUrl(imageUrl));

                // Query for the object tag
                var objectTag = predictionResult.Predictions.Where(x => x.Tag == "Object").FirstOrDefault();

                // Check if the object tag probability surpassed the minimum score
                if (objectTag != null && objectTag.Probability >= minimumScore)
                {
                    objectFound = true;
                }
            }
            catch (Exception e)
            {
                throw e;
            }

            // Return result
            return(objectFound);
        }
Пример #2
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="imageUrl"></param>
        /// <returns></returns>
        public static async Task <ImagePredictionResultModel> PredictImageUrl(string imageUrl)
        {
            PredictionEndpoint endpoint = new PredictionEndpoint()
            {
                ApiKey = predictionKey,
            };

            var result = await endpoint.PredictImageUrlAsync(new Guid(projectId), new ImageUrl(imageUrl), iterationId : new Guid("3a06600a-2917-41de-9a9a-95a70157b007"));

            return(result);
        }
Пример #3
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
            }));
        }