From 2d395ab3b16bfcbe79e67b83871a5514c4ee9a93 Mon Sep 17 00:00:00 2001 From: lltcggie Date: Fri, 29 Apr 2016 13:57:23 +0900 Subject: [PATCH] =?UTF-8?q?=E3=83=BB=E3=83=A1=E3=83=A2=E3=83=AA=E4=BD=BF?= =?UTF-8?q?=E7=94=A8=E9=87=8F=E3=82=92=E6=B8=9B=E3=82=89=E3=81=99=E3=82=88?= =?UTF-8?q?=E3=81=86=E3=81=AB=E3=81=97=E3=81=9F=20=E3=83=BB=E6=8B=A1?= =?UTF-8?q?=E5=A4=A7=E5=BE=8C=E3=81=AE=E3=82=B5=E3=82=A4=E3=82=BA=E3=81=8C?= =?UTF-8?q?3GB=E8=B6=85=E3=81=88=E3=81=A6=E3=81=84=E3=81=9F=E3=82=89?= =?UTF-8?q?=E3=83=87=E3=83=BC=E3=82=BF=E3=82=92=E4=B8=80=E6=99=82=E3=83=95?= =?UTF-8?q?=E3=82=A1=E3=82=A4=E3=83=AB=E3=81=AB=E6=9B=B8=E3=81=8D=E5=87=BA?= =?UTF-8?q?=E3=81=97=E3=81=A6=E3=83=A1=E3=83=A2=E3=83=AA=E4=B8=8D=E8=B6=B3?= =?UTF-8?q?=E5=AF=BE=E7=AD=96=E3=82=92=E3=81=99=E3=82=8B=E3=82=88=E3=81=86?= =?UTF-8?q?=E3=81=AB=E3=81=97=E3=81=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- common/waifu2x.cpp | 214 ++++++++++++++++++++++++++++++++++++++++----- common/waifu2x.h | 2 +- 2 files changed, 195 insertions(+), 21 deletions(-) diff --git a/common/waifu2x.cpp b/common/waifu2x.cpp index 22071de..1c18c97 100644 --- a/common/waifu2x.cpp +++ b/common/waifu2x.cpp @@ -16,6 +16,7 @@ #include #include #include +#include #ifdef _MSC_VER #include #endif @@ -654,10 +655,9 @@ Waifu2x::eWaifu2xError Waifu2x::Zoom2xAndPaddingImage(const cv::Mat &input, cv:: zoom_size.width *= 2; zoom_size.height *= 2; - cv::Mat zoom_image; - cv::resize(input, zoom_image, zoom_size, 0.0, 0.0, cv::INTER_NEAREST); + cv::resize(input, output, zoom_size, 0.0, 0.0, cv::INTER_NEAREST); - return PaddingImage(zoom_image, output); + return PaddingImage(output, output); } // 入力画像をzoom_sizeの大きさにcv::INTER_CUBICで拡大し、色情報のみを残す @@ -1618,7 +1618,7 @@ Waifu2x::eWaifu2xError Waifu2x::Reconstruct(const bool isReconstructNoise, const return eWaifu2xError_OK; } -Waifu2x::eWaifu2xError Waifu2x::AfterReconstructFloatMatProcess(const bool isReconstructScale, const waifu2xCancelFunc cancel_func, const cv::Mat &floatim, const cv::Mat &in, cv::Mat &out) +Waifu2x::eWaifu2xError Waifu2x::AfterReconstructFloatMatProcess(const bool isReconstructScale, const waifu2xCancelFunc cancel_func, const cv::Mat &floatim, cv::Mat &in, cv::Mat &out) { cv::Size_ image_size = in.size(); @@ -1631,6 +1631,7 @@ Waifu2x::eWaifu2xError Waifu2x::AfterReconstructFloatMatProcess(const bool isRec CreateZoomColorImage(floatim, image_size, color_planes); color_planes[0] = in; + in.release(); cv::Mat converted_image; cv::merge(color_planes, converted_image); @@ -1643,6 +1644,7 @@ Waifu2x::eWaifu2xError Waifu2x::AfterReconstructFloatMatProcess(const bool isRec { std::vector planes; cv::split(in, planes); + in.release(); // RGBからBGRに直す std::swap(planes[0], planes[2]); @@ -1654,16 +1656,200 @@ Waifu2x::eWaifu2xError Waifu2x::AfterReconstructFloatMatProcess(const bool isRec const int scale2 = ceil(log2(ratio)); const double shrinkRatio = ratio >= 1.0 ? ratio / std::pow(2.0, (double)scale2) : ratio; + if (isReconstructScale) + { + const cv::Size_ ns(image_size.width * shrinkRatio, image_size.height * shrinkRatio); + if (image_size.width != ns.width || image_size.height != ns.height) + { + int argo = cv::INTER_CUBIC; + if (ratio < 0.5) + argo = cv::INTER_AREA; + + cv::resize(process_image, process_image, ns, 0.0, 0.0, argo); + } + } + cv::Mat alpha; if (floatim.channels() == 4) { std::vector planes; cv::split(floatim, planes); + alpha = planes[3]; + planes.clear(); + if (isReconstructScale) - Reconstruct(false, true, cancel_func, planes[3], alpha); - else - alpha = planes[3]; + { + const auto memSize = process_image.step1() * process_image.elemSize1() * process_image.size().height; + + if (memSize < 3ULL * 1000ULL * 1000ULL * 1000ULL) // 拡大後のサイズが3GB超えていたらファイルに書き出してメモリ不足対策 + Reconstruct(false, true, cancel_func, alpha, alpha); + else + { + boost::filesystem::path temp = boost::filesystem::unique_path("%%%%-%%%%-%%%%-%%%%.bin"); + + auto compp = [](const cv::Mat &im, const boost::filesystem::path &temp) + { + static char outbuf[10240000]; + FILE *fout; + z_stream z; + int count; + + if (!(fout = fopen(temp.string().c_str(), "wb"))) + return false; + + z.zalloc = Z_NULL; + z.zfree = Z_NULL; + z.opaque = Z_NULL; + + if (deflateInit(&z, Z_DEFAULT_COMPRESSION) != Z_OK) + { + fclose(fout); + return false; + } + + z.next_in = (z_const Bytef *)im.data; + z.avail_in = im.step1() * im.elemSize1() * im.size().height; + z.next_out = (Bytef *)outbuf; + z.avail_out = sizeof(outbuf); + + for(;;) + { + const int status = deflate(&z, Z_FINISH); + if (status == Z_STREAM_END) + break; // 完了 + + if (status != Z_OK) + { + fclose(fout); + return false; + } + + if (z.avail_out == 0) + { + if (fwrite(outbuf, 1, sizeof(outbuf), fout) != sizeof(outbuf)) + { + fclose(fout); + return false; + } + z.next_out = (Bytef *)outbuf; // 出力バッファ残量を元に戻す + z.avail_out = sizeof(outbuf); // 出力ポインタを元に戻す + } + } + + // 残りを吐き出す + if ((count = sizeof(outbuf) - z.avail_out) != 0) + { + if (fwrite(outbuf, 1, count, fout) != count) + { + fclose(fout); + return false; + } + } + + // 後始末 + if (deflateEnd(&z) != Z_OK) + { + fclose(fout); + return false; + } + + fclose(fout); + + return true; + }; + + auto decompp = [](const cv::Size &size, const int type, cv::Mat &out, const boost::filesystem::path &temp) + { + static char inbuf[102400]; + FILE *fin; + z_stream z; + + if (!(fin = fopen(temp.string().c_str(), "rb"))) + return false; + + z.zalloc = Z_NULL; + z.zfree = Z_NULL; + z.opaque = Z_NULL; + + z.next_in = Z_NULL; + z.avail_in = 0; + if (inflateInit(&z) != Z_OK) + { + fclose(fin); + return false; + } + + out = cv::Mat(size, type); + + const int MaxSize = out.step1() * out.elemSize1() * out.size().height; + z.next_out = (Bytef *)out.data; // 出力ポインタ + z.avail_out = MaxSize; // 出力バッファ残量 + + for(;;) + { + if (z.avail_in == 0) + { + z.next_in = (Bytef *)inbuf; + z.avail_in = fread(inbuf, 1, sizeof(inbuf), fin); + } + + const int status = inflate(&z, Z_NO_FLUSH); + if (status == Z_STREAM_END) + break; + + if (status != Z_OK) + { + fclose(fin); + return false; + } + + if (z.avail_out == 0) + { + fclose(fin); + return false; + } + } + + if (inflateEnd(&z) != Z_OK) + { + fclose(fin); + return false; + } + + fclose(fin); + + return true; + }; + + const auto step1Old = process_image.step1(); + const auto size = process_image.size(); + const auto type = process_image.type(); + compp(process_image, temp); + process_image.release(); + + Reconstruct(false, true, cancel_func, alpha, alpha); + + decompp(size, type, process_image, temp); + boost::filesystem::remove(temp); + + assert(step1Old == process_image.step1()); + } + } + } + + if (isReconstructScale) + { + const cv::Size_ ns(image_size.width * shrinkRatio, image_size.height * shrinkRatio); + if (image_size.width != ns.width || image_size.height != ns.height) + { + int argo = cv::INTER_CUBIC; + if (ratio < 0.5) + argo = cv::INTER_AREA; + + if (!alpha.empty()) + cv::resize(alpha, alpha, ns, 0.0, 0.0, argo); + } } // アルファチャンネルがあったらアルファを付加する @@ -1674,23 +1860,11 @@ Waifu2x::eWaifu2xError Waifu2x::AfterReconstructFloatMatProcess(const bool isRec process_image.release(); planes.push_back(alpha); + alpha.release(); cv::merge(planes, process_image); } - if (isReconstructScale) - { - const cv::Size_ ns(image_size.width * shrinkRatio, image_size.height * shrinkRatio); - if (image_size.width != ns.width || image_size.height != ns.height) - { - int argo = cv::INTER_CUBIC; - if(ratio < 0.5) - argo = cv::INTER_AREA; - - cv::resize(process_image, process_image, ns, 0.0, 0.0, argo); - } - } - // 値を0〜1にクリッピング cv::threshold(process_image, process_image, 1.0, 1.0, cv::THRESH_TRUNC); cv::threshold(process_image, process_image, 0.0, 0.0, cv::THRESH_TOZERO); diff --git a/common/waifu2x.h b/common/waifu2x.h index 7a4a73d..0ab4ff2 100644 --- a/common/waifu2x.h +++ b/common/waifu2x.h @@ -133,7 +133,7 @@ private: eWaifu2xError BeforeReconstructFloatMatProcess(const cv::Mat &in, cv::Mat &out, bool &convertBGRflag); eWaifu2xError ReconstructFloatMat(const bool isReconstructNoise, const bool isReconstructScale, const waifu2xCancelFunc cancel_func, const cv::Mat &in, cv::Mat &out); eWaifu2xError Reconstruct(const bool isReconstructNoise, const bool isReconstructScale, const waifu2xCancelFunc cancel_func, const cv::Mat &in, cv::Mat &out); - eWaifu2xError AfterReconstructFloatMatProcess(const bool isReconstructScale, const waifu2xCancelFunc cancel_func, const cv::Mat &floatim, const cv::Mat &in, cv::Mat &out); + eWaifu2xError AfterReconstructFloatMatProcess(const bool isReconstructScale, const waifu2xCancelFunc cancel_func, const cv::Mat &floatim, cv::Mat &in, cv::Mat &out); eWaifu2xError waifu2xConvetedMat(const bool isJpeg, const cv::Mat &inMat, cv::Mat &outMat, const waifu2xCancelFunc cancel_func = nullptr);