diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 5501751da..794924cc8 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -216,6 +216,7 @@ ncnn_add_layer(HardSigmoid) ncnn_add_layer(SELU) ncnn_add_layer(HardSwish) ncnn_add_layer(Noop) +ncnn_add_layer(PixelShuffle) if(NCNN_VULKAN) ncnn_add_shader(${CMAKE_CURRENT_SOURCE_DIR}/convert_ycbcr.comp) diff --git a/src/layer/pixelshuffle.cpp b/src/layer/pixelshuffle.cpp new file mode 100644 index 000000000..ed097adc8 --- /dev/null +++ b/src/layer/pixelshuffle.cpp @@ -0,0 +1,78 @@ +// Tencent is pleased to support the open source community by making ncnn available. +// +// Copyright (C) 2020 THL A29 Limited, a Tencent company. All rights reserved. +// +// Licensed under the BSD 3-Clause License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// https://opensource.org/licenses/BSD-3-Clause +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#include "pixelshuffle.h" + +namespace ncnn { + +DEFINE_LAYER_CREATOR(PixelShuffle) + +PixelShuffle::PixelShuffle() +{ + one_blob_only = true; + support_inplace = false; +} + +int PixelShuffle::load_param(const ParamDict& pd) +{ + upscale_factor = pd.get(0, 1); + + return 0; +} + +int PixelShuffle::forward(const Mat& bottom_blob, Mat& top_blob, const Option& opt) const +{ + int w = bottom_blob.w; + int h = bottom_blob.h; + int channels = bottom_blob.c; + size_t elemsize = bottom_blob.elemsize; + + int outw = w * upscale_factor; + int outh = h * upscale_factor; + int outc = channels / (upscale_factor * upscale_factor); + + top_blob.create(outw, outh, outc, elemsize, opt.blob_allocator); + if (top_blob.empty()) + return -100; + + #pragma omp parallel for num_threads(opt.num_threads) + for (int p = 0; p < outc; p++) + { + Mat m = top_blob.channel(p); + + for (int sh = 0; sh < upscale_factor; sh++) + { + for (int sw = 0; sw < upscale_factor; sw++) + { + const float* sptr = bottom_blob.channel(p*upscale_factor*upscale_factor + sh*upscale_factor + sw); + + for (int i = 0; i < h; i++) + { + float* outptr = m.row(i*upscale_factor + sh) + sw; + for (int j = 0; j < w; j++) + { + outptr[0] = sptr[0]; + + sptr++; + outptr += upscale_factor; + } + } + } + } + } + + return 0; +} + +} // namespace ncnn diff --git a/src/layer/pixelshuffle.h b/src/layer/pixelshuffle.h new file mode 100644 index 000000000..93c9afa12 --- /dev/null +++ b/src/layer/pixelshuffle.h @@ -0,0 +1,37 @@ +// Tencent is pleased to support the open source community by making ncnn available. +// +// Copyright (C) 2020 THL A29 Limited, a Tencent company. All rights reserved. +// +// Licensed under the BSD 3-Clause License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// https://opensource.org/licenses/BSD-3-Clause +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef LAYER_PIXELSHUFFLE_H +#define LAYER_PIXELSHUFFLE_H + +#include "layer.h" + +namespace ncnn { + +class PixelShuffle : public Layer +{ +public: + PixelShuffle(); + + virtual int load_param(const ParamDict& pd); + + virtual int forward(const Mat& bottom_blob, Mat& top_blob, const Option& opt) const; + +public: + int upscale_factor; +}; + +} // namespace ncnn + +#endif // LAYER_PIXELSHUFFLE_H