1
mirror of https://github.com/nihui/rife-ncnn-vulkan synced 2024-11-25 08:07:20 +01:00

model path and output filename pattern

This commit is contained in:
nihui 2020-12-05 20:29:10 +08:00
parent 46a8daf8ab
commit f497380dc3
7 changed files with 132 additions and 33 deletions

View File

@ -71,15 +71,16 @@ Usage: rife-ncnn-vulkan -0 infile -1 infile1 -o outfile [options]...
-1 input1-path input image1 path (jpg/png/webp)
-i input-path input image directory (jpg/png/webp)
-o output-path output image path (jpg/png/webp) or directory
-m model-path rife model path (default=rife-HD)
-g gpu-id gpu device to use (default=auto) can be 0,1,2 for multi-gpu
-j load:proc:save thread count for load/proc/save (default=1:2:2) can be 1:2,2,2:2 for multi-gpu
-f format output image format (jpg/png/webp, default=ext/png)
-f pattern-format output image filename pattern format (%08d.jpg/png/webp, default=ext/%08d.png)
```
- `input0-path`, `input1-path` and `output-path` accept file path
- `input-path` and `output-path` accept file directory
- `load:proc:save` = thread count for the three stages (image decoding + rife interpolation + image encoding), using larger values may increase GPU usage and consume more GPU memory. You can tune this configuration with "4:4:4" for many small-size images, and "2:2:2" for large-size images. The default setting usually works fine for most situations. If you find that your GPU is hungry, try increasing thread count to achieve faster processing.
- `format` = the format of the image to be output, png is better supported, however webp generally yields smaller file sizes, both are losslessly encoded
- `pattern-format` = the filename pattern and format of the image to be output, png is better supported, however webp generally yields smaller file sizes, both are losslessly encoded
If you encounter a crash or error, try upgrading your GPU driver:

View File

@ -177,6 +177,10 @@ if(NOT USE_SYSTEM_NCNN)
option(WITH_LAYER_mish "" OFF)
option(WITH_LAYER_statisticspooling "" OFF)
option(WITH_LAYER_swish "" OFF)
option(WITH_LAYER_gemm "" OFF)
option(WITH_LAYER_groupnorm "" OFF)
option(WITH_LAYER_layernorm "" OFF)
option(WITH_LAYER_softplus "" OFF)
add_subdirectory(ncnn)
endif()

View File

@ -156,4 +156,12 @@ static path_t sanitize_filepath(const path_t& path)
return get_executable_directory() + path;
}
static path_t sanitize_dirpath(const path_t& path)
{
if (path_is_directory(path))
return path;
return get_executable_directory() + path;
}
#endif // FILESYSTEM_UTILS_H

View File

@ -109,9 +109,10 @@ static void print_usage()
fprintf(stderr, " -1 input1-path input image1 path (jpg/png/webp)\n");
fprintf(stderr, " -i input-path input image directory (jpg/png/webp)\n");
fprintf(stderr, " -o output-path output image path (jpg/png/webp) or directory\n");
fprintf(stderr, " -m model-path rife model path (default=rife-HD)\n");
fprintf(stderr, " -g gpu-id gpu device to use (default=auto) can be 0,1,2 for multi-gpu\n");
fprintf(stderr, " -j load:proc:save thread count for load/proc/save (default=1:2:2) can be 1:2,2,2:2 for multi-gpu\n");
fprintf(stderr, " -f format output image format (jpg/png/webp, default=ext/png)\n");
fprintf(stderr, " -f pattern-format output image filename pattern format (%%08d.jpg/png/webp, default=ext/%%08d.png)\n");
}
static int decode_image(const path_t& imagepath, ncnn::Mat& image, int* webp)
@ -440,17 +441,18 @@ int main(int argc, char** argv)
path_t input1path;
path_t inputpath;
path_t outputpath;
path_t model = PATHSTR("rife-HD");
std::vector<int> gpuid;
int jobs_load = 1;
std::vector<int> jobs_proc;
int jobs_save = 2;
int verbose = 0;
path_t format = PATHSTR("png");
path_t pattern_format = PATHSTR("%08d.png");
#if _WIN32
setlocale(LC_ALL, "");
wchar_t opt;
while ((opt = getopt(argc, argv, L"0:1:i:o:g:j:f:vh")) != (wchar_t)-1)
while ((opt = getopt(argc, argv, L"0:1:i:o:m:g:j:f:vh")) != (wchar_t)-1)
{
switch (opt)
{
@ -466,6 +468,9 @@ int main(int argc, char** argv)
case L'o':
outputpath = optarg;
break;
case L'm':
model = optarg;
break;
case L'g':
gpuid = parse_optarg_int_array(optarg);
break;
@ -474,7 +479,7 @@ int main(int argc, char** argv)
jobs_proc = parse_optarg_int_array(wcschr(optarg, L':') + 1);
break;
case L'f':
format = optarg;
pattern_format = optarg;
break;
case L'v':
verbose = 1;
@ -487,7 +492,7 @@ int main(int argc, char** argv)
}
#else // _WIN32
int opt;
while ((opt = getopt(argc, argv, "0:1:i:o:g:j:f:vh")) != -1)
while ((opt = getopt(argc, argv, "0:1:i:o:m:g:j:f:vh")) != -1)
{
switch (opt)
{
@ -503,6 +508,9 @@ int main(int argc, char** argv)
case 'o':
outputpath = optarg;
break;
case 'm':
model = optarg;
break;
case 'g':
gpuid = parse_optarg_int_array(optarg);
break;
@ -511,7 +519,7 @@ int main(int argc, char** argv)
jobs_proc = parse_optarg_int_array(strchr(optarg, ':') + 1);
break;
case 'f':
format = optarg;
pattern_format = optarg;
break;
case 'v':
verbose = 1;
@ -551,6 +559,20 @@ int main(int argc, char** argv)
}
}
path_t pattern = get_file_name_without_extension(pattern_format);
path_t format = get_file_extension(pattern_format);
if (format.empty())
{
pattern = PATHSTR("%08d");
format = pattern_format;
}
if (pattern.empty())
{
pattern = PATHSTR("%08d");
}
if (!path_is_directory(outputpath))
{
// guess format from outputpath no matter what format argument specified
@ -627,13 +649,12 @@ int main(int argc, char** argv)
path_t filename0 = filenames[sx];
path_t filename1 = filenames[sx + 1];
// TODO provide option to specify output filename scheme
#if _WIN32
wchar_t tmp[256];
swprintf(tmp, L"%06d", i+1);
swprintf(tmp, pattern.c_str(), i+1);
#else
char tmp[256];
sprintf(tmp, "%06d", i+1); // ffmpeg start from 1
sprintf(tmp, pattern.c_str(), i+1); // ffmpeg start from 1
#endif
path_t output_filename = path_t(tmp) + PATHSTR('.') + format;
@ -658,6 +679,18 @@ int main(int argc, char** argv)
}
}
if (model.find(PATHSTR("rife")) != path_t::npos)
{
// fine
}
else
{
fprintf(stderr, "unknown model dir type\n");
return -1;
}
path_t modeldir = sanitize_dirpath(model);
#if _WIN32
CoInitializeEx(NULL, COINIT_MULTITHREADED);
#endif
@ -707,7 +740,7 @@ int main(int argc, char** argv)
{
rife[i] = new RIFE(gpuid[i]);
rife[i]->load();
rife[i]->load(modeldir);
}
// main routine

@ -1 +1 @@
Subproject commit 6f49529da23cb7613670a4485a2bee549e9f7236
Subproject commit eb48cf1b98e5a595ca1a6b4036c6a63d01c23a31

View File

@ -29,7 +29,55 @@ RIFE::~RIFE()
}
}
int RIFE::load()
#if _WIN32
static void load_param_model(ncnn::Net& net, const std::wstring& modeldir, const wchar_t* name)
{
wchar_t parampath[256];
wchar_t modelpath[256];
swprintf(parampath, 256, L"%s/%s.param", modeldir.c_str(), name);
swprintf(modelpath, 256, L"%s/%s.bin", modeldir.c_str(), name);
{
FILE* fp = _wfopen(parampath, L"rb");
if (!fp)
{
fwprintf(stderr, L"_wfopen %ls failed\n", parampath);
}
net.load_param(fp);
fclose(fp);
}
{
FILE* fp = _wfopen(modelpath, L"rb");
if (!fp)
{
fwprintf(stderr, L"_wfopen %ls failed\n", modelpath);
}
net.load_model(fp);
fclose(fp);
}
}
#else
static void load_param_model(ncnn::Net& net, const std::string& modeldir, const char* name)
{
char parampath[256];
char modelpath[256];
sprintf(parampath, "%s/%s.param", modeldir.c_str(), name);
sprintf(modelpath, "%s/%s.bin", modeldir.c_str(), name);
net.load_param(parampath);
net.load_model(modelpath);
}
#endif
#if _WIN32
int RIFE::load(const std::wstring& modeldir)
#else
int RIFE::load(const std::string& modeldir)
#endif
{
ncnn::Option opt;
opt.use_vulkan_compute = true;
@ -50,14 +98,15 @@ int RIFE::load()
contextnet.register_custom_layer("rife.Warp", Warp_layer_creator);
fusionnet.register_custom_layer("rife.Warp", Warp_layer_creator);
flownet.load_param("flownet.param");
flownet.load_model("flownet.bin");
contextnet.load_param("contextnet.param");
contextnet.load_model("contextnet.bin");
fusionnet.load_param("fusionnet.param");
fusionnet.load_model("fusionnet.bin");
#if _WIN32
load_param_model(flownet, modeldir, L"flownet");
load_param_model(contextnet, modeldir, L"contextnet");
load_param_model(fusionnet, modeldir, L"fusionnet");
#else
load_param_model(flownet, modeldir, "flownet");
load_param_model(contextnet, modeldir, "contextnet");
load_param_model(fusionnet, modeldir, "fusionnet");
#endif
// initialize preprocess and postprocess pipeline
{
@ -168,16 +217,6 @@ int RIFE::process(const ncnn::Mat& in0image, const ncnn::Mat& in1image, float ti
cmd.record_clone(in1, in1_gpu, opt);
}
ncnn::VkMat out_gpu;
if (opt.use_fp16_storage && opt.use_int8_storage)
{
out_gpu.create(w, h, (size_t)channels, 1, blob_vkallocator);
}
else
{
out_gpu.create(w, h, channels, (size_t)4u, 1, blob_vkallocator);
}
// preproc
ncnn::VkMat in0_gpu_padded;
ncnn::VkMat in1_gpu_padded;
@ -295,6 +334,16 @@ int RIFE::process(const ncnn::Mat& in0image, const ncnn::Mat& in1image, float ti
ex.extract("output", out_gpu_padded, cmd);
}
ncnn::VkMat out_gpu;
if (opt.use_fp16_storage && opt.use_int8_storage)
{
out_gpu.create(w, h, (size_t)channels, 1, blob_vkallocator);
}
else
{
out_gpu.create(w, h, channels, (size_t)4u, 1, blob_vkallocator);
}
// postproc
{
std::vector<ncnn::VkMat> bindings(2);

View File

@ -14,7 +14,11 @@ public:
RIFE(int gpuid);
~RIFE();
int load();
#if _WIN32
int load(const std::wstring& modeldir);
#else
int load(const std::string& modeldir);
#endif
int process(const ncnn::Mat& in0image, const ncnn::Mat& in1image, float timestep, ncnn::Mat& outimage) const;