//Path = object to be worked on ex. @C:\Users\YHM\Desktop\Videos\sample.mp4 //Filename = ex. stats.p protected override void Save(ImagestatsDict imgd) { if (rnd.Next(1, 40) == 10) { voSave.SerializableObject(imgd, pfile); } }
/// <summary> /// Returns a list of floats representing times when the video has a new key frame. /// </summary> /// <param name="dictionary"></param> /// <param name="fsensitivity"></param> /// <param name="videolength"></param> /// <returns></returns> protected List <float> KeyFramesIndex(ImagestatsDict dictionary, float fsensitivity, float videolength = 4) { List <float> list = new List <float>(); Boolean b; float i = 0; var orderedDictionary = dictionary.OrderBy(y => y.Key); KeyValuePair <float, float[]> x_1 = orderedDictionary.First(); foreach (KeyValuePair <float, float[]> x in orderedDictionary.Skip(1)) { b = Different(dictionary, x_1.Key, x.Key, i > 0 ? fsensitivity / 2 : fsensitivity); if (b) { if (i <= 0) { list.Add((float)Math.Round(x.Key, 1)); } i = videolength; } else { i -= x.Key - x_1.Key; } x_1 = x; } return(list); }
/// <summary> ///Builds an Imagestatsdict, or resumes building an incomplete imagestatsDict parameter. ///Assume that the video will not return to the exact frame after 25.6s. /// </summary> /// <param name="imagestatsDict"></param> /// <returns></returns> protected ImagestatsDict getAnalysis(ImagestatsDict imagestatsDict) { imagestatsDict = imagestatsDict ?? new ImagestatsDict(); SegmentAnalysis(imagestatsDict, 0, length, (float)25.6); Action <float> scanFrames; scanFrames = delegate(float f) { var orderedimagestatsDict = imagestatsDict.OrderBy(item => item.Key); KeyValuePair <float, float[]> oldPair = orderedimagestatsDict.First(); foreach (var item in orderedimagestatsDict.Skip(1)) { if (Different(imagestatsDict, item.Key, oldPair.Key, (float)sensitivity)) //Sensitivity is 0.25 { SegmentAnalysis(imagestatsDict, oldPair.Key, item.Key, f); } oldPair = item; } }; scanFrames((float)12.8); scanFrames((float)6.4); scanFrames((float)3.2); scanFrames((float)1.6); scanFrames((float)0.8); scanFrames((float)0.4); scanFrames((float)0.2); return(imagestatsDict); }
/// <summary> /// Examines the image statistics dictionary at time index1 and index2 and returns whether the frames are different enough. /// Based on distance between standard-deviation-of-R,G,B vectors /// </summary> /// <param name="dictionary"></param> /// <param name="index1"></param> /// <param name="index2"></param> /// <param name="fsensitivity"></param> /// <returns></returns> private Boolean Different(ImagestatsDict dictionary, float index1, float index2, float fsensitivity) { float e = (float)Math.Round(index1, 1); Boolean a = dictionary.TryGetValue(e, out float[] float1); float f = (float)Math.Round(index2, 1); Boolean b = dictionary.TryGetValue(f, out float[] float2); return(a && b && Math.Sqrt(((float1[3] - float2[3]) * (float1[3] - float2[3])) + ((float1[4] - float2[4]) * (float1[4] - float2[4])) + ((float1[5] - float2[5]) * (float1[5] - float2[5]))) > fsensitivity); }
/// <summary> /// Modifies the incompleteDict by filling in ImageAnalysis outputs from start to end per interval. /// </summary> /// <param name="incompleteDict"></param> /// <param name="start"></param> /// <param name="end"></param> /// <param name="interval"></param> private void SegmentAnalysis(ImagestatsDict incompleteDict, float start, float end, float interval) { //incompleteDict may already contain information for (float time = (float)Math.Round(start, 1); time < end + 0.1; time = (float)Math.Round(time + interval, 1)) { if (incompleteDict.ContainsKey((float)Math.Round(time, 1))) { } else { float[] iavp = ImageAnalysis(new Bitmap(VideoImage(time))); incompleteDict.Add(time, iavp); Save(incompleteDict); if (Stop()) { return; } } } }
/// <summary> /// Will try to get a float[] from pfile. /// If unsuccessful, try to get an ImagestatsDict from pfile, and getAnalysis to complete. Save float[] to pfile. <br/> /// </summary> /// <returns></returns> public override List <float> KeyFramesIndex() { // try { List <float> kfi = voSave.DeserializeObject <List <float> >(pfile); return(kfi); } catch { } ImagestatsDict dictionary = new ImagestatsDict(); try { dictionary = voSave.DeserializeObject <ImagestatsDict>(pfile); } catch { } List <float> outkfi = KeyFramesIndex(getAnalysis(dictionary), (float)0.5); voSave.SerializableObject(outkfi, pfile); return(outkfi); }
/// <summary> /// Save runs every time a frame is analyzed in getAnalysis. /// Ex. you can inherit and overide to serialize imgd to a file every 50 executions of save /// </summary> protected virtual void Save(ImagestatsDict imgd) { }