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); } }
private static byte[] SaveDatabaseMetaTable(VideoFingerPrintDatabaseMetaTableWrapper wrapper) { var builder = new FlatBufferBuilder(DefaultBufferSize); CreateDatabaseMetaTable(wrapper, builder); return(builder.SizedByteArray()); }
/// <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); } }
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); }
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()); }
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)); } } } }
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); }
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)); } } }
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); }
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); }
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); }
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); }
/// <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); }