예제 #1
0
        public static string GetAggregatedResultString(List <SatyamResultsTableEntry> results)
        {
            if (results.Count == 0)
            {
                return(null);
            }

            string resultString = null;
            List <ImageSegmentationResult> resultList = new List <ImageSegmentationResult>();
            List <string> WorkersPerTask = new List <string>();

            SatyamResult res0      = JSonUtils.ConvertJSonToObject <SatyamResult>(results[0].ResultString);
            SatyamTask   task      = JSonUtils.ConvertJSonToObject <SatyamTask>(res0.TaskParametersString);
            string       SatyamURL = task.SatyamURI;
            string       guid      = results[0].JobGUID;

            foreach (SatyamResultsTableEntry entry in results)
            {
                SatyamResult res = JSonUtils.ConvertJSonToObject <SatyamResult>(entry.ResultString);

                // remove duplicate workers result
                string workerID = res.amazonInfo.WorkerID;
                if (WorkersPerTask.Contains(workerID))
                {
                    continue;
                }

                string assignmentID = res.amazonInfo.AssignmentID;
                if (assignmentID == "" || assignmentID == "ASSIGNMENT_ID_NOT_AVAILABLE")
                {
                    continue;
                }

                //enclose only non-duplicate results, one per each worker.
                if (workerID != "" && workerID != TaskConstants.AdminID)
                {
                    // make a pass for test and admins
                    WorkersPerTask.Add(workerID);
                }


                ImageSegmentationResult taskr = JSonUtils.ConvertJSonToObject <ImageSegmentationResult>(res.TaskResult);
                resultList.Add(taskr);
            }


            ImageSegmentationAggregatedResult r = getAggregatedResult(resultList, SatyamURL, guid);

            if (r != null)
            {
                string rString = JSonUtils.ConvertObjectToJSon <ImageSegmentationAggregatedResult>(r);
                SatyamAggregatedResult aggResult = new SatyamAggregatedResult();
                aggResult.SatyamTaskTableEntryID = results[0].SatyamTaskTableEntryID;
                aggResult.AggregatedResultString = rString;
                SatyamResult res = JSonUtils.ConvertJSonToObject <SatyamResult>(results[0].ResultString);
                aggResult.TaskParameters = res.TaskParametersString;
                resultString             = JSonUtils.ConvertObjectToJSon <SatyamAggregatedResult>(aggResult);
            }
            return(resultString);
        }
예제 #2
0
        public static bool IsAcceptable(
            SatyamAggregatedResultsTableEntry aggResultEntry,
            SatyamResultsTableEntry resultEntry,
            double APPROVAL_RATIO_OF_POLYGONS_THRESHOLD = TaskConstants.IMAGE_SEGMENTATION_MTURK_OBJECT_COVERAGE_THRESHOLD_FOR_PAYMENT, //the person must have made at least 80% of the polygon
            double POLYGON_IOU_THRESHOLD = TaskConstants.IMAGE_SEGMENTATION_MTURK_POLYGON_IOU_THRESHOLD_FOR_PAYMENT
            )
        {
            //most boxes should be within limits
            //most categories should be right
            SatyamAggregatedResult            satyamAggResult = JSonUtils.ConvertJSonToObject <SatyamAggregatedResult>(aggResultEntry.ResultString);
            ImageSegmentationAggregatedResult aggresult       = JSonUtils.ConvertJSonToObject <ImageSegmentationAggregatedResult>(satyamAggResult.AggregatedResultString);
            SatyamResult            satyamResult = JSonUtils.ConvertJSonToObject <SatyamResult>(resultEntry.ResultString);
            ImageSegmentationResult result       = JSonUtils.ConvertJSonToObject <ImageSegmentationResult>(satyamResult.TaskResult);

            if (result == null)
            {
                return(false);
            }

            //first check if the number of boxes are within limit
            // the objects are dummy polygons just for counting
            int boxLimit = (int)Math.Ceiling((double)aggresult.boxesAndCategories.objects.Count * APPROVAL_RATIO_OF_POLYGONS_THRESHOLD);

            if (result.objects.Count < boxLimit)
            {
                return(false);
            }


            //now find how many of the results match aggregated results
            int noAccepted = 0;

            byte[] resPNG = ImageSegmentationResult.PolygonResult2Bitmap(result);

            int width = -1; int height = -1;

            byte[] aggPNG = ImageUtilities.readPNGRawDataFromURL(aggresult.metaData.PNG_URL, out width, out height);

            if (resPNG.Length != aggPNG.Length)
            {
                Console.WriteLine("res and agg res are different size");
                return(false);
            }

            SortedDictionary <int, SortedDictionary <int, int> > overlapping = new SortedDictionary <int, SortedDictionary <int, int> >();
            SortedDictionary <int, int> resObjectArea = new SortedDictionary <int, int>();
            SortedDictionary <int, int> aggObjectArea = new SortedDictionary <int, int>();

            for (int i = 0; i < width; i++)
            {
                for (int j = 0; j < height; j++)
                {
                    int idx      = j * width + i;
                    int resObjID = resPNG[idx];
                    int aggObjID = aggPNG[idx];
                    if (!overlapping.ContainsKey(resObjID))
                    {
                        overlapping.Add(resObjID, new SortedDictionary <int, int>());
                    }
                    if (!overlapping[resObjID].ContainsKey(aggObjID))
                    {
                        overlapping[resObjID].Add(aggObjID, 0);
                    }

                    overlapping[resObjID][aggObjID]++;

                    if (!resObjectArea.ContainsKey(resObjID))
                    {
                        resObjectArea.Add(resObjID, 0);
                    }
                    resObjectArea[resObjID]++;

                    if (!aggObjectArea.ContainsKey(aggObjID))
                    {
                        aggObjectArea.Add(aggObjID, 0);
                    }
                    aggObjectArea[aggObjID]++;
                }
            }

            foreach (int id in resObjectArea.Keys)
            {
                if (id == 0)
                {
                    continue;
                }

                int maxOverlap         = -1;
                int maxOverlapAggObjID = -1;


                SortedDictionary <int, int> overlapArea = overlapping[id];
                foreach (int aggid in overlapArea.Keys)
                {
                    if (aggid == 0)
                    {
                        continue;
                    }
                    if (overlapArea[aggid] > maxOverlap)
                    {
                        maxOverlap         = overlapArea[aggid];
                        maxOverlapAggObjID = aggid;
                    }
                }

                if (maxOverlapAggObjID == -1)
                {
                    continue;
                }

                double iou = (double)maxOverlap / (double)(resObjectArea[id] + aggObjectArea[maxOverlapAggObjID] - maxOverlap);

                if (iou >= POLYGON_IOU_THRESHOLD)
                {
                    noAccepted++;
                    ////now check category
                    //if (result.objects[match.elementList[0]].Category == aggresult.boxesAndCategories.objects[match.elementList[1]].Category)
                    //{
                    //    //both category and bounding box tests have passed

                    //}
                }
            }



            if (noAccepted >= boxLimit)
            {
                return(true);
            }

            return(false);
        }
예제 #3
0
        public static ImageSegmentationAggregatedResult getAggregatedResult(List <ImageSegmentationResult> originalResults,
                                                                            string SatyamURL,
                                                                            string guid,
                                                                            int MinResults = TaskConstants.IMAGE_SEGMENTATION_MTURK_MIN_RESULTS_TO_AGGREGATE,
                                                                            int MaxResults = TaskConstants.IMAGE_SEGMENTATION_MTURK_MAX_RESULTS_TO_AGGREGATE,
                                                                            double CategoryMajorityThreshold        = TaskConstants.IMAGE_SEGMENTATION_MTURK_MAJORITY_CATEGORY_THRESHOLD,
                                                                            double PolygonBoundaryMajorityThreshold = TaskConstants.IMAGE_SEGMENTATION_MTURK_MAJORITY_POLYGON_BOUNDARY_THRESHOLD,
                                                                            double ObjectsCoverageThreshold         = TaskConstants.IMAGE_SEGMENTATION_MTURK_OBJECT_COVERAGE_THRESHOLD_FOR_AGGREGATION_TERMINATION,
                                                                            double minSimilarityThreshold           = TaskConstants.IMAGE_SEGMENTATION_MTURK_POLYGON_IOU_THRESHOLD,
                                                                            int minResultsForConsensus = TaskConstants.IMAGE_SEGMENTATION_MTURK_MIN_RESULTS_FOR_CONSENSUS
                                                                            )
        {
            List <ImageSegmentationResult> results = new List <ImageSegmentationResult>();

            // Warning: filter empty results: strong assumption that there has to be something for now!!!
            for (int i = 0; i < originalResults.Count; i++)
            {
                if (originalResults[i] != null && originalResults[i].objects.Count != 0)
                {
                    results.Add(originalResults[i]);
                }
            }

            Console.WriteLine("Filetered Results: {0}", results.Count);

            if (results.Count < MinResults) //need at least three results!
            {
                return(null);
            }

            int ImageWidth  = results[0].imageWidth;
            int ImageHeight = results[0].imageHeight;

            //auto padding data to make the stride a multiple of 4. required by bmpdata for output
            int paddedWidth = ImageWidth;

            if (paddedWidth % 4 != 0)
            {
                paddedWidth = (paddedWidth / 4 + 1) * 4;
            }
            byte[] PNG = new byte[ImageHeight * paddedWidth];


            ImageSegmentationAggregatedResult aggResult = new ImageSegmentationAggregatedResult();

            aggResult.metaData            = new ImageSegmentationAggregatedResultMetaData();
            aggResult.metaData.TotalCount = results.Count;

            for (int i = 0; i < PNG.Length; i++)
            {
                PNG[i] = 0;
            }

            aggResult.boxesAndCategories         = new ImageSegmentationResult();
            aggResult.boxesAndCategories.objects = new List <ImageSegmentationResultSingleEntry>();
            aggResult.boxesAndCategories.displayScaleReductionX = results[0].displayScaleReductionX;
            aggResult.boxesAndCategories.displayScaleReductionY = results[0].displayScaleReductionY;
            aggResult.boxesAndCategories.imageHeight            = ImageHeight;
            aggResult.boxesAndCategories.imageWidth             = ImageWidth;

            //first use multipartitie wieghted matching to associated the boxes disregarding the labels since
            //people might make mistake with lables but boxes are usually right
            List <List <Segment> > AllPolygons         = new List <List <Segment> >();
            List <int>             noPolygonsPerResult = new List <int>();

            foreach (ImageSegmentationResult res in results)
            {
                AllPolygons.Add(new List <Segment>());

                if (res == null)
                {
                    noPolygonsPerResult.Add(0);
                    continue;
                }

                List <Segment> polygonList = AllPolygons[AllPolygons.Count - 1];

                foreach (ImageSegmentationResultSingleEntry entry in res.objects)
                {
                    polygonList.Add(entry.segment);
                }
                noPolygonsPerResult.Add(polygonList.Count);
            }
            //now associate boxes across the various results
            //List<MultipartiteWeightedMatch> polyAssociation = PolygonAssociation.computeGenericPolygonAssociations(AllPolygons);

            List <MultipartiteWeightedMatch> polyAssociation = GenericObjectAssociation.computeAssociations <Segment>(AllPolygons, Segment.computeIoU_PixelSweep);

            int noObjects            = polyAssociation.Count;
            int noAssociatedPolygons = 0;

            //how many of the drawn boxes for each result were actually associated by two or more people for each user?
            SortedDictionary <int, int> noMultipleAssociatedPolygonsPerResult = new SortedDictionary <int, int>();

            for (int i = 0; i < results.Count; i++)
            {
                noMultipleAssociatedPolygonsPerResult.Add(i, 0);
            }
            foreach (MultipartiteWeightedMatch match in polyAssociation)
            {
                if (match.elementList.Count > 1) //this has been corroborated by two people
                {
                    noAssociatedPolygons++;
                    foreach (KeyValuePair <int, int> entry in match.elementList)
                    {
                        noMultipleAssociatedPolygonsPerResult[entry.Key]++;
                    }
                }
            }

            //count how many people have a high association ratio
            int noHighAssociationRatio = 0;

            for (int i = 0; i < results.Count; i++)
            {
                if (noPolygonsPerResult[i] == 0)
                {
                    continue;
                }
                double ratio = (double)noMultipleAssociatedPolygonsPerResult[i] / (double)noPolygonsPerResult[i];
                if (ratio > ObjectsCoverageThreshold)
                {
                    noHighAssociationRatio++;
                }
            }
            if (noHighAssociationRatio < MinResults && results.Count < MaxResults) //at least three people should have all their boxes highly corroborated by one other person
            {
                return(null);
            }

            //int noAcceptedPolygons = 0;

            SortedDictionary <int, List <int> > noHighQualityAssociation = new SortedDictionary <int, List <int> >();

            for (int idx = 0; idx < polyAssociation.Count; idx++)
            {
                MultipartiteWeightedMatch match       = polyAssociation[idx];
                List <Segment>            polyList    = new List <Segment>();
                List <string>             identifiers = new List <string>();
                foreach (KeyValuePair <int, int> entry in match.elementList)
                {
                    polyList.Add(AllPolygons[entry.Key][entry.Value]);
                    identifiers.Add(entry.Key + "_" + entry.Value);
                }

                SegmentGroup majorityGroup = getMajorityGroupPolygons(identifiers, polyList, minSimilarityThreshold, match.weightMatrix);

                if (majorityGroup == null)
                {
                    continue;
                }

                if (majorityGroup.segments.Count < minResultsForConsensus)
                {
                    continue;
                }
                Segment aggregatedPolygon = new Segment();// dummy polygon
                byte[]  png = GetAggregatedGenericPolygon_PixelSweep(majorityGroup.segments, ImageWidth, ImageHeight, PolygonBoundaryMajorityThreshold);


                // log where the results come from
                foreach (string id in majorityGroup.identifiers)
                {
                    string[] fields = id.Split('_');
                    int      k      = Convert.ToInt32(fields[0]);
                    int      v      = Convert.ToInt32(fields[1]);
                    if (!noHighQualityAssociation.ContainsKey(k))
                    {
                        noHighQualityAssociation.Add(k, new List <int>());
                    }
                    noHighQualityAssociation[k].Add(v);
                }


                // category aggregation
                Dictionary <string, int> categoryNames = new Dictionary <string, int>();
                int    totalCount  = match.elementList.Count;
                int    maxCount    = 0;
                string maxCategory = "";
                foreach (KeyValuePair <int, int> entry in match.elementList)
                {
                    string category = results[entry.Key].objects[entry.Value].Category;
                    if (!categoryNames.ContainsKey(category))
                    {
                        categoryNames.Add(category, 0);
                    }
                    categoryNames[category]++;
                    if (maxCount < categoryNames[category])
                    {
                        maxCount    = categoryNames[category];
                        maxCategory = category;
                    }
                }
                double probability = ((double)maxCount + 1) / ((double)totalCount + 2);
                if (probability < CategoryMajorityThreshold && results.Count < MaxResults) //this is not a valid category need more work
                {
                    return(null);
                }


                // now we have one segment ready
                ImageSegmentationResultSingleEntry aggregated = new ImageSegmentationResultSingleEntry();
                aggregated.segment  = aggregatedPolygon;
                aggregated.Category = maxCategory;

                aggResult.boxesAndCategories.objects.Add(aggregated);
                for (int i = 0; i < ImageWidth; i++)
                {
                    for (int j = 0; j < ImageHeight; j++)
                    {
                        int pospng = j * ImageWidth + i;
                        int pos    = j * paddedWidth + i;
                        if (PNG[pos] == 0 && png[pospng] != 0)
                        {
                            PNG[pos] = (byte)(idx + 1);
                        }
                    }
                }
            }


            // check no. of high association results
            int noResultsWithHighQualityObjectCoverage = 0;

            for (int i = 0; i < results.Count; i++)
            {
                if (noPolygonsPerResult[i] == 0)
                {
                    continue;
                }
                if (!noHighQualityAssociation.ContainsKey(i))
                {
                    continue;
                }
                double ratio = ((double)noHighQualityAssociation[i].Count) / (double)noPolygonsPerResult[i];
                if (ratio > ObjectsCoverageThreshold)
                {
                    noResultsWithHighQualityObjectCoverage++;
                }
            }
            if (noResultsWithHighQualityObjectCoverage < MinResults && results.Count < MaxResults) //at least three people should have most of their boxes highly corroborated by one other person
            {
                return(null);
            }

            // save and upload to azure
            string filename = URIUtilities.filenameFromURINoExtension(SatyamURL);
            //string filepath = DirectoryConstants.defaultTempDirectory + filename + "_aggregated.PNG";
            string filepath = DirectoryConstants.defaultAzureTempDirectory + filename + "_aggregated.PNG";

            ImageUtilities.savePNGRawData(filepath, ImageWidth, ImageHeight, PNG);

            SatyamJobStorageAccountAccess blob = new SatyamJobStorageAccountAccess();
            string container     = SatyamTaskGenerator.JobTemplateToSatyamContainerNameMap[TaskConstants.Segmentation_Image_MTurk];
            string directoryPath = guid + "_aggregated";

            blob.UploadALocalFile(filepath, container, directoryPath);

            aggResult.metaData.PNG_URL = TaskConstants.AzureBlobURL + container + "/" + directoryPath + "/" + filename + "_aggregated.PNG";

            //clean up
            File.Delete(filepath);
            return(aggResult);
        }