縦幅か横幅指定の拡大で、指定サイズから1pxくらいずれることがあるのを修正 #84

This commit is contained in:
lltcggie 2017-04-29 12:41:42 +09:00
parent 5b98bda53c
commit c7d020639e
4 changed files with 65 additions and 32 deletions

View File

@ -404,14 +404,14 @@ Waifu2x::eWaifu2xError stImage::Load(const void* source, const int width, const
return Waifu2x::eWaifu2xError_OK; return Waifu2x::eWaifu2xError_OK;
} }
double stImage::GetScaleFromWidth(const int width) const Factor stImage::GetScaleFromWidth(const int width) const
{ {
return (double)width / (double)mOrgSize.width; return Factor((double)width, (double)mOrgSize.width);
} }
double stImage::GetScaleFromHeight(const int height) const Factor stImage::GetScaleFromHeight(const int height) const
{ {
return (double)height / (double)mOrgSize.height; return Factor((double)height, (double)mOrgSize.height);
} }
bool stImage::RequestDenoise() const bool stImage::RequestDenoise() const
@ -619,7 +619,7 @@ void stImage::SetReconstructedImage(cv::Mat &dst, cv::Mat &src, const cv::Size_<
src.release(); src.release();
} }
void stImage::Postprocess(const int input_plane, const double scale, const int depth) void stImage::Postprocess(const int input_plane, const Factor scale, const int depth)
{ {
DeconvertFromNetFormat(input_plane); DeconvertFromNetFormat(input_plane);
ShrinkImage(scale); ShrinkImage(scale);
@ -742,20 +742,21 @@ void stImage::DeconvertFromNetFormat(const int input_plane)
} }
} }
void stImage::ShrinkImage(const double scale) void stImage::ShrinkImage(const Factor scale)
{ {
// TODO: scale = 1.0 でも悪影響を及ぼさないか調べる // TODO: scale = 1.0 でも悪影響を及ぼさないか調べる
const int scaleBase = 2; // TODO: モデルの拡大率によって可変できるようにする const int scaleBase = 2; // TODO: モデルの拡大率によって可変できるようにする
const int scaleNum = ceil(log(scale) / log(scaleBase)); const auto Width = scale.MultiNumerator(mOrgSize.width);
const double shrinkRatio = scale >= 1.0 ? scale / std::pow(scaleBase, scaleNum) : scale; const auto Height = scale.MultiNumerator(mOrgSize.height);
const cv::Size_<int> ns(mOrgSize.width * scale, mOrgSize.height * scale); //const cv::Size_<int> ns(mOrgSize.width * scale, mOrgSize.height * scale);
const cv::Size_<int> ns((int)Width.toDouble(), (int)Height.toDouble());
if (mEndImage.size().width != ns.width || mEndImage.size().height != ns.height) if (mEndImage.size().width != ns.width || mEndImage.size().height != ns.height)
{ {
int argo = cv::INTER_CUBIC; int argo = cv::INTER_CUBIC;
if (scale < 0.5) if (scale.toDouble() < 0.5)
argo = cv::INTER_AREA; argo = cv::INTER_AREA;
cv::resize(mEndImage, mEndImage, ns, 0.0, 0.0, argo); cv::resize(mEndImage, mEndImage, ns, 0.0, 0.0, argo);

View File

@ -68,7 +68,7 @@ private:
void SetReconstructedImage(cv::Mat &dst, cv::Mat &src, const cv::Size_<int> &size, const int inner_scale); void SetReconstructedImage(cv::Mat &dst, cv::Mat &src, const cv::Size_<int> &size, const int inner_scale);
void DeconvertFromNetFormat(const int input_plane); void DeconvertFromNetFormat(const int input_plane);
void ShrinkImage(const double scale); void ShrinkImage(const Factor scale);
void ShrinkImage(const int width, const int height); void ShrinkImage(const int width, const int height);
static int DepthBitToCVDepth(const int depth_bit); static int DepthBitToCVDepth(const int depth_bit);
@ -94,8 +94,8 @@ public:
// sourceはPostprocess()が終わるまで存在している必要がある // sourceはPostprocess()が終わるまで存在している必要がある
Waifu2x::eWaifu2xError Load(const void* source, const int width, const int height, const int channel, const int stride); Waifu2x::eWaifu2xError Load(const void* source, const int width, const int height, const int channel, const int stride);
double GetScaleFromWidth(const int width) const; Factor GetScaleFromWidth(const int width) const;
double GetScaleFromHeight(const int width) const; Factor GetScaleFromHeight(const int width) const;
bool RequestDenoise() const; bool RequestDenoise() const;
@ -125,7 +125,7 @@ public:
// size: GetScalePaddingedImage()で取得したsize // size: GetScalePaddingedImage()で取得したsize
void SetReconstructedA(cv::Mat &im, const cv::Size_<int> &size, const int inner_scale); void SetReconstructedA(cv::Mat &im, const cv::Size_<int> &size, const int inner_scale);
void Postprocess(const int input_plane, const double scale, const int depth); void Postprocess(const int input_plane, const Factor scale, const int depth);
void Postprocess(const int input_plane, const int width, const int height, const int depth); void Postprocess(const int input_plane, const int width, const int height, const int depth);
cv::Mat GetEndImage() const; cv::Mat GetEndImage() const;

View File

@ -769,18 +769,18 @@ Waifu2x::eWaifu2xError Waifu2x::waifu2x(const boost::filesystem::path &input_fil
const bool isReconstructNoise = mMode == eWaifu2xModelTypeNoise || mMode == eWaifu2xModelTypeNoiseScale || (mMode == eWaifu2xModelTypeAutoScale && image.RequestDenoise()); const bool isReconstructNoise = mMode == eWaifu2xModelTypeNoise || mMode == eWaifu2xModelTypeNoiseScale || (mMode == eWaifu2xModelTypeAutoScale && image.RequestDenoise());
const bool isReconstructScale = mMode == eWaifu2xModelTypeScale || mMode == eWaifu2xModelTypeNoiseScale || mMode == eWaifu2xModelTypeAutoScale; const bool isReconstructScale = mMode == eWaifu2xModelTypeScale || mMode == eWaifu2xModelTypeNoiseScale || mMode == eWaifu2xModelTypeAutoScale;
double Factor = CalcScaleRatio(scale_ratio, scale_width, scale_height, image); auto factor = CalcScaleRatio(scale_ratio, scale_width, scale_height, image);
if (!isReconstructScale) if (!isReconstructScale)
Factor = 1.0; factor = Factor(1.0, 1.0);
cv::Mat reconstruct_image; cv::Mat reconstruct_image;
ret = ReconstructImage(Factor, crop_w, crop_h, use_tta, batch_size, isReconstructNoise, isReconstructScale, cancel_func, image); ret = ReconstructImage(factor, crop_w, crop_h, use_tta, batch_size, isReconstructNoise, isReconstructScale, cancel_func, image);
if (ret != Waifu2x::eWaifu2xError_OK) if (ret != Waifu2x::eWaifu2xError_OK)
return ret; return ret;
if(!scale_width || !scale_height) if(!scale_width || !scale_height)
image.Postprocess(mInputPlane, Factor, output_depth); image.Postprocess(mInputPlane, factor, output_depth);
else else
image.Postprocess(mInputPlane, *scale_width, *scale_height, output_depth); image.Postprocess(mInputPlane, *scale_width, *scale_height, output_depth);
@ -822,16 +822,16 @@ Waifu2x::eWaifu2xError Waifu2x::waifu2x(const double factor, const void* source,
const bool isReconstructNoise = mMode == eWaifu2xModelTypeNoise || mMode == eWaifu2xModelTypeNoiseScale; const bool isReconstructNoise = mMode == eWaifu2xModelTypeNoise || mMode == eWaifu2xModelTypeNoiseScale;
const bool isReconstructScale = mMode == eWaifu2xModelTypeScale || mMode == eWaifu2xModelTypeNoiseScale || mMode == eWaifu2xModelTypeAutoScale; const bool isReconstructScale = mMode == eWaifu2xModelTypeScale || mMode == eWaifu2xModelTypeNoiseScale || mMode == eWaifu2xModelTypeAutoScale;
double Factor = factor; Factor nowFactor = Factor(factor, 1.0);
if (!isReconstructScale) if (!isReconstructScale)
Factor = 1.0; nowFactor = Factor(1.0, 1.0);
cv::Mat reconstruct_image; cv::Mat reconstruct_image;
ret = ReconstructImage(Factor, crop_w, crop_h, use_tta, batch_size, isReconstructNoise, isReconstructScale, nullptr, image); ret = ReconstructImage(nowFactor, crop_w, crop_h, use_tta, batch_size, isReconstructNoise, isReconstructScale, nullptr, image);
if (ret != Waifu2x::eWaifu2xError_OK) if (ret != Waifu2x::eWaifu2xError_OK)
return ret; return ret;
image.Postprocess(mInputPlane, Factor, 8); image.Postprocess(mInputPlane, nowFactor, 8);
cv::Mat out_bgr_image = image.GetEndImage(); cv::Mat out_bgr_image = image.GetEndImage();
image.Clear(); image.Clear();
@ -854,18 +854,18 @@ Waifu2x::eWaifu2xError Waifu2x::waifu2x(const double factor, const void* source,
return Waifu2x::eWaifu2xError_OK; return Waifu2x::eWaifu2xError_OK;
} }
double Waifu2x::CalcScaleRatio(const boost::optional<double> scale_ratio, const boost::optional<int> scale_width, const boost::optional<int> scale_height, Factor Waifu2x::CalcScaleRatio(const boost::optional<double> scale_ratio, const boost::optional<int> scale_width, const boost::optional<int> scale_height,
const stImage &image) const stImage &image)
{ {
if (scale_ratio) if (scale_ratio)
return *scale_ratio; return Factor(*scale_ratio, 1.0);
if (scale_width && scale_height) if (scale_width && scale_height)
{ {
const auto d1 = image.GetScaleFromWidth(*scale_width); const auto d1 = image.GetScaleFromWidth(*scale_width);
const auto d2 = image.GetScaleFromWidth(*scale_height); const auto d2 = image.GetScaleFromWidth(*scale_height);
return d1 >= d2 ? d1 : d2; return d1.toDouble() >= d2.toDouble() ? d1 : d2;
} }
if (scale_width) if (scale_width)
@ -874,7 +874,7 @@ double Waifu2x::CalcScaleRatio(const boost::optional<double> scale_ratio, const
if(scale_height) if(scale_height)
return image.GetScaleFromHeight(*scale_height); return image.GetScaleFromHeight(*scale_height);
return 1.0; return Factor(1.0, 1.0);
} }
int Waifu2x::GetcuDNNAlgorithm(const char * layer_name, int num_input, int num_output, int batch_size, int Waifu2x::GetcuDNNAlgorithm(const char * layer_name, int num_input, int num_output, int batch_size,
@ -899,12 +899,12 @@ void Waifu2x::SetcuDNNAlgorithm(int algo, const char * layer_name, int num_input
return g_DeconvCcuDNNAlgorithm.SetAlgorithm(algo, num_input, num_output, batch_size, width, height, kernel_w, kernel_h, pad_w, pad_h, stride_w, stride_h); return g_DeconvCcuDNNAlgorithm.SetAlgorithm(algo, num_input, num_output, batch_size, width, height, kernel_w, kernel_h, pad_w, pad_h, stride_w, stride_h);
} }
Waifu2x::eWaifu2xError Waifu2x::ReconstructImage(const double factor, const int crop_w, const int crop_h, const bool use_tta, const int batch_size, Waifu2x::eWaifu2xError Waifu2x::ReconstructImage(const Factor factor, const int crop_w, const int crop_h, const bool use_tta, const int batch_size,
const bool isReconstructNoise, const bool isReconstructScale, const Waifu2x::waifu2xCancelFunc cancel_func, stImage &image) const bool isReconstructNoise, const bool isReconstructScale, const Waifu2x::waifu2xCancelFunc cancel_func, stImage &image)
{ {
Waifu2x::eWaifu2xError ret; Waifu2x::eWaifu2xError ret;
double Factor = factor; Factor nowFactor = factor;
if (isReconstructNoise) if (isReconstructNoise)
{ {
@ -926,14 +926,15 @@ Waifu2x::eWaifu2xError Waifu2x::ReconstructImage(const double factor, const int
if (ret != Waifu2x::eWaifu2xError_OK) if (ret != Waifu2x::eWaifu2xError_OK)
return ret; return ret;
Factor /= mNoiseNet->GetInnerScale(); //nowFactor /= mNoiseNet->GetInnerScale();
nowFactor = nowFactor.MultiDenominator(mNoiseNet->GetInnerScale());
} }
} }
if (cancel_func && cancel_func()) if (cancel_func && cancel_func())
return Waifu2x::eWaifu2xError_Cancel; return Waifu2x::eWaifu2xError_Cancel;
const int scaleNum = ceil(log(Factor) / log(ScaleBase)); const int scaleNum = ceil(log(nowFactor.toDouble()) / log(ScaleBase));
if (isReconstructScale) if (isReconstructScale)
{ {

View File

@ -25,6 +25,37 @@ class cNet;
class stImage; class stImage;
class Factor
{
private:
double mNumerator; // •ªŽq
double mDenominator; // •ê<E280A2>
public:
Factor() : mNumerator(1.0), mDenominator(1.0)
{
}
Factor(const double numerator, const double denominator) : mNumerator(numerator), mDenominator(denominator)
{
}
Factor MultiNumerator(const double numerator) const
{
return Factor(mNumerator * numerator, mDenominator);
}
Factor MultiDenominator(const double denominator) const
{
return Factor(mNumerator, mDenominator * denominator);
}
double toDouble() const
{
return mNumerator / mDenominator;
}
};
class Waifu2x class Waifu2x
{ {
public: public:
@ -97,7 +128,7 @@ private:
static boost::filesystem::path GetModeDirPath(const boost::filesystem::path &model_dir); static boost::filesystem::path GetModeDirPath(const boost::filesystem::path &model_dir);
static boost::filesystem::path GetInfoPath(const boost::filesystem::path &model_dir); static boost::filesystem::path GetInfoPath(const boost::filesystem::path &model_dir);
static double CalcScaleRatio(const boost::optional<double> scale_ratio, const boost::optional<int> scale_width, const boost::optional<int> scale_height, static Factor CalcScaleRatio(const boost::optional<double> scale_ratio, const boost::optional<int> scale_width, const boost::optional<int> scale_height,
const stImage &image); const stImage &image);
static int GetcuDNNAlgorithm(const char *layer_name, int num_input, int num_output, int batch_size, static int GetcuDNNAlgorithm(const char *layer_name, int num_input, int num_output, int batch_size,
@ -106,7 +137,7 @@ private:
static void SetcuDNNAlgorithm(int algo, const char *layer_name, int num_input, int num_output, int batch_size, static void SetcuDNNAlgorithm(int algo, const char *layer_name, int num_input, int num_output, int batch_size,
int width, int height, int kernel_w, int kernel_h, int pad_w, int pad_h, int stride_w, int stride_h); int width, int height, int kernel_w, int kernel_h, int pad_w, int pad_h, int stride_w, int stride_h);
Waifu2x::eWaifu2xError ReconstructImage(const double factor, const int crop_w, const int crop_h, const bool use_tta, const int batch_size, Waifu2x::eWaifu2xError ReconstructImage(const Factor factor, const int crop_w, const int crop_h, const bool use_tta, const int batch_size,
const bool isReconstructNoise, const bool isReconstructScale, const Waifu2x::waifu2xCancelFunc cancel_func, stImage &image); const bool isReconstructNoise, const bool isReconstructScale, const Waifu2x::waifu2xCancelFunc cancel_func, stImage &image);
Waifu2x::eWaifu2xError ReconstructScale(const int crop_w, const int crop_h, const bool use_tta, const int batch_size, Waifu2x::eWaifu2xError ReconstructScale(const int crop_w, const int crop_h, const bool use_tta, const int batch_size,
const Waifu2x::waifu2xCancelFunc cancel_func, stImage &image); const Waifu2x::waifu2xCancelFunc cancel_func, stImage &image);