diff --git a/waifu2x-caffe/Test.cpp b/waifu2x-caffe/Test.cpp index 83ff5f7..ac559cc 100644 --- a/waifu2x-caffe/Test.cpp +++ b/waifu2x-caffe/Test.cpp @@ -280,8 +280,11 @@ public: } }; +void reg(); + int main(int argc, char** argv) { - CV_DNN_REGISTER_LAYER_CLASS(CropCenter, CropCenterLayer); + //CV_DNN_REGISTER_LAYER_CLASS(CropCenter, CropCenterLayer); + reg(); // ImageNet Caffeリファレンスモデル string protoFile = "models/upresnet10/noise0_scale2.0x_model.prototxt"; @@ -298,7 +301,7 @@ int main(int argc, char** argv) { //net.setPreferableBackend(cv::dnn::DNN_BACKEND_CUDA); //net.setPreferableTarget(cv::dnn::DNN_TARGET_CUDA); - //net.setPreferableBackend(cv::dnn::DNN_BACKEND_OPENCV); + net.setPreferableBackend(cv::dnn::DNN_BACKEND_OPENCV); net.setPreferableTarget(cv::dnn::DNN_TARGET_CPU); } catch (const cv::Exception& e) { @@ -326,8 +329,8 @@ int main(int argc, char** argv) { const auto probMat = net.forward(); std::vector outImgs; - //cv::dnn::imagesFromBlob(probMat, outImgs); - cv::dnn::imagesFromBlob(inputBlob, outImgs); + cv::dnn::imagesFromBlob(probMat, outImgs); + //cv::dnn::imagesFromBlob(inputBlob, outImgs); auto outImg = outImgs[0]; // 値を0〜1にクリッピング diff --git a/waifu2x-caffe/slice_layer.cpp b/waifu2x-caffe/slice_layer.cpp index 996b054..596b09a 100644 --- a/waifu2x-caffe/slice_layer.cpp +++ b/waifu2x-caffe/slice_layer.cpp @@ -23,89 +23,94 @@ using namespace cv::dnn::cuda4dnn; #endif +namespace +{ + cv::Range normalizeRange(const cv::Range& input_range, int n) + { + cv::Range range = input_range; + + if (range.start != n) { + range.start = std::min(std::max(range.start, -n), n - 1); + if (range.start < 0) + { + range.start += n; + } + } + + range.end = std::min(std::max(range.end, -n), n); + if (range.end < 0) + { + range.end += n; + } + + return range; + } + + // TODO: support cv::Range with steps and negative steps to get rid of this transformation + void tranformForNegSteps(const cv::dnn::MatShape& inpShape, std::vector >& sliceRanges, std::vector >& sliceSteps) + { + // in case of negative steps, + // x of shape [5, 10], x[5:0:-1, 10:1:-3] <=> np.flip(x[1:5:1, 2:10:3], aixs=(0, 1)) + // new_end_i = start_i + 1 > dim_i ? dim_i : start_i + 1 + // new_start_i = end + 1 + // new_start_i = new_end_i - 1 - ((new_end_i - 1 - new_start_i) / abs(step_i)) * abs(step_i) + int start, end, new_start, new_end, step; + for (int i = 0; i < sliceSteps[0].size(); ++i) + { + step = sliceSteps[0][i]; + if (step > 0) + continue; + + step = -step; + start = sliceRanges[0][i].start; + end = sliceRanges[0][i].end; + new_end = start >= inpShape[i] ? inpShape[i] : start + 1; + new_start = end + 1; + new_start = new_end - 1 - ((new_end - 1 - new_start) / step) * step; + + sliceSteps[0][i] = step; + sliceRanges[0][i].start = new_start; + sliceRanges[0][i].end = new_end; + } + } + + std::vector > finalizeSliceRange(const cv::dnn::MatShape& inpShape, int& axis, + const std::vector >& inputSliceRanges) + { + std::vector > sliceRanges = inputSliceRanges; + CV_Assert(inpShape.size() > 0); + bool axisNeg = (axis < 0); + axis = (axis + static_cast(inpShape.size())) % inpShape.size(); + + for (size_t i = 0; i < sliceRanges.size(); ++i) { + std::vector& ranges = sliceRanges[i]; + if (axisNeg) + { + ranges.insert(ranges.begin(), axis, cv::Range::all()); + } + + for (size_t j = 0; j < ranges.size(); ++j) + { + int n = inpShape[j]; + if (n <= 0) + { + continue; + } + + ranges[j] = normalizeRange(ranges[j], n); + } + } + + return sliceRanges; + } +} + namespace cv { namespace dnn { - Range normalizeRange(const Range& input_range, int n) - { - Range range = input_range; - if (range.start != n) { - range.start = std::min(std::max(range.start, -n), n - 1); - if (range.start < 0) - { - range.start += n; - } - } - - range.end = std::min(std::max(range.end, -n), n); - if (range.end < 0) - { - range.end += n; - } - - return range; - } - - // TODO: support cv::Range with steps and negative steps to get rid of this transformation - void tranformForNegSteps(const MatShape& inpShape, std::vector >& sliceRanges, std::vector >& sliceSteps) - { - // in case of negative steps, - // x of shape [5, 10], x[5:0:-1, 10:1:-3] <=> np.flip(x[1:5:1, 2:10:3], aixs=(0, 1)) - // new_end_i = start_i + 1 > dim_i ? dim_i : start_i + 1 - // new_start_i = end + 1 - // new_start_i = new_end_i - 1 - ((new_end_i - 1 - new_start_i) / abs(step_i)) * abs(step_i) - int start, end, new_start, new_end, step; - for (int i = 0; i < sliceSteps[0].size(); ++i) - { - step = sliceSteps[0][i]; - if (step > 0) - continue; - - step = -step; - start = sliceRanges[0][i].start; - end = sliceRanges[0][i].end; - new_end = start >= inpShape[i] ? inpShape[i] : start + 1; - new_start = end + 1; - new_start = new_end - 1 - ((new_end - 1 - new_start) / step) * step; - - sliceSteps[0][i] = step; - sliceRanges[0][i].start = new_start; - sliceRanges[0][i].end = new_end; - } - } - - std::vector > finalizeSliceRange(const MatShape& inpShape, int& axis, - const std::vector >& inputSliceRanges) - { - std::vector > sliceRanges = inputSliceRanges; - CV_Assert(inpShape.size() > 0); - bool axisNeg = (axis < 0); - axis = (axis + static_cast(inpShape.size())) % inpShape.size(); - - for (size_t i = 0; i < sliceRanges.size(); ++i) { - std::vector& ranges = sliceRanges[i]; - if (axisNeg) - { - ranges.insert(ranges.begin(), axis, Range::all()); - } - - for (size_t j = 0; j < ranges.size(); ++j) - { - int n = inpShape[j]; - if (n <= 0) - { - continue; - } - - ranges[j] = normalizeRange(ranges[j], n); - } - } - - return sliceRanges; - } class SliceLayerImpl : public SliceLayer { @@ -826,10 +831,10 @@ namespace cv bool hasSteps; }; - class CropLayerImpl CV_FINAL : public SliceLayerImpl + class CropCenterLayerImpl CV_FINAL : public SliceLayerImpl { public: - CropLayerImpl(const LayerParams& params) : SliceLayerImpl(LayerParams()) + CropCenterLayerImpl(const LayerParams& params) : SliceLayerImpl(LayerParams()) { setParamsFrom(params); axis = params.get("axis", 2); @@ -840,6 +845,21 @@ namespace cv for (int i = 0; i < paramOffset->size(); i++) offset.push_back(paramOffset->get(i)); } + + if (params.has("crop_size")) + { + const auto& paramCropSize = params.get("crop_size"); + const auto& str = paramCropSize.getStringValue(); + + const int s = atoi(str.c_str()); + offset.resize(4); + offset[0] = 0; + offset[1] = 0; + offset[2] = s; + offset[3] = s; + + axis = 0; + } } bool getMemoryShapes(const std::vector& inputs, @@ -847,26 +867,75 @@ namespace cv std::vector& outputs, std::vector& internals) const CV_OVERRIDE { - CV_Assert(inputs.size() == 2); + //CV_Assert(inputs.size() == 2); + + //MatShape dstShape = inputs[0]; + //int start = normalize_axis(axis, dstShape); + //for (int i = start; i < dstShape.size(); i++) + //{ + // dstShape[i] = inputs[1][i]; + //} + //outputs.resize(1, dstShape); MatShape dstShape = inputs[0]; int start = normalize_axis(axis, dstShape); for (int i = start; i < dstShape.size(); i++) { - dstShape[i] = inputs[1][i]; + dstShape[i] = dstShape[i] - offset[i] * 2; } outputs.resize(1, dstShape); + return false; } void finalize(InputArrayOfArrays inputs_arr, OutputArrayOfArrays) CV_OVERRIDE { + //std::vector inputs; + //inputs_arr.getMatVector(inputs); + //CV_Assert(2 == inputs.size()); + + //const Mat& inpBlob = inputs[0]; + //const Mat& inpSzBlob = inputs[1]; + + //int dims = inpBlob.dims; + //int start_axis = normalize_axis(axis, dims); + + //std::vector offset_final(dims, 0); + //if (offset.size() == 1) + //{ + // for (int i = start_axis; i < dims; i++) + // offset_final[i] = offset[0]; + //} + //else if (offset.size() > 1) + //{ + // if ((int)offset.size() != dims - start_axis) + // CV_Error(Error::StsBadArg, "number of offset values specified must be " + // "equal to the number of dimensions following axis."); + + // for (int i = start_axis; i < dims; i++) + // offset_final[i] = offset[i - start_axis]; + //} + + //finalSliceRanges.resize(1); + //finalSliceRanges[0].resize(dims); + //for (int i = 0; i < start_axis; i++) + //{ + // finalSliceRanges[0][i] = Range(0, inpBlob.size[i]); + //} + //for (int i = start_axis; i < dims; i++) + //{ + // if (offset_final[i] < 0 || offset_final[i] + inpSzBlob.size[i] > inpBlob.size[i]) + // CV_Error(Error::StsBadArg, "invalid crop parameters or blob sizes"); + + // finalSliceRanges[0][i] = Range(offset_final[i], offset_final[i] + inpSzBlob.size[i]); + //} + + std::vector inputs; inputs_arr.getMatVector(inputs); - CV_Assert(2 == inputs.size()); + CV_Assert(1 == inputs.size()); const Mat& inpBlob = inputs[0]; - const Mat& inpSzBlob = inputs[1]; int dims = inpBlob.dims; int start_axis = normalize_axis(axis, dims); @@ -895,25 +964,29 @@ namespace cv } for (int i = start_axis; i < dims; i++) { - if (offset_final[i] < 0 || offset_final[i] + inpSzBlob.size[i] > inpBlob.size[i]) + int w = inpBlob.size[i] - offset_final[i] * 2; + if (offset_final[i] < 0 || w < 0) CV_Error(Error::StsBadArg, "invalid crop parameters or blob sizes"); - finalSliceRanges[0][i] = Range(offset_final[i], offset_final[i] + inpSzBlob.size[i]); + finalSliceRanges[0][i] = Range(offset_final[i], offset_final[i] + w); } } + static cv::Ptr create(cv::dnn::LayerParams& params) + { + return cv::Ptr(new CropCenterLayerImpl(params)); + } + private: std::vector offset; }; - Ptr SliceLayer::create(const LayerParams& params) - { - return Ptr(new SliceLayerImpl(params)); - } - - Ptr CropLayer::create(const LayerParams& params) - { - return Ptr(new CropLayerImpl(params)); - } } } + +# include + +void reg() +{ + CV_DNN_REGISTER_LAYER_CLASS(CropCenter, cv::dnn::CropCenterLayerImpl); +} \ No newline at end of file