全体の設計を変更

This commit is contained in:
lltcggie 2015-06-03 03:01:56 +09:00
parent a78fbbf322
commit a2b222ee12
4 changed files with 428 additions and 353 deletions

View File

@ -11,6 +11,8 @@
#if defined(WIN32) || defined(WIN64) #if defined(WIN32) || defined(WIN64)
#include <Windows.h> #include <Windows.h>
#undef LoadImage
#endif #endif
#ifdef _MSC_VER #ifdef _MSC_VER
@ -42,12 +44,21 @@ const auto original_width_height = 128 + layer_num * 2;
const int ConvertMode = CV_RGB2YUV; const int ConvertMode = CV_RGB2YUV;
const int ConvertInverseMode = CV_YUV2RGB; const int ConvertInverseMode = CV_YUV2RGB;
std::once_flag waifu2x_once_flag; static std::once_flag waifu2x_once_flag;
std::once_flag waifu2x_cudnn_once_flag; static std::once_flag waifu2x_cudnn_once_flag;
Waifu2x::Waifu2x() : is_inited(false)
{
}
Waifu2x::~Waifu2x()
{
destroy();
}
// cuDNNが使えるかチェック。現状Windowsのみ // cuDNNが使えるかチェック。現状Windowsのみ
bool can_use_cuDNN() bool Waifu2x::can_use_cuDNN()
{ {
static bool cuDNNFlag = false; static bool cuDNNFlag = false;
std::call_once(waifu2x_cudnn_once_flag, [&]() std::call_once(waifu2x_cudnn_once_flag, [&]()
@ -80,7 +91,7 @@ bool can_use_cuDNN()
} }
// 画像を読み込んで値を0.0f1.0fの範囲に変換 // 画像を読み込んで値を0.0f1.0fの範囲に変換
eWaifu2xError LoadImage(cv::Mat &float_image, const std::string &input_file) Waifu2x::eWaifu2xError Waifu2x::LoadImage(cv::Mat &float_image, const std::string &input_file)
{ {
cv::Mat original_image = cv::imread(input_file, cv::IMREAD_UNCHANGED); cv::Mat original_image = cv::imread(input_file, cv::IMREAD_UNCHANGED);
if (original_image.empty()) if (original_image.empty())
@ -115,7 +126,7 @@ eWaifu2xError LoadImage(cv::Mat &float_image, const std::string &input_file)
} }
// 画像から輝度の画像を取り出す // 画像から輝度の画像を取り出す
eWaifu2xError CreateBrightnessImage(const cv::Mat &float_image, cv::Mat &im) Waifu2x::eWaifu2xError Waifu2x::CreateBrightnessImage(const cv::Mat &float_image, cv::Mat &im)
{ {
cv::Mat converted_color; cv::Mat converted_color;
cv::cvtColor(float_image, converted_color, ConvertMode); cv::cvtColor(float_image, converted_color, ConvertMode);
@ -131,7 +142,7 @@ eWaifu2xError CreateBrightnessImage(const cv::Mat &float_image, cv::Mat &im)
// 入力画像の(Photoshopでいう)キャンバスサイズをoutput_sizeの倍数に変更 // 入力画像の(Photoshopでいう)キャンバスサイズをoutput_sizeの倍数に変更
// 画像は左上配置、余白はcv::BORDER_REPLICATEで埋める // 画像は左上配置、余白はcv::BORDER_REPLICATEで埋める
eWaifu2xError PaddingImage(const cv::Mat &input, cv::Mat &output) Waifu2x::eWaifu2xError Waifu2x::PaddingImage(const cv::Mat &input, cv::Mat &output)
{ {
const auto h_blocks = (int)floor(input.size().width / output_size) + (input.size().width % output_size == 0 ? 0 : 1); const auto h_blocks = (int)floor(input.size().width / output_size) + (input.size().width % output_size == 0 ? 0 : 1);
const auto w_blocks = (int)floor(input.size().height / output_size) + (input.size().height % output_size == 0 ? 0 : 1); const auto w_blocks = (int)floor(input.size().height / output_size) + (input.size().height % output_size == 0 ? 0 : 1);
@ -148,7 +159,7 @@ eWaifu2xError PaddingImage(const cv::Mat &input, cv::Mat &output)
} }
// 画像をcv::INTER_NEARESTで二倍に拡大して、PaddingImage()でパディングする // 画像をcv::INTER_NEARESTで二倍に拡大して、PaddingImage()でパディングする
eWaifu2xError Zoom2xAndPaddingImage(const cv::Mat &input, cv::Mat &output, cv::Size_<int> &zoom_size) Waifu2x::eWaifu2xError Waifu2x::Zoom2xAndPaddingImage(const cv::Mat &input, cv::Mat &output, cv::Size_<int> &zoom_size)
{ {
zoom_size = input.size(); zoom_size = input.size();
zoom_size.width *= 2; zoom_size.width *= 2;
@ -161,7 +172,7 @@ eWaifu2xError Zoom2xAndPaddingImage(const cv::Mat &input, cv::Mat &output, cv::S
} }
// 入力画像をzoom_sizeの大きさにcv::INTER_CUBICで拡大し、色情報のみを残す // 入力画像をzoom_sizeの大きさにcv::INTER_CUBICで拡大し、色情報のみを残す
eWaifu2xError CreateZoomColorImage(const cv::Mat &float_image, const cv::Size_<int> &zoom_size, std::vector<cv::Mat> &cubic_planes) Waifu2x::eWaifu2xError Waifu2x::CreateZoomColorImage(const cv::Mat &float_image, const cv::Size_<int> &zoom_size, std::vector<cv::Mat> &cubic_planes)
{ {
cv::Mat zoom_cubic_image; cv::Mat zoom_cubic_image;
cv::resize(float_image, zoom_cubic_image, zoom_size, 0.0, 0.0, cv::INTER_CUBIC); cv::resize(float_image, zoom_cubic_image, zoom_size, 0.0, 0.0, cv::INTER_CUBIC);
@ -180,7 +191,7 @@ eWaifu2xError CreateZoomColorImage(const cv::Mat &float_image, const cv::Size_<i
} }
// 学習したパラメータをファイルから読み込む // 学習したパラメータをファイルから読み込む
eWaifu2xError LoadParameter(boost::shared_ptr<caffe::Net<float>> net, const std::string &param_path) Waifu2x::eWaifu2xError Waifu2x::LoadParameter(boost::shared_ptr<caffe::Net<float>> net, const std::string &param_path)
{ {
rapidjson::Document d; rapidjson::Document d;
std::vector<char> jsonBuf; std::vector<char> jsonBuf;
@ -295,7 +306,7 @@ eWaifu2xError LoadParameter(boost::shared_ptr<caffe::Net<float>> net, const std:
// モデルファイルからネットワークを構築 // モデルファイルからネットワークを構築
// processでcudnnが指定されなかった場合はcuDNNが呼び出されないように変更する // processでcudnnが指定されなかった場合はcuDNNが呼び出されないように変更する
eWaifu2xError ConstractNet(boost::shared_ptr<caffe::Net<float>> &net, const std::string &model_path, const std::string &process) Waifu2x::eWaifu2xError Waifu2x::ConstractNet(boost::shared_ptr<caffe::Net<float>> &net, const std::string &model_path, const std::string &process)
{ {
caffe::NetParameter param; caffe::NetParameter param;
if (!caffe::ReadProtoFromTextFile(model_path, &param)) if (!caffe::ReadProtoFromTextFile(model_path, &param))
@ -337,7 +348,7 @@ eWaifu2xError ConstractNet(boost::shared_ptr<caffe::Net<float>> &net, const std:
} }
// ネットワークを使って画像を再構築する // ネットワークを使って画像を再構築する
eWaifu2xError ReconstructImage(boost::shared_ptr<caffe::Net<float>> net, cv::Mat &im, const waifu2xProgressFunc func) Waifu2x::eWaifu2xError Waifu2x::ReconstructImage(boost::shared_ptr<caffe::Net<float>> net, cv::Mat &im)
{ {
const auto Height = im.size().height; const auto Height = im.size().height;
const auto Width = im.size().width; const auto Width = im.size().width;
@ -464,18 +475,21 @@ eWaifu2xError ReconstructImage(boost::shared_ptr<caffe::Net<float>> net, cv::Mat
return eWaifu2xError_OK; return eWaifu2xError_OK;
} }
#include <boost/timer.hpp> Waifu2x::eWaifu2xError Waifu2x::init(int argc, char** argv, const std::string &Mode, const int NoiseLevel, const double ScaleRatio, const std::string &ModelDir, const std::string &Process)
eWaifu2xError waifu2x(int argc, char** argv, const std::vector<InputOutputPathPair> &file_paths,
const std::string &mode, const int noise_level, const double scale_ratio, const std::string &model_dir, const std::string &process,
std::vector<PathAndErrorPair> &errors, const waifu2xCancelFunc cancel_func, const waifu2xProgressFunc progress_func, const waifu2xTimeFunc time_func)
{ {
if (scale_ratio <= 0.0) Waifu2x::eWaifu2xError ret;
if (is_inited)
return eWaifu2xError_OK;
if (ScaleRatio <= 0.0)
return eWaifu2xError_InvalidParameter; return eWaifu2xError_InvalidParameter;
const auto StartTime = std::chrono::system_clock::now(); mode = Mode;
noise_level = NoiseLevel;
eWaifu2xError ret; scale_ratio = ScaleRatio;
model_dir = ModelDir;
process = Process;
std::call_once(waifu2x_once_flag, [argc, argv]() std::call_once(waifu2x_once_flag, [argc, argv]()
{ {
@ -490,12 +504,11 @@ eWaifu2xError waifu2x(int argc, char** argv, const std::vector<InputOutputPathPa
const auto cuDNNCheckStartTime = std::chrono::system_clock::now(); const auto cuDNNCheckStartTime = std::chrono::system_clock::now();
std::string process_fix(process); if (process == "gpu")
if (process_fix == "gpu")
{ {
// cuDNNが使えそうならcuDNNを使う // cuDNNが使えそうならcuDNNを使う
if (can_use_cuDNN()) if (can_use_cuDNN())
process_fix = "cudnn"; process = "cudnn";
} }
const auto cuDNNCheckEndTime = std::chrono::system_clock::now(); const auto cuDNNCheckEndTime = std::chrono::system_clock::now();
@ -516,20 +529,17 @@ eWaifu2xError waifu2x(int argc, char** argv, const std::vector<InputOutputPathPa
if (!boost::filesystem::exists(mode_dir_path)) if (!boost::filesystem::exists(mode_dir_path))
return eWaifu2xError_FailedOpenModelFile; return eWaifu2xError_FailedOpenModelFile;
if (process_fix == "cpu") if (process == "cpu")
caffe::Caffe::set_mode(caffe::Caffe::CPU); caffe::Caffe::set_mode(caffe::Caffe::CPU);
else else
caffe::Caffe::set_mode(caffe::Caffe::GPU); caffe::Caffe::set_mode(caffe::Caffe::GPU);
boost::shared_ptr<caffe::Net<float>> net_noise;
boost::shared_ptr<caffe::Net<float>> net_scale;
if (mode == "noise" || mode == "noise_scale" || mode == "auto_scale") if (mode == "noise" || mode == "noise_scale" || mode == "auto_scale")
{ {
const std::string model_path = (mode_dir_path / "srcnn.prototxt").string(); const std::string model_path = (mode_dir_path / "srcnn.prototxt").string();
const std::string param_path = (mode_dir_path / ("noise" + std::to_string(noise_level) + "_model.json")).string(); const std::string param_path = (mode_dir_path / ("noise" + std::to_string(noise_level) + "_model.json")).string();
ret = ConstractNet(net_noise, model_path, process_fix); ret = ConstractNet(net_noise, model_path, process);
if (ret != eWaifu2xError_OK) if (ret != eWaifu2xError_OK)
return ret; return ret;
@ -543,7 +553,7 @@ eWaifu2xError waifu2x(int argc, char** argv, const std::vector<InputOutputPathPa
const std::string model_path = (mode_dir_path / "srcnn.prototxt").string(); const std::string model_path = (mode_dir_path / "srcnn.prototxt").string();
const std::string param_path = (mode_dir_path / "scale2.0x_model.json").string(); const std::string param_path = (mode_dir_path / "scale2.0x_model.json").string();
ret = ConstractNet(net_scale, model_path, process_fix); ret = ConstractNet(net_scale, model_path, process);
if (ret != eWaifu2xError_OK) if (ret != eWaifu2xError_OK)
return ret; return ret;
@ -552,27 +562,31 @@ eWaifu2xError waifu2x(int argc, char** argv, const std::vector<InputOutputPathPa
return ret; return ret;
} }
const auto InitEndTime = std::chrono::system_clock::now(); is_inited = true;
int fileCount = 0; return eWaifu2xError_OK;
for (const auto &p : file_paths) }
void Waifu2x::destroy()
{ {
if (progress_func) net_noise.reset();
progress_func(file_paths.size(), fileCount); net_scale.reset();
if (cancel_func && cancel_func()) is_inited = false;
return eWaifu2xError_Cancel; }
const auto &input_file = p.first; Waifu2x::eWaifu2xError Waifu2x::waifu2x(const std::string &input_file, const std::string &output_file,
const auto &output_file = p.second; const waifu2xCancelFunc cancel_func)
{
Waifu2x::eWaifu2xError ret;
if (!is_inited)
return eWaifu2xError_NotInitialized;
cv::Mat float_image; cv::Mat float_image;
ret = LoadImage(float_image, input_file); ret = LoadImage(float_image, input_file);
if (ret != eWaifu2xError_OK) if (ret != eWaifu2xError_OK)
{ return ret;
errors.emplace_back(p, ret);
continue;
}
cv::Mat im; cv::Mat im;
CreateBrightnessImage(float_image, im); CreateBrightnessImage(float_image, im);
@ -591,12 +605,9 @@ eWaifu2xError waifu2x(int argc, char** argv, const std::vector<InputOutputPathPa
{ {
PaddingImage(im, im); PaddingImage(im, im);
ret = ReconstructImage(net_noise, im, progress_func); ret = ReconstructImage(net_noise, im);
if (ret != eWaifu2xError_OK) if (ret != eWaifu2xError_OK)
{ return ret;
errors.emplace_back(p, ret);
continue;
}
// パディングを取り払う // パディングを取り払う
im = im(cv::Rect(offset, offset, image_size.width, image_size.height)); im = im(cv::Rect(offset, offset, image_size.width, image_size.height));
@ -615,20 +626,13 @@ eWaifu2xError waifu2x(int argc, char** argv, const std::vector<InputOutputPathPa
{ {
Zoom2xAndPaddingImage(im, im, image_size); Zoom2xAndPaddingImage(im, im, image_size);
ret = ReconstructImage(net_scale, im, progress_func); ret = ReconstructImage(net_scale, im);
if (ret != eWaifu2xError_OK) if (ret != eWaifu2xError_OK)
{ return ret;
errors.emplace_back(p, ret);
isError = true;
break;
}
// パディングを取り払う // パディングを取り払う
im = im(cv::Rect(offset, offset, image_size.width, image_size.height)); im = im(cv::Rect(offset, offset, image_size.width, image_size.height));
} }
if (isError)
continue;
} }
if (cancel_func && cancel_func()) if (cancel_func && cancel_func())
@ -689,28 +693,14 @@ eWaifu2xError waifu2x(int argc, char** argv, const std::vector<InputOutputPathPa
process_image.release(); process_image.release();
if (!cv::imwrite(output_file, write_iamge)) if (!cv::imwrite(output_file, write_iamge))
{ return eWaifu2xError_FailedOpenOutputFile;
errors.emplace_back(p, eWaifu2xError_FailedOpenOutputFile);
continue;
}
write_iamge.release(); write_iamge.release();
fileCount++;
}
if (progress_func)
progress_func(file_paths.size(), fileCount);
const auto ProcessEndTime = std::chrono::system_clock::now();
const auto cuDNNCheckTime = (cuDNNCheckEndTime - cuDNNCheckStartTime);
const auto InitTime = (InitEndTime - StartTime) - cuDNNCheckTime;
const auto ProcessTime = (ProcessEndTime - InitEndTime);
if (time_func)
time_func(std::chrono::duration_cast<std::chrono::milliseconds>(InitTime).count()
, std::chrono::duration_cast<std::chrono::milliseconds>(cuDNNCheckTime).count()
, std::chrono::duration_cast<std::chrono::milliseconds>(ProcessTime).count(), process_fix);
return eWaifu2xError_OK; return eWaifu2xError_OK;
} }
const std::string& Waifu2x::used_process() const
{
return process;
}

View File

@ -5,11 +5,24 @@
#include <vector> #include <vector>
#include <utility> #include <utility>
#include <functional> #include <functional>
#include <boost/shared_ptr.hpp>
#include <opencv2/opencv.hpp>
namespace caffe
{
template <typename Dtype>
class Net;
};
class Waifu2x
{
public:
enum eWaifu2xError enum eWaifu2xError
{ {
eWaifu2xError_OK = 0, eWaifu2xError_OK = 0,
eWaifu2xError_Cancel, eWaifu2xError_Cancel,
eWaifu2xError_NotInitialized,
eWaifu2xError_InvalidParameter, eWaifu2xError_InvalidParameter,
eWaifu2xError_FailedOpenInputFile, eWaifu2xError_FailedOpenInputFile,
eWaifu2xError_FailedOpenOutputFile, eWaifu2xError_FailedOpenOutputFile,
@ -19,16 +32,44 @@ enum eWaifu2xError
eWaifu2xError_FailedProcessCaffe, eWaifu2xError_FailedProcessCaffe,
}; };
typedef std::pair<std::string, std::string> InputOutputPathPair;
typedef std::pair<InputOutputPathPair, eWaifu2xError> PathAndErrorPair;
typedef std::function<bool()> waifu2xCancelFunc; typedef std::function<bool()> waifu2xCancelFunc;
typedef std::function<void(const int ProgressFileMax, const int ProgressFileNow)> waifu2xProgressFunc;
typedef std::function<void(const uint64_t InitTime, const uint64_t cuDNNCheckTime, const uint64_t ProcessTime, const std::string &Process)> waifu2xTimeFunc;
bool can_use_cuDNN(); private:
bool is_inited;
std::string mode;
int noise_level;
double scale_ratio;
std::string model_dir;
std::string process;
boost::shared_ptr<caffe::Net<float>> net_noise;
boost::shared_ptr<caffe::Net<float>> net_scale;
private:
eWaifu2xError LoadImage(cv::Mat &float_image, const std::string &input_file);
eWaifu2xError CreateBrightnessImage(const cv::Mat &float_image, cv::Mat &im);
eWaifu2xError PaddingImage(const cv::Mat &input, cv::Mat &output);
eWaifu2xError Zoom2xAndPaddingImage(const cv::Mat &input, cv::Mat &output, cv::Size_<int> &zoom_size);
eWaifu2xError CreateZoomColorImage(const cv::Mat &float_image, const cv::Size_<int> &zoom_size, std::vector<cv::Mat> &cubic_planes);
eWaifu2xError LoadParameter(boost::shared_ptr<caffe::Net<float>> net, const std::string &param_path);
eWaifu2xError ConstractNet(boost::shared_ptr<caffe::Net<float>> &net, const std::string &model_path, const std::string &process);
eWaifu2xError ReconstructImage(boost::shared_ptr<caffe::Net<float>> net, cv::Mat &im);
public:
Waifu2x();
~Waifu2x();
static bool can_use_cuDNN();
// mode: noise or scale or noise_scale or auto_scale // mode: noise or scale or noise_scale or auto_scale
// process: cpu or gpu or cudnn // process: cpu or gpu or cudnn
eWaifu2xError waifu2x(int argc, char** argv, eWaifu2xError init(int argc, char** argv, const std::string &mode, const int noise_level, const double scale_ratio, const std::string &model_dir, const std::string &process);
const std::vector<InputOutputPathPair> &file_paths, const std::string &mode, const int noise_level, const double scale_ratio, const std::string &model_dir, const std::string &process,
std::vector<PathAndErrorPair> &errors, const waifu2xCancelFunc cancel_func = nullptr, const waifu2xProgressFunc progress_func = nullptr, const waifu2xTimeFunc time_func = nullptr); void destroy();
eWaifu2xError waifu2x(const std::string &input_file, const std::string &output_file,
const waifu2xCancelFunc cancel_func = nullptr);
const std::string& used_process() const;
};

View File

@ -5,6 +5,7 @@
#include <string> #include <string>
#include <thread> #include <thread>
#include <atomic> #include <atomic>
#include <chrono>
#include <boost/filesystem.hpp> #include <boost/filesystem.hpp>
#include <boost/tokenizer.hpp> #include <boost/tokenizer.hpp>
#include <boost/foreach.hpp> #include <boost/foreach.hpp>
@ -15,9 +16,8 @@
#include "CControl.h" #include "CControl.h"
#define WM_FAILD_CREATE_DIR (WM_APP + 5) #define WM_FAILD_CREATE_DIR (WM_APP + 5)
#define WM_END_WAIFU2X (WM_APP + 6) #define WM_ON_WAIFU2X_ERROR (WM_APP + 6)
#define WM_END_THREAD (WM_APP + 7) #define WM_END_THREAD (WM_APP + 7)
#define WM_TIME_WAIFU2X (WM_APP + 8)
const size_t AR_PATH_MAX(1024); const size_t AR_PATH_MAX(1024);
@ -83,13 +83,12 @@ private:
std::string autoSetAddName; std::string autoSetAddName;
bool isLastError; bool isLastError;
struct stWaifu2xTime std::string logMessage;
{
uint64_t InitTime; std::string usedProcess;
uint64_t cuDNNCheckTime; std::chrono::system_clock::duration cuDNNCheckTime;
uint64_t ProcessTime; std::chrono::system_clock::duration InitTime;
std::string Process; std::chrono::system_clock::duration ProcessTime;
};
private: private:
std::string AddName() const std::string AddName() const
@ -184,7 +183,7 @@ private:
{ {
const boost::filesystem::path input_path(boost::filesystem::absolute(input_str)); const boost::filesystem::path input_path(boost::filesystem::absolute(input_str));
std::vector<InputOutputPathPair> file_paths; std::vector<std::pair<std::string, std::string>> file_paths;
if (boost::filesystem::is_directory(input_path)) // input_pathがフォルダならそのディレクトリ以下の画像ファイルを一括変換 if (boost::filesystem::is_directory(input_path)) // input_pathがフォルダならそのディレクトリ以下の画像ファイルを一括変換
{ {
boost::filesystem::path output_path(output_str); boost::filesystem::path output_path(output_str);
@ -273,24 +272,46 @@ private:
SendMessage(GetDlgItem(dh, IDC_PROGRESS), PBM_SETPOS, ProgressFileNow, 0); SendMessage(GetDlgItem(dh, IDC_PROGRESS), PBM_SETPOS, ProgressFileNow, 0);
}; };
const auto TimeFunc = [this](const uint64_t InitTime, const uint64_t cuDNNCheckTime, const uint64_t ProcessTime, const std::string &Process) const auto cuDNNCheckStartTime = std::chrono::system_clock::now();
if (process == "gpu")
Waifu2x::can_use_cuDNN();
const auto cuDNNCheckEndTime = std::chrono::system_clock::now();
Waifu2x::eWaifu2xError ret;
Waifu2x w;
ret = w.init(__argc, __argv, mode, noise_level, scale_ratio, "models", process);
if(ret != Waifu2x::eWaifu2xError_OK)
SendMessage(dh, WM_ON_WAIFU2X_ERROR, (WPARAM)&ret, 0);
else
{ {
stWaifu2xTime t; const auto InitEndTime = std::chrono::system_clock::now();
t.InitTime = InitTime;
t.cuDNNCheckTime = cuDNNCheckTime;
t.ProcessTime = ProcessTime;
t.Process = Process;
SendMessage(dh, WM_TIME_WAIFU2X, (WPARAM)&t, 0); for (const auto &p : file_paths)
}; {
ret = w.waifu2x(p.first, p.second, [this]()
std::vector<PathAndErrorPair> errors;
const eWaifu2xError ret = waifu2x(__argc, __argv, file_paths, mode, noise_level, scale_ratio, "models", process, errors, [this]()
{ {
return cancelFlag; return cancelFlag;
}, ProgessFunc, TimeFunc); });
SendMessage(dh, WM_END_WAIFU2X, (WPARAM)&ret, (LPARAM)&errors); if (ret != Waifu2x::eWaifu2xError_OK)
{
SendMessage(dh, WM_ON_WAIFU2X_ERROR, (WPARAM)&ret, (LPARAM)&p);
if (ret == Waifu2x::eWaifu2xError_Cancel)
break;
}
}
const auto ProcessEndTime = std::chrono::system_clock::now();
cuDNNCheckTime = cuDNNCheckEndTime - cuDNNCheckStartTime;
InitTime = InitEndTime - cuDNNCheckEndTime;
ProcessTime = ProcessEndTime - InitEndTime;
usedProcess = w.used_process();
}
PostMessage(dh, WM_END_THREAD, 0, 0); PostMessage(dh, WM_END_THREAD, 0, 0);
} }
@ -317,6 +338,64 @@ private:
} }
} }
void AddLogMessage(const char *msg)
{
if (logMessage.length() == 0)
logMessage += msg;
else
logMessage += std::string("\r\n") + msg;
SetWindowTextA(GetDlgItem(dh, IDC_EDIT_LOG), logMessage.c_str());
}
void Waifu2xTime()
{
char msg[1024 * 2];
char *ptr = msg;
{
std::string p(usedProcess);
if (p == "cpu")
p = "CPU";
else if (p == "gpu")
p = "GPU";
else if (p == "cudnn")
p = "cuDNN";
ptr += sprintf(ptr, "使用プロセッサーモード: %s\r\n", p.c_str());
}
{
uint64_t t = std::chrono::duration_cast<std::chrono::milliseconds>(ProcessTime).count();
const int msec = t % 1000; t /= 1000;
const int sec = t % 60; t /= 60;
const int min = t % 60; t /= 60;
const int hour = (int)t;
ptr += sprintf(ptr, "処理時間: %02d:%02d:%02d.%d\r\n", hour, min, sec, msec);
}
{
uint64_t t = std::chrono::duration_cast<std::chrono::milliseconds>(InitTime).count();
const int msec = t % 1000; t /= 1000;
const int sec = t % 60; t /= 60;
const int min = t % 60; t /= 60;
const int hour = (int)t;
ptr += sprintf(ptr, "初期化時間: %02d:%02d:%02d.%d\r\n", hour, min, sec, msec);
}
if (process == "gpu" || process == "cudnn")
{
uint64_t t = std::chrono::duration_cast<std::chrono::milliseconds>(cuDNNCheckTime).count();
const int msec = t % 1000; t /= 1000;
const int sec = t % 60; t /= 60;
const int min = t % 60; t /= 60;
const int hour = (int)t;
ptr += sprintf(ptr, "cuDNNチェック時間: %02d:%02d:%02d.%d", hour, min, sec, msec);
}
AddLogMessage(msg);
}
public: public:
DialogEvent() : dh(nullptr), mode("noise_scale"), noise_level(1), scale_ratio(2.0), process("gpu"), outputExt("png"), inputFileExt("png:jpg:jpeg:tif:tiff:bmp"), isLastError(false) DialogEvent() : dh(nullptr), mode("noise_scale"), noise_level(1), scale_ratio(2.0), process("gpu"), outputExt("png"), inputFileExt("png:jpg:jpeg:tif:tiff:bmp"), isLastError(false)
{ {
@ -357,6 +436,7 @@ public:
EnableWindow(GetDlgItem(dh, IDC_BUTTON_EXEC), FALSE); EnableWindow(GetDlgItem(dh, IDC_BUTTON_EXEC), FALSE);
SetWindowTextA(GetDlgItem(hWnd, IDC_EDIT_LOG), ""); SetWindowTextA(GetDlgItem(hWnd, IDC_EDIT_LOG), "");
logMessage.clear();
} }
void WaitThreadExit(HWND hWnd, WPARAM wParam, LPARAM lParam, LPVOID lpData) void WaitThreadExit(HWND hWnd, WPARAM wParam, LPARAM lParam, LPVOID lpData)
@ -366,57 +446,15 @@ public:
EnableWindow(GetDlgItem(dh, IDC_BUTTON_EXEC), TRUE); EnableWindow(GetDlgItem(dh, IDC_BUTTON_EXEC), TRUE);
if (!isLastError) if (!isLastError)
{
if (!cancelFlag)
AddLogMessage("変換に成功しました");
Waifu2xTime();
MessageBeep(MB_ICONASTERISK); MessageBeep(MB_ICONASTERISK);
} }
else
void Waifu2xTime(HWND hWnd, WPARAM wParam, LPARAM lParam, LPVOID lpData) MessageBoxA(dh, "エラーが発生しました", "エラー", MB_OK | MB_ICONERROR);
{
const stWaifu2xTime *tp = (const stWaifu2xTime *)wParam;
char msg[1024*2];
char *ptr = msg;
{
std::string p(tp->Process);
if (p == "cpu")
p = "CPU";
else if (p == "gpu")
p = "GPU";
else if (p == "cudnn")
p = "cuDNN";
ptr += sprintf(ptr, "使用プロセッサーモード: %s\r\n", p.c_str());
}
{
uint64_t t = tp->ProcessTime;
const int msec = t % 1000; t /= 1000;
const int sec = t % 60; t /= 60;
const int min = t % 60; t /= 60;
const int hour = (int)t;
ptr += sprintf(ptr, "処理時間: %02d:%02d:%02d.%d\r\n", hour, min, sec, msec);
}
{
uint64_t t = tp->InitTime;
const int msec = t % 1000; t /= 1000;
const int sec = t % 60; t /= 60;
const int min = t % 60; t /= 60;
const int hour = (int)t;
ptr += sprintf(ptr, "初期化時間: %02d:%02d:%02d.%d\r\n", hour, min, sec, msec);
}
if (tp->Process == "gpu" || tp->Process == "cudnn")
{
uint64_t t = tp->cuDNNCheckTime;
const int msec = t % 1000; t /= 1000;
const int sec = t % 60; t /= 60;
const int min = t % 60; t /= 60;
const int hour = (int)t;
ptr += sprintf(ptr, "cuDNNチェック時間: %02d:%02d:%02d.%d", hour, min, sec, msec);
}
SetWindowTextA(GetDlgItem(hWnd, IDC_EDIT_LOG), msg);
} }
void OnDialogEnd(HWND hWnd, WPARAM wParam, LPARAM lParam, LPVOID lpData) void OnDialogEnd(HWND hWnd, WPARAM wParam, LPARAM lParam, LPVOID lpData)
@ -441,62 +479,62 @@ public:
isLastError = true; isLastError = true;
} }
void OnEndWaifu2x(HWND hWnd, WPARAM wParam, LPARAM lParam, LPVOID lpData) void OnWaifu2xError(HWND hWnd, WPARAM wParam, LPARAM lParam, LPVOID lpData)
{ {
const eWaifu2xError ret = *(const eWaifu2xError *)wParam; const Waifu2x::eWaifu2xError ret = *(const Waifu2x::eWaifu2xError *)wParam;
const std::vector<PathAndErrorPair> &errors = *(const std::vector<PathAndErrorPair> *)lParam;
if ((ret != eWaifu2xError_OK) || errors.size() > 0) if (ret != Waifu2x::eWaifu2xError_OK)
{ {
char msg[1024] = ""; char msg[1024] = "";
if (lParam == 0)
{
switch (ret) switch (ret)
{ {
case eWaifu2xError_Cancel: case Waifu2x::eWaifu2xError_Cancel:
sprintf(msg, "キャンセルされました"); sprintf(msg, "キャンセルされました");
break; break;
case eWaifu2xError_InvalidParameter: case Waifu2x::eWaifu2xError_InvalidParameter:
sprintf(msg, "パラメータが不正です"); sprintf(msg, "パラメータが不正です");
break; break;
case eWaifu2xError_FailedOpenModelFile: case Waifu2x::eWaifu2xError_FailedOpenModelFile:
sprintf(msg, "モデルファイルが開けませんでした"); sprintf(msg, "モデルファイルが開けませんでした");
break; break;
case eWaifu2xError_FailedParseModelFile: case Waifu2x::eWaifu2xError_FailedParseModelFile:
sprintf(msg, "モデルファイルが壊れています"); sprintf(msg, "モデルファイルが壊れています");
break; break;
case eWaifu2xError_FailedConstructModel: case Waifu2x::eWaifu2xError_FailedConstructModel:
sprintf(msg, "ネットワークの構築に失敗しました"); sprintf(msg, "ネットワークの構築に失敗しました");
break; break;
} }
}
if (ret == eWaifu2xError_OK) else
{ {
// 全てのエラーを表示することは出来ないので最初の一つだけ表示 const auto &fp = *(const std::pair<std::string, std::string> *)lParam;
const auto &fp = errors[0].first; switch (ret)
bool isBreak = false;
switch (errors[0].second)
{ {
case eWaifu2xError_InvalidParameter: case Waifu2x::eWaifu2xError_Cancel:
sprintf(msg, "キャンセルされました");
break;
case Waifu2x::eWaifu2xError_InvalidParameter:
sprintf(msg, "パラメータが不正です"); sprintf(msg, "パラメータが不正です");
break; break;
case eWaifu2xError_FailedOpenInputFile: case Waifu2x::eWaifu2xError_FailedOpenInputFile:
//sprintf(msg, "入力画像「%s」が開けませんでした", fp.first.c_str()); sprintf(msg, "入力画像「%s」が開けませんでした", fp.first.c_str());
sprintf(msg, "入力画像が開けませんでした");
break; break;
case eWaifu2xError_FailedOpenOutputFile: case Waifu2x::eWaifu2xError_FailedOpenOutputFile:
//sprintf(msg, "出力画像「%s」が書き込めませんでした", fp.second.c_str()); sprintf(msg, "出力画像を「%s」に書き込めませんでした", fp.second.c_str());
sprintf(msg, "出力画像が書き込めませんでした");
break; break;
case eWaifu2xError_FailedProcessCaffe: case Waifu2x::eWaifu2xError_FailedProcessCaffe:
sprintf(msg, "補間処理に失敗しました"); sprintf(msg, "補間処理に失敗しました");
break; break;
} }
} }
MessageBoxA(dh, msg, "エラー", MB_OK | MB_ICONERROR); AddLogMessage(msg);
if (ret != Waifu2x::eWaifu2xError_Cancel)
isLastError = true; isLastError = true;
} }
} }
@ -530,7 +568,7 @@ public:
void CheckCUDNN(HWND hWnd, WPARAM wParam, LPARAM lParam, LPVOID lpData) void CheckCUDNN(HWND hWnd, WPARAM wParam, LPARAM lParam, LPVOID lpData)
{ {
if (can_use_cuDNN()) if (Waifu2x::can_use_cuDNN())
MessageBox(dh, TEXT("cuDNNが使えます"), TEXT("結果"), MB_OK | MB_ICONINFORMATION); MessageBox(dh, TEXT("cuDNNが使えます"), TEXT("結果"), MB_OK | MB_ICONINFORMATION);
else else
MessageBox(dh, TEXT("cuDNNは使えません"), TEXT("結果"), MB_OK | MB_ICONERROR); MessageBox(dh, TEXT("cuDNNは使えません"), TEXT("結果"), MB_OK | MB_ICONERROR);
@ -664,9 +702,8 @@ int WINAPI WinMain(HINSTANCE hInstance,
cDialog.SetEventCallBack(SetClassFunc(DialogEvent::Create, &cDialogEvent), NULL, WM_INITDIALOG); cDialog.SetEventCallBack(SetClassFunc(DialogEvent::Create, &cDialogEvent), NULL, WM_INITDIALOG);
cDialog.SetEventCallBack(SetClassFunc(DialogEvent::OnDialogEnd, &cDialogEvent), NULL, WM_CLOSE); cDialog.SetEventCallBack(SetClassFunc(DialogEvent::OnDialogEnd, &cDialogEvent), NULL, WM_CLOSE);
cDialog.SetEventCallBack(SetClassFunc(DialogEvent::OnFaildCreateDir, &cDialogEvent), NULL, WM_FAILD_CREATE_DIR); cDialog.SetEventCallBack(SetClassFunc(DialogEvent::OnFaildCreateDir, &cDialogEvent), NULL, WM_FAILD_CREATE_DIR);
cDialog.SetEventCallBack(SetClassFunc(DialogEvent::OnEndWaifu2x, &cDialogEvent), NULL, WM_END_WAIFU2X); cDialog.SetEventCallBack(SetClassFunc(DialogEvent::OnWaifu2xError, &cDialogEvent), NULL, WM_ON_WAIFU2X_ERROR);
cDialog.SetEventCallBack(SetClassFunc(DialogEvent::WaitThreadExit, &cDialogEvent), NULL, WM_END_THREAD); cDialog.SetEventCallBack(SetClassFunc(DialogEvent::WaitThreadExit, &cDialogEvent), NULL, WM_END_THREAD);
cDialog.SetEventCallBack(SetClassFunc(DialogEvent::Waifu2xTime, &cDialogEvent), NULL, WM_TIME_WAIFU2X);
// ダイアログを表示 // ダイアログを表示
cDialog.DoModal(hInstance, IDD_DIALOG); cDialog.DoModal(hInstance, IDD_DIALOG);

View File

@ -120,7 +120,7 @@ int main(int argc, char** argv)
if (outputExt.length() > 0 && outputExt[0] != '.') if (outputExt.length() > 0 && outputExt[0] != '.')
outputExt = "." + outputExt; outputExt = "." + outputExt;
std::vector<InputOutputPathPair> file_paths; std::vector<std::pair<std::string, std::string>> file_paths;
if (boost::filesystem::is_directory(input_path)) // input_pathがフォルダならそのディレクトリ以下の画像ファイルを一括変換 if (boost::filesystem::is_directory(input_path)) // input_pathがフォルダならそのディレクトリ以下の画像ファイルを一括変換
{ {
boost::filesystem::path output_path; boost::filesystem::path output_path;
@ -227,51 +227,58 @@ int main(int argc, char** argv)
file_paths.emplace_back(cmdInputFile.getValue(), outputFileName); file_paths.emplace_back(cmdInputFile.getValue(), outputFileName);
} }
std::vector<PathAndErrorPair> errors; Waifu2x::eWaifu2xError ret;
Waifu2x w;
const eWaifu2xError ret = waifu2x(argc, argv, file_paths, cmdMode.getValue(), cmdNRLevel.getValue(), cmdScaleRatio.getValue(), cmdModelPath.getValue(), cmdProcess.getValue(), errors); ret = w.init(argc, argv, cmdMode.getValue(), cmdNRLevel.getValue(), cmdScaleRatio.getValue(), cmdModelPath.getValue(), cmdProcess.getValue());
if (ret != eWaifu2xError_OK || errors.size() > 0)
{
switch (ret) switch (ret)
{ {
case eWaifu2xError_InvalidParameter: case Waifu2x::eWaifu2xError_InvalidParameter:
printf("エラー: パラメータが不正です\n"); printf("エラー: パラメータが不正です\n");
break; return 1;
case eWaifu2xError_FailedOpenModelFile: case Waifu2x::eWaifu2xError_FailedOpenModelFile:
printf("エラー: モデルファイルが開けませんでした\n"); printf("エラー: モデルファイルが開けませんでした\n");
break; return 1;
case eWaifu2xError_FailedParseModelFile: case Waifu2x::eWaifu2xError_FailedParseModelFile:
printf("エラー: モデルファイルが壊れています\n"); printf("エラー: モデルファイルが壊れています\n");
break; return 1;
case eWaifu2xError_FailedConstructModel: case Waifu2x::eWaifu2xError_FailedConstructModel:
printf("エラー: ネットワークの構築に失敗しました\n"); printf("エラー: ネットワークの構築に失敗しました\n");
break;
}
for (const auto &ep : errors)
{
const auto &fp = ep.first;
switch (ep.second)
{
case eWaifu2xError_InvalidParameter:
printf("エラー: パラメータが不正です\n");
break;
case eWaifu2xError_FailedOpenInputFile:
printf("エラー: 入力画像「%s」が開けませんでした\n", fp.first.c_str());
break;
case eWaifu2xError_FailedOpenOutputFile:
printf("エラー: 出力画像「%s」が書き込めませんでした\n", fp.second.c_str());
break;
case eWaifu2xError_FailedProcessCaffe:
printf("エラー: 補間処理に失敗しました\n");
break;
}
}
printf("変換に失敗しました\n");
return 1; return 1;
} }
bool isError = false;
for (const auto &p : file_paths)
{
const Waifu2x::eWaifu2xError ret = w.waifu2x(p.first, p.second);
if (ret != Waifu2x::eWaifu2xError_OK)
{
switch (ret)
{
case Waifu2x::eWaifu2xError_InvalidParameter:
printf("エラー: パラメータが不正です\n");
break;
case Waifu2x::eWaifu2xError_FailedOpenInputFile:
printf("エラー: 入力画像「%s」が開けませんでした\n", p.first.c_str());
break;
case Waifu2x::eWaifu2xError_FailedOpenOutputFile:
printf("エラー: 出力画像「%s」が書き込めませんでした\n", p.second.c_str());
break;
case Waifu2x::eWaifu2xError_FailedProcessCaffe:
printf("エラー: 補間処理に失敗しました\n");
break;
}
isError = true;
}
}
if (isError)
{
printf("変換に失敗したファイルがあります\n");
return 1;
}
printf("変換に成功しました\n");
return 0; return 0;
} }