Frame order file creation now works with fractional factors, loop also works, scene detect does not

This commit is contained in:
n00mkrad
2022-04-07 14:20:28 +02:00
parent 90eb2b0f3e
commit 6e70d89cd5
4 changed files with 86 additions and 14 deletions

View File

@@ -14,7 +14,7 @@ namespace Flowframes.Data
"Experimental Pytorch Implementation of FLAVR (Nvidia Only!)", "flavr-cuda", AI.FactorSupport.Fixed, new int[] { 2, 4, 8 }); "Experimental Pytorch Implementation of FLAVR (Nvidia Only!)", "flavr-cuda", AI.FactorSupport.Fixed, new int[] { 2, 4, 8 });
public static AI dainNcnn = new AI(AI.Backend.Ncnn, "DAIN_NCNN", "DAIN (NCNN)", public static AI dainNcnn = new AI(AI.Backend.Ncnn, "DAIN_NCNN", "DAIN (NCNN)",
"Vulkan/NCNN Implementation of DAIN", "dain-ncnn", AI.FactorSupport.AnyInteger, new int[] { 2, 3, 4, 5, 6, 7, 8 }); "Vulkan/NCNN Implementation of DAIN", "dain-ncnn", AI.FactorSupport.AnyFloat, new int[] { 2, 3, 4, 5, 6, 7, 8 });
public static AI xvfiCuda = new AI(AI.Backend.Pytorch, "XVFI_CUDA", "XVFI", public static AI xvfiCuda = new AI(AI.Backend.Pytorch, "XVFI_CUDA", "XVFI",
"CUDA/Pytorch Implementation of XVFI (Nvidia Only!)", "xvfi-cuda", AI.FactorSupport.AnyInteger, new int[] { 2, 3, 4, 5, 6, 7, 8, 9, 10 }); "CUDA/Pytorch Implementation of XVFI (Nvidia Only!)", "xvfi-cuda", AI.FactorSupport.AnyInteger, new int[] { 2, 3, 4, 5, 6, 7, 8, 9, 10 });

View File

@@ -85,13 +85,22 @@ namespace Flowframes.Main
inputFilenames.Clear(); inputFilenames.Clear();
bool debug = Config.GetBool("frameOrderDebug", false); bool debug = Config.GetBool("frameOrderDebug", false);
List<Task> tasks = new List<Task>(); List<Task> tasks = new List<Task>();
int linesPerTask = 400 / (int)interpFactor; int linesPerTask = (400 / interpFactor).RoundToInt();
int num = 0; int num = 0;
for (int i = 0; i < frameFilesWithoutLast.Length; i += linesPerTask) int targetFrameCount = (frameFiles.Length * interpFactor).RoundToInt() - InterpolateUtils.GetRoundedInterpFramesPerInputFrame(interpFactor);
if(interpFactor == (int)interpFactor) // Use old multi-threaded code if factor is not fractional
{ {
tasks.Add(GenerateFrameLines(num, i, linesPerTask, (int)interpFactor, loopEnabled, sceneDetection, debug)); for (int i = 0; i < frameFilesWithoutLast.Length; i += linesPerTask)
num++; {
tasks.Add(GenerateFrameLines(num, i, linesPerTask, (int)interpFactor, sceneDetection, debug));
num++;
}
}
else
{
await GenerateFrameLinesFloat(targetFrameCount, interpFactor, sceneDetection, debug);
} }
await Task.WhenAll(tasks); await Task.WhenAll(tasks);
@@ -100,25 +109,63 @@ namespace Flowframes.Main
fileContent += frameFileContents[x]; fileContent += frameFileContents[x];
lastOutFileCount++; lastOutFileCount++;
int lastFrameTimes = Config.GetBool(Config.Key.fixOutputDuration) ? (int)interpFactor : 1;
for(int i = 0; i < lastFrameTimes; i++) if (Config.GetBool(Config.Key.fixOutputDuration)) // Match input duration by padding duping last frame until interp frames == (inputframes * factor)
{ {
fileContent += $"{(i > 0 ? "\n" : "")}file '{Paths.interpDir}/{lastOutFileCount.ToString().PadLeft(Padding.interpFrames, '0')}{ext}'"; // Last frame (source) int neededFrames = (frameFiles.Length * interpFactor).RoundToInt() - fileContent.SplitIntoLines().Where(x => x.StartsWith("'file ")).Count();
inputFilenames.Add(frameFiles.Last().Name);
for (int i = 0; i < neededFrames; i++)
fileContent += fileContent.SplitIntoLines().Where(x => x.StartsWith("'file ")).Last();
} }
//int lastFrameTimes = Config.GetBool(Config.Key.fixOutputDuration) ? (int)interpFactor : 1;
//
//for (int i = 0; i < lastFrameTimes; i++)
//{
// fileContent += $"{(i > 0 ? "\n" : "")}file '{Paths.interpDir}/{lastOutFileCount.ToString().PadLeft(Padding.interpFrames, '0')}{ext}'"; // Last frame (source)
// inputFilenames.Add(frameFiles.Last().Name);
//}
if (loop) if (loop)
{ {
fileContent = fileContent.Remove(fileContent.LastIndexOf("\n")); fileContent = fileContent.Remove(fileContent.LastIndexOf("\n"));
inputFilenames.Remove(inputFilenames.Last()); //inputFilenames.Remove(inputFilenames.Last());
} }
File.WriteAllText(framesFile, fileContent); File.WriteAllText(framesFile, fileContent);
File.WriteAllText(framesFile + ".inputframes.json", JsonConvert.SerializeObject(inputFilenames, Formatting.Indented)); File.WriteAllText(framesFile + ".inputframes.json", JsonConvert.SerializeObject(inputFilenames, Formatting.Indented));
} }
static async Task GenerateFrameLines(int number, int startIndex, int count, int factor, bool loopEnabled, bool sceneDetection, bool debug) static async Task GenerateFrameLinesFloat(int targetFrameCount, float factor, bool sceneDetection, bool debug)
{
int totalFileCount = 0;
string ext = Interpolate.current.interpExt;
float step = 1 / factor;
string fileContent = "";
//float currentFrameTime = 1f; // Start at 1 because there are no interp frames before the first input frame
for (int i = 0; i < targetFrameCount; i++)
{
if (Interpolate.canceled) return;
//if (i >= frameFilesWithoutLast.Length) break;
//string frameName = GetNameNoExt(frameFilesWithoutLast[i].Name);
float currentFrameTime = 1 + (step * i);
string filename = $"{Paths.interpDir}/{(i + 1).ToString().PadLeft(Padding.interpFrames, '0')}{ext}";
string note = $"Frame {currentFrameTime.ToString("0.0000")} {(currentFrameTime.ToString("0.0000").EndsWith("0000") ? $"[Source Frame {frameFiles[(int)currentFrameTime - 1]}]" : "[Interp]")}";
fileContent += $"file '{filename}' # {note}\n";
}
if (totalFileCount > lastOutFileCount)
lastOutFileCount = totalFileCount;
frameFileContents[0] = fileContent;
//frameFileContents[number] = fileContent;
}
static async Task GenerateFrameLines(int number, int startIndex, int count, int factor, bool sceneDetection, bool debug)
{ {
int totalFileCount = (startIndex) * factor; int totalFileCount = (startIndex) * factor;
int interpFramesAmount = factor; int interpFramesAmount = factor;
@@ -192,7 +239,7 @@ namespace Flowframes.Main
return fileContent; return fileContent;
} }
static string GetNameNoExt (string path) static string GetNameNoExt(string path)
{ {
return Path.GetFileNameWithoutExtension(path); return Path.GetFileNameWithoutExtension(path);
} }

View File

@@ -337,5 +337,13 @@ namespace Flowframes.Main
foreach (string frame in sceneFramesToDelete) foreach (string frame in sceneFramesToDelete)
IoUtils.TryDeleteIfExists(Path.Combine(sceneFramesPath, frame + I.current.framesExt)); IoUtils.TryDeleteIfExists(Path.Combine(sceneFramesPath, frame + I.current.framesExt));
} }
public static int GetRoundedInterpFramesPerInputFrame(float factor, bool roundDown = true)
{
if (roundDown)
return (int)Math.Floor(factor) - 1;
else
return factor.RoundToInt();
}
} }
} }

View File

@@ -8,6 +8,9 @@ using Flowframes.Ui;
using Flowframes.Main; using Flowframes.Main;
using Flowframes.Data; using Flowframes.Data;
using Flowframes.MiscUtils; using Flowframes.MiscUtils;
using System.Collections.Generic;
using ImageMagick;
using Paths = Flowframes.IO.Paths;
namespace Flowframes.Os namespace Flowframes.Os
{ {
@@ -251,6 +254,7 @@ namespace Flowframes.Os
//await RunRifeNcnnMulti(framesPath, outPath, factor, mdl); //await RunRifeNcnnMulti(framesPath, outPath, factor, mdl);
await RunRifeNcnnProcess(framesPath, factor, outPath, mdl); await RunRifeNcnnProcess(framesPath, factor, outPath, mdl);
await DeleteNcnnDupes(outPath, factor);
} }
catch (Exception e) catch (Exception e)
{ {
@@ -266,7 +270,7 @@ namespace Flowframes.Os
Process rifeNcnn = OsUtils.NewProcess(!OsUtils.ShowHiddenCmd()); Process rifeNcnn = OsUtils.NewProcess(!OsUtils.ShowHiddenCmd());
AiStarted(rifeNcnn, 1500, inPath); AiStarted(rifeNcnn, 1500, inPath);
SetProgressCheck(outPath, factor); SetProgressCheck(outPath, factor);
int targetFrames = ((IoUtils.GetAmountOfFiles(lastInPath, false, "*.*") * factor).RoundToInt()) - (factor.RoundToInt() - 1); // TODO: Maybe won't work with fractional factors ?? int targetFrames = ((IoUtils.GetAmountOfFiles(lastInPath, false, "*.*") * factor).RoundToInt()); // TODO: Maybe won't work with fractional factors ??
string uhdStr = await InterpolateUtils.UseUhd() ? "-u" : ""; string uhdStr = await InterpolateUtils.UseUhd() ? "-u" : "";
string ttaStr = Config.GetBool(Config.Key.rifeNcnnUseTta, false) ? "-x" : ""; string ttaStr = Config.GetBool(Config.Key.rifeNcnnUseTta, false) ? "-x" : "";
@@ -301,6 +305,7 @@ namespace Flowframes.Os
try try
{ {
await RunDainNcnnProcess(framesPath, outPath, factor, mdl, tilesize); await RunDainNcnnProcess(framesPath, outPath, factor, mdl, tilesize);
await DeleteNcnnDupes(outPath, factor);
} }
catch (Exception e) catch (Exception e)
{ {
@@ -540,5 +545,17 @@ namespace Flowframes.Os
return $"4:{progThreadsStr}:4"; ; return $"4:{progThreadsStr}:4"; ;
} }
static async Task DeleteNcnnDupes (string dir, float factor)
{
int dupeCount = InterpolateUtils.GetRoundedInterpFramesPerInputFrame(factor);
Logger.Log($"DeleteNcnnDupes: Calculated dupe count from factor; deleting last {dupeCount} interp frames ({IoUtils.GetAmountOfFiles(dir, false)} files)", true);
IoUtils.GetFileInfosSorted(dir, false).Reverse().Take(dupeCount).ToList().ForEach(x => x.Delete());
}
static double Compare(string referenceImg, string compareImg)
{
return new MagickImage(referenceImg).Compare(new MagickImage(compareImg), ErrorMetric.PeakSignalToNoiseRatio);
}
} }
} }