public void TestDatabaseMetaTableSerialization()
        {
            var entry = new VideoFingerPrintDatabaseMetaTableEntryWrapper
            {
                FileName = "test",
                FileSize = 1,
            };

            var entry2 = new VideoFingerPrintDatabaseMetaTableEntryWrapper
            {
                FileName = "test 2",
                FileSize = 2,
            };

            var database = new VideoFingerPrintDatabaseMetaTableWrapper
            {
                DatabaseMetaTableEntries = new[] { entry, entry2 },
            };

            using (var memoryStream = new MemoryStream())
            {
                VideoFingerPrintDatabaseMetaTableSaver.Save(database, memoryStream);
                byte[] savedDatabase = memoryStream.ToArray();
                VideoFingerPrintDatabaseMetaTableWrapper reloadedDatabase = VideoFingerPrintDatabaseMetaTableLoader.Load(savedDatabase);

                Assert.AreEqual(database, reloadedDatabase);
            }
        }
Beispiel #2
0
        private static byte[] SaveDatabaseMetaTable(VideoFingerPrintDatabaseMetaTableWrapper wrapper)
        {
            var builder = new FlatBufferBuilder(DefaultBufferSize);

            CreateDatabaseMetaTable(wrapper, builder);

            return(builder.SizedByteArray());
        }
Beispiel #3
0
 /// <summary>
 /// Saves a Database MetaTable wrapper to disk
 /// </summary>
 /// <param name="databaseMetaTable"></param>
 /// <param name="filePath"></param>
 public static void Save(VideoFingerPrintDatabaseMetaTableWrapper databaseMetaTable, string filePath)
 {
     byte[] rawDatabaseBytes = SaveDatabaseMetaTable(databaseMetaTable);
     using (BinaryWriter writer = new BinaryWriter(File.Open(filePath, FileMode.Create)))
     {
         writer.Write(rawDatabaseBytes);
     }
 }
Beispiel #4
0
        private static void CreateDatabaseMetaTable(VideoFingerPrintDatabaseMetaTableWrapper wrapper, FlatBufferBuilder builder)
        {
            Offset <VideoFingerPrintDatabaseMetaTableEntry>[] databaseMetaTableEntryArrayOffset = CreateDatabaseMetaTableEntryArray(wrapper, builder);

            VectorOffset entryArrayOffset = VideoFingerPrintDatabaseMetaTable.CreateDatabaseMetaTableEntriesVector(builder, databaseMetaTableEntryArrayOffset);

            Offset <VideoFingerPrintDatabaseMetaTable> databaseMetaTableOffset = VideoFingerPrintDatabaseMetaTable.CreateVideoFingerPrintDatabaseMetaTable(builder, entryArrayOffset);

            VideoFingerPrintDatabaseMetaTable.FinishVideoFingerPrintDatabaseMetaTableBuffer(builder, databaseMetaTableOffset);
        }
Beispiel #5
0
        private Tuple <VideoFingerPrintDatabaseWrapper, string> GetNextEligibleDatabase()
        {
            VideoFingerPrintDatabaseMetaTableWrapper        metatable        = CreateOrLoadMetatable(_metatablePath);
            Tuple <VideoFingerPrintDatabaseWrapper, string> eligibleDatabase = (from entry in metatable.DatabaseMetaTableEntries
                                                                                where entry.FileSize < MaxDatabaseSize
                                                                                select Tuple.Create(VideoFingerPrintDatabaseLoader.Load(entry.FileName), entry.FileName)).FirstOrDefault();

            // If we can't find an eligible database, then we need to create one and send it back
            return(eligibleDatabase ?? CreateNewDatabaseAndAddToMetatable());
        }
Beispiel #6
0
        private static void ExecuteCheckDatabase(string[] args)
        {
            string maxMemoryArg          = GetMaxMemory(args);
            string databaseMetaTablePath = GetDatabaseMetaTable(args);

            if (string.IsNullOrWhiteSpace(databaseMetaTablePath))
            {
                PrintHelp("Database metatable path not provided");
                return;
            }

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

            if (string.IsNullOrWhiteSpace(maxMemoryArg))
            {
                PrintHelp("--max-memory must be set");
                return;
            }

            long maxMemory = 0;

            if (long.TryParse(maxMemoryArg, out maxMemory) == false)
            {
                PrintHelp("--max-memory could not be parsed");
                return;
            }

            VideoFingerPrintDatabaseMetaTableWrapper metaTable = VideoFingerPrintDatabaseMetaTableLoader.Load(databaseMetaTablePath);
            var random = new Random();

            foreach (string databasePath in metaTable.DatabaseMetaTableEntries.Select(e => e.FileName))
            {
                VideoFingerPrintDatabaseWrapper database = VideoFingerPrintDatabaseLoader.Load(databasePath);
                int videoFingerPrintSampleCount          = (int)Math.Round(database.VideoFingerPrints.Length / 3.0);
                IEnumerable <VideoFingerPrintWrapper> videoFingerPrints = from fingerPrint in database.VideoFingerPrints
                                                                          where random.Next() % 2 == 0
                                                                          select fingerPrint;

                foreach (VideoFingerPrintWrapper videoFingerPrint in videoFingerPrints.Take(videoFingerPrintSampleCount))
                {
                    VideoFingerPrintWrapper actualVideoFingerPrint = Video.VideoIndexer.IndexVideo(videoFingerPrint.FilePath, maxMemory);

                    if (Equals(videoFingerPrint, actualVideoFingerPrint) == false)
                    {
                        Console.WriteLine("{0} Fingerprint does not match", Path.GetFileName(videoFingerPrint.FilePath));
                    }
                }
            }
        }
Beispiel #7
0
        private void UpdateMetatable(string databasePath, ulong fileSize)
        {
            VideoFingerPrintDatabaseMetaTableWrapper metatable = CreateOrLoadMetatable(_metatablePath);

            // Get matching database entry
            VideoFingerPrintDatabaseMetaTableEntryWrapper databaseEntry = (from entry in metatable.DatabaseMetaTableEntries
                                                                           where string.Equals(entry.FileName, databasePath, StringComparison.Ordinal)
                                                                           select entry).SingleOrDefault();

            databaseEntry.FileSize = fileSize;

            VideoFingerPrintDatabaseMetaTableSaver.Save(metatable, _metatablePath);
        }
Beispiel #8
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));
                }
            }
        }
Beispiel #9
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);
        }
        /// <summary>
        /// Translate a metatable into a BKTree for easier querying
        /// </summary>
        /// <param name="metatable"></param>
        /// <returns></returns>
        public static BKTree <FrameMetricWrapper> CreateBKTree(VideoFingerPrintDatabaseMetaTableWrapper metatable)
        {
            var tree = new BKTree <FrameMetricWrapper>();

            foreach (VideoFingerPrintWrapper video in MetaTableUtils.EnumerateVideoFingerPrints(metatable))
            {
                foreach (FrameFingerPrintWrapper frame in video.FingerPrints)
                {
                    tree.Add(new FrameMetricWrapper
                    {
                        Frame = frame,
                        Video = video,
                    });
                }
            }

            return(tree);
        }
Beispiel #11
0
        private static IEnumerable <string> GetKnownDatabaseEntries(string databaseMetaTablePath)
        {
            if (File.Exists(databaseMetaTablePath) == false)
            {
                return(Enumerable.Empty <string>());
            }

            var knownDatabaseEntries = new HashSet <string>();
            VideoFingerPrintDatabaseMetaTableWrapper metatable = VideoFingerPrintDatabaseMetaTableLoader.Load(databaseMetaTablePath);

            foreach (VideoFingerPrintDatabaseMetaTableEntryWrapper entry in metatable.DatabaseMetaTableEntries)
            {
                VideoFingerPrintDatabaseWrapper database = VideoFingerPrintDatabaseLoader.Load(entry.FileName);
                foreach (VideoFingerPrintWrapper fingerprint in database.VideoFingerPrints)
                {
                    knownDatabaseEntries.Add(fingerprint.FilePath);
                }
            }

            return(knownDatabaseEntries);
        }
        public static VideoFingerPrintDatabaseMetaTableWrapper Coalesce(
            string pathToMetatable
            )
        {
            VideoFingerPrintDatabaseMetaTableWrapper oldMetatable = VideoFingerPrintDatabaseMetaTableLoader.Load(pathToMetatable);
            IEnumerable <VideoFingerPrintDatabaseMetaTableEntryWrapper> databasesSelectedForCoalescing = GetDatabasesThatNeedCoalescing(oldMetatable);
            IEnumerable <VideoFingerPrintDatabaseMetaTableEntryWrapper> remainingDatabases             = oldMetatable.DatabaseMetaTableEntries.Except(databasesSelectedForCoalescing);
            IEnumerable <IEnumerable <VideoFingerPrintDatabaseMetaTableEntryWrapper> > groupedEntries  = DetermineGroups(databasesSelectedForCoalescing);
            IEnumerable <VideoFingerPrintDatabaseMetaTableEntryWrapper> coalescedDatabaseGroups        = CoalesceDatabaseGroups(groupedEntries);

            VideoFingerPrintDatabaseMetaTableWrapper newMetaTable = new VideoFingerPrintDatabaseMetaTableWrapper
            {
                DatabaseMetaTableEntries = coalescedDatabaseGroups.Concat(remainingDatabases).ToArray(),
            };

            VideoFingerPrintDatabaseMetaTableSaver.Save(newMetaTable, pathToMetatable);

            // Delete old databases
            DeleteOldDatabases(databasesSelectedForCoalescing);

            return(newMetaTable);
        }
Beispiel #13
0
        private static Offset <VideoFingerPrintDatabaseMetaTableEntry>[] CreateDatabaseMetaTableEntryArray(
            VideoFingerPrintDatabaseMetaTableWrapper databaseMetaTableWrapper,
            FlatBufferBuilder builder
            )
        {
            int databaseMetaTableEntryCounter     = 0;
            var databaseMetaTableEntryArrayOffset = new Offset <VideoFingerPrintDatabaseMetaTableEntry> [databaseMetaTableWrapper.DatabaseMetaTableEntries.Length];

            foreach (VideoFingerPrintDatabaseMetaTableEntryWrapper databaseMetaTableEntry in databaseMetaTableWrapper.DatabaseMetaTableEntries)
            {
                StringOffset fileNameOffset = builder.CreateString(databaseMetaTableEntry.FileName);

                VideoFingerPrintDatabaseMetaTableEntry.StartVideoFingerPrintDatabaseMetaTableEntry(builder);
                VideoFingerPrintDatabaseMetaTableEntry.AddFileName(builder, fileNameOffset);
                VideoFingerPrintDatabaseMetaTableEntry.AddFileSize(builder, databaseMetaTableEntry.FileSize);

                databaseMetaTableEntryArrayOffset[databaseMetaTableEntryCounter] = VideoFingerPrintDatabaseMetaTableEntry.EndVideoFingerPrintDatabaseMetaTableEntry(builder);
                databaseMetaTableEntryCounter++;
            }

            return(databaseMetaTableEntryArrayOffset);
        }
Beispiel #14
0
        private Tuple <VideoFingerPrintDatabaseWrapper, string> CreateNewDatabaseAndAddToMetatable()
        {
            VideoFingerPrintDatabaseMetaTableWrapper metatable = CreateOrLoadMetatable(_metatablePath);
            string emptyDatabaseFileName = Path.GetRandomFileName() + ".bin";
            VideoFingerPrintDatabaseWrapper emptyDatabase = new VideoFingerPrintDatabaseWrapper();

            VideoFingerPrintDatabaseSaver.Save(emptyDatabase, emptyDatabaseFileName);

            // Add to the metatable
            var databaseEntries = new List <VideoFingerPrintDatabaseMetaTableEntryWrapper>(metatable.DatabaseMetaTableEntries);

            databaseEntries.Add(new VideoFingerPrintDatabaseMetaTableEntryWrapper
            {
                FileName = emptyDatabaseFileName,
                FileSize = 0ul,
            });

            metatable.DatabaseMetaTableEntries = databaseEntries.ToArray();

            VideoFingerPrintDatabaseMetaTableSaver.Save(metatable, _metatablePath);

            return(Tuple.Create(emptyDatabase, emptyDatabaseFileName));
        }
 /// <summary>
 /// Enumerate all databases in the metatable
 /// </summary>
 /// <param name="metatable">The metatable</param>
 /// <returns>An enumeration of all of the databases</returns>
 public static IEnumerable <VideoFingerPrintDatabaseWrapper> EnumerateDatabases(VideoFingerPrintDatabaseMetaTableWrapper metatable)
 {
     return(from entry in metatable.DatabaseMetaTableEntries
            select VideoFingerPrintDatabaseLoader.Load(entry.FileName));
 }
 /// <summary>
 /// Enumerate all of the database fingerprints given a metatable
 /// </summary>
 /// <param name="metatable">The metatable</param>
 /// <returns>An enumeration of all of the fingerprints</returns>
 public static IEnumerable <VideoFingerPrintWrapper> EnumerateVideoFingerPrints(VideoFingerPrintDatabaseMetaTableWrapper metatable)
 {
     return(from database in EnumerateDatabases(metatable)
            from fingerprint in database.VideoFingerPrints
            select fingerprint);
 }
 /// <summary>
 /// Enumerate frame fingerprints
 /// </summary>
 /// <param name="metatable">The metatable</param>
 /// <returns>An enumeration of all of the frame fingerprints</returns>
 public static IEnumerable <FrameFingerPrintWrapper> EnumerateFrameFingerPrints(VideoFingerPrintDatabaseMetaTableWrapper metatable)
 {
     return(from videoFingerPrint in EnumerateVideoFingerPrints(metatable)
            from frame in videoFingerPrint.FingerPrints
            select frame);
 }
 private static IEnumerable <VideoFingerPrintDatabaseMetaTableEntryWrapper> GetDatabasesThatNeedCoalescing(VideoFingerPrintDatabaseMetaTableWrapper metatable)
 {
     return(from entry in metatable.DatabaseMetaTableEntries
            where entry.FileSize < (ulong)FileSizeLimit
            select entry);
 }
Beispiel #19
0
        /// <summary>
        /// Saves a Database MetaTable wrapper to disk
        /// </summary>
        /// <param name="databaseMetaTable"></param>
        /// <param name="outStream"></param>
        public static void Save(VideoFingerPrintDatabaseMetaTableWrapper databaseMetaTable, Stream outStream)
        {
            byte[] buffer = SaveDatabaseMetaTable(databaseMetaTable);

            outStream.Write(buffer, 0, buffer.Length);
        }