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:
parent
46a8daf8ab
commit
f497380dc3
@ -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:
|
||||
|
||||
|
@ -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()
|
||||
|
@ -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
|
||||
|
53
src/main.cpp
53
src/main.cpp
@ -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
|
||||
|
2
src/ncnn
2
src/ncnn
@ -1 +1 @@
|
||||
Subproject commit 6f49529da23cb7613670a4485a2bee549e9f7236
|
||||
Subproject commit eb48cf1b98e5a595ca1a6b4036c6a63d01c23a31
|
87
src/rife.cpp
87
src/rife.cpp
@ -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);
|
||||
|
@ -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;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user