示例#1
0
        public void BKTreeShouldQueryBestMatchesBelowGivenThreshold()
        {
            BKTree <ExampleMetric> tree = new BKTree <ExampleMetric>();

            ExampleMetric search = new ExampleMetric(new int[] { 399, 400, 400 });

            ExampleMetric best1 = new ExampleMetric(41, new int[] { 400, 400, 400 });
            ExampleMetric best2 = new ExampleMetric(42, new int[] { 403, 403, 403 });
            ExampleMetric best3 = new ExampleMetric(43, new int[] { 406, 406, 406 });

            tree.Add(new ExampleMetric(1, new int[] { 100, 100, 100 }));
            tree.Add(new ExampleMetric(2, new int[] { 200, 200, 200 }));
            tree.Add(new ExampleMetric(3, new int[] { 300, 300, 300 }));
            tree.Add(best1);
            tree.Add(best2);
            tree.Add(new ExampleMetric(5, new int[] { 500, 500, 500 }));

            // Query for match within distance of 1 (best1 is only expected result)
            IDictionary <ExampleMetric, int> results = tree.Query(search, 1);

            Assert.AreEqual(1, DistanceMetric.CalculateLeeDistance(search.Data, best1.Data));
            Assert.AreEqual(1, results.Values.ElementAt(0));
            Assert.AreEqual(41, results.Keys.ElementAt(0).Id);
            Assert.AreEqual(best1.Data, results.Keys.ElementAt(0).Data);

            // Query for match within distance of 10 (best1 & best2 are expected results)
            tree.Add(best3); // exercise adding another node after already queried
            results = tree.Query(search, 10);

            Assert.AreEqual(2, results.Count);
            Assert.AreEqual(1, DistanceMetric.CalculateLeeDistance(search.Data, best1.Data));
            Assert.AreEqual(10, DistanceMetric.CalculateLeeDistance(search.Data, best2.Data));
            Assert.IsTrue(results.Contains(new KeyValuePair <ExampleMetric, int>(best1, 1)));
            Assert.IsTrue(results.Contains(new KeyValuePair <ExampleMetric, int>(best2, 10)));

            // Query for matches within distance of 20 (best1, best2 & best3 are expected results)
            results = tree.Query(search, 20);

            Assert.AreEqual(3, results.Count);
            Assert.AreEqual(1, DistanceMetric.CalculateLeeDistance(search.Data, best1.Data));
            Assert.AreEqual(10, DistanceMetric.CalculateLeeDistance(search.Data, best2.Data));
            Assert.AreEqual(19, DistanceMetric.CalculateLeeDistance(search.Data, best3.Data));
            Assert.IsTrue(results.Contains(new KeyValuePair <ExampleMetric, int>(best1, 1)));
            Assert.IsTrue(results.Contains(new KeyValuePair <ExampleMetric, int>(best2, 10)));
            Assert.IsTrue(results.Contains(new KeyValuePair <ExampleMetric, int>(best3, 19)));
        }
示例#2
0
        private static void ExecuteSearch(string[] args)
        {
            string photoFilePath         = GetPhotoPath(args);
            string databaseMetaTablePath = GetDatabaseMetaTable(args);

            if (string.IsNullOrWhiteSpace(photoFilePath) || string.IsNullOrWhiteSpace(databaseMetaTablePath))
            {
                PrintHelp("Photo path or database metatable path not provided");
                return;
            }

            if (File.Exists(photoFilePath) == false)
            {
                PrintHelp("Photo file does not exist");
                return;
            }

            if (File.Exists(databaseMetaTablePath) == false)
            {
                PrintHelp("Database MetaTable does not exist");
                return;
            }

            using (Image frame = Image.FromFile(photoFilePath))
            {
                ulong providedPhotoHash = FrameIndexer.CalculateFramePerceptionHashOnly(frame);
                VideoFingerPrintDatabaseMetaTableWrapper metaTable = VideoFingerPrintDatabaseMetaTableLoader.Load(databaseMetaTablePath);
                BKTree <FrameMetricWrapper>           bktree       = ModelMetricUtils.CreateBKTree(metaTable);
                IDictionary <FrameMetricWrapper, int> treeResults  = bktree.Query(
                    new PhotoMetricWrapper
                {
                    Photo = new PhotoFingerPrintWrapper
                    {
                        FilePath = photoFilePath,
                        PHash    = providedPhotoHash,
                    },
                },
                    2
                    );

                foreach (KeyValuePair <FrameMetricWrapper, int> kvp in treeResults.OrderBy(e => e.Value))
                {
                    FrameMetricWrapper frameWrapper = kvp.Key;
                    int distance = kvp.Value;
                    Console.WriteLine(string.Format("Distance {0} for {1} at Frame {2}", distance, frameWrapper.Video.FilePath, frameWrapper.Frame.FrameNumber));
                }
            }
        }
示例#3
0
        private static IDictionary <string, ISet <PhotoFingerPrintWrapper> > MapPhotosToVideos(
            PhotoFingerPrintDatabaseWrapper photoDatabase,
            VideoFingerPrintDatabaseMetaTableWrapper metatable
            )
        {
            IDictionary <string, ISet <PhotoFingerPrintWrapper> > resultMap = new Dictionary <string, ISet <PhotoFingerPrintWrapper> >();
            IDictionary <string, VideoFingerPrintWrapper>         fileNameToVideoFingerPrintMap = MetaTableUtils.EnumerateVideoFingerPrints(metatable).ToDictionary(e => e.FilePath);
            BKTree <FrameMetricWrapper> bktree = ModelMetricUtils.CreateBKTree(metatable);

            foreach (PhotoFingerPrintWrapper photo in photoDatabase.PhotoFingerPrints)
            {
                // 1. Find bucket of possible candidates
                IDictionary <FrameMetricWrapper, int> treeResults = bktree.Query(
                    new PhotoMetricWrapper
                {
                    Photo = photo,
                },
                    DefaultMetricThreshold
                    );

                IDictionary <string, ISet <FrameMetricWrapper> > collapsedTreeResults = ModelMetricUtils.CollapseTreeResults(treeResults);

                // 2. Find most likely result and add it to the bucket
                if (treeResults.Count > 0)
                {
                    VideoFingerPrintWrapper mostLikelyVideo = FindMostLikelyVideo(photo, collapsedTreeResults, fileNameToVideoFingerPrintMap);

                    // In the case where we didn't get any results, we just skip this photo and move alone
                    if (mostLikelyVideo == null)
                    {
                        continue;
                    }

                    ISet <PhotoFingerPrintWrapper> bucket;
                    string videoFileName = mostLikelyVideo.FilePath;
                    if (resultMap.TryGetValue(videoFileName, out bucket) == false)
                    {
                        bucket = new HashSet <PhotoFingerPrintWrapper>();
                        resultMap.Add(videoFileName, bucket);
                    }
                }
            }

            return(resultMap);
        }