From 2cb17714ff784a8bc5fbfb9f7acc942224d5a79e Mon Sep 17 00:00:00 2001 From: lijiancheng0614 Date: Sat, 20 Oct 2018 15:08:34 +0800 Subject: [PATCH] add polygon box transform op --- src/common/types.cpp | 2 + src/framework/load_ops.h | 3 + .../arm/polygon_box_transform_kernel.cpp | 38 ++++++ .../polygon_box_transform_arm_func.h | 53 ++++++++ .../kernel/polygon_box_transform_kernel.h | 36 +++++ src/operators/op_param.h | 22 +++ src/operators/polygon_box_transform_op.cpp | 45 +++++++ src/operators/polygon_box_transform_op.h | 56 ++++++++ test/CMakeLists.txt | 4 + .../test_polygon_box_transform_op.cpp | 126 ++++++++++++++++++ tools/op.cmake | 5 + 11 files changed, 390 insertions(+) create mode 100644 src/operators/kernel/arm/polygon_box_transform_kernel.cpp create mode 100644 src/operators/kernel/central-arm-func/polygon_box_transform_arm_func.h create mode 100644 src/operators/kernel/polygon_box_transform_kernel.h create mode 100644 src/operators/polygon_box_transform_op.cpp create mode 100644 src/operators/polygon_box_transform_op.h create mode 100644 test/operators/test_polygon_box_transform_op.cpp diff --git a/src/common/types.cpp b/src/common/types.cpp index 46e5bfab37..2a8b8c8a15 100644 --- a/src/common/types.cpp +++ b/src/common/types.cpp @@ -34,6 +34,7 @@ const char *G_OP_TYPE_FUSION_CONV_ADD = "fusion_conv_add"; const char *G_OP_TYPE_LRN = "lrn"; const char *G_OP_TYPE_MUL = "mul"; const char *G_OP_TYPE_MULTICLASS_NMS = "multiclass_nms"; +const char *G_OP_TYPE_POLYGON_BOX_TRANSFORM = "polygon_box_transform"; const char *G_OP_TYPE_POOL2D = "pool2d"; const char *G_OP_TYPE_PRIOR_BOX = "prior_box"; const char *G_OP_TYPE_RELU = "relu"; @@ -94,6 +95,7 @@ std::unordered_map< {G_OP_TYPE_FUSION_CONV_BN_ADD_RELU, {{"Input"}, {"Out"}}}, {G_OP_TYPE_PRIOR_BOX, {{"Image", "Input"}, {"Boxes", "Variances"}}}, {G_OP_TYPE_MULTICLASS_NMS, {{"BBoxes", "Scores"}, {"Out"}}}, + {G_OP_TYPE_POLYGON_BOX_TRANSFORM, {{"Input"}, {"Output"}}}, {G_OP_TYPE_FC, {{"X", "Y", "Z"}, {"Out"}}}, {G_OP_TYPE_RESHAPE, {{"X"}, {"Out"}}}, {G_OP_TYPE_DEPTHWISE_CONV, {{"Input"}, {"Output"}}}, diff --git a/src/framework/load_ops.h b/src/framework/load_ops.h index a2a6da3484..bc34b9cb60 100644 --- a/src/framework/load_ops.h +++ b/src/framework/load_ops.h @@ -199,6 +199,9 @@ LOAD_OP3(pool2d, CPU, MALI_GPU, FPGA); #ifdef MULTICLASSNMS_OP LOAD_OP1(multiclass_nms, CPU); #endif +#ifdef POLYGONBOXTRANSFORM_OP +LOAD_OP1(polygon_box_transform, CPU); +#endif #ifdef SLICE_OP LOAD_OP2(slice, CPU, MALI_GPU); #endif diff --git a/src/operators/kernel/arm/polygon_box_transform_kernel.cpp b/src/operators/kernel/arm/polygon_box_transform_kernel.cpp new file mode 100644 index 0000000000..e72c29135e --- /dev/null +++ b/src/operators/kernel/arm/polygon_box_transform_kernel.cpp @@ -0,0 +1,38 @@ +/* Copyright (c) 2018 PaddlePaddle Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +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. */ + +#ifdef POLYGONBOXTRANSFORM_OP + +#include "operators/kernel/polygon_box_transform_kernel.h" +#include "operators/kernel/central-arm-func/polygon_box_transform_arm_func.h" + +namespace paddle_mobile { +namespace operators { + +template <> +bool PolygonBoxTransformKernel::Init( + PolygonBoxTransformParam *param) { + return true; +} + +template <> +void PolygonBoxTransformKernel::Compute( + const PolygonBoxTransformParam ¶m) const { + PolygonBoxTransformCompute(param); +} + +} // namespace operators +} // namespace paddle_mobile + +#endif diff --git a/src/operators/kernel/central-arm-func/polygon_box_transform_arm_func.h b/src/operators/kernel/central-arm-func/polygon_box_transform_arm_func.h new file mode 100644 index 0000000000..6db4297046 --- /dev/null +++ b/src/operators/kernel/central-arm-func/polygon_box_transform_arm_func.h @@ -0,0 +1,53 @@ +/* Copyright (c) 2018 PaddlePaddle Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +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. */ + +#ifdef POLYGONBOXTRANSFORM_OP +#pragma once + +#include "operators/op_param.h" + +namespace paddle_mobile { +namespace operators { + +template +void PolygonBoxTransformCompute(const PolygonBoxTransformParam& param) { + const auto* input = param.Input(); + const auto& input_dims = input->dims(); + const auto* input_data = input->data(); + auto* output = param.Output(); + auto* output_data = output->mutable_data(); + + int64_t batch_size = input_dims[0]; + int64_t geo_channel = input_dims[1]; + int64_t height = input_dims[2]; + int64_t width = input_dims[3]; + int64_t id = 0; + for (int64_t id_n = 0; id_n < batch_size * geo_channel; ++id_n) { + for (int64_t id_h = 0; id_h < height; ++id_h) { + for (int64_t id_w = 0; id_w < width; ++id_w) { + id = id_n * height * width + width * id_h + id_w; + if (id_n % 2 == 0) { + output_data[id] = id_w * 4 - input_data[id]; + } else { + output_data[id] = id_h * 4 - input_data[id]; + } + } + } + } +} + +} // namespace operators +} // namespace paddle_mobile + +#endif diff --git a/src/operators/kernel/polygon_box_transform_kernel.h b/src/operators/kernel/polygon_box_transform_kernel.h new file mode 100644 index 0000000000..d5baf32cc7 --- /dev/null +++ b/src/operators/kernel/polygon_box_transform_kernel.h @@ -0,0 +1,36 @@ +/* Copyright (c) 2018 PaddlePaddle Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +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. */ + +#ifdef POLYGONBOXTRANSFORM_OP + +#pragma once + +#include "framework/operator.h" +#include "operators/op_param.h" + +namespace paddle_mobile { +namespace operators { + +template +class PolygonBoxTransformKernel + : public framework::OpKernelBase> { + public: + void Compute(const PolygonBoxTransformParam& param) const; + bool Init(PolygonBoxTransformParam* param); +}; +} // namespace operators +} // namespace paddle_mobile + +#endif diff --git a/src/operators/op_param.h b/src/operators/op_param.h index 27ab4629f0..59855cbf15 100644 --- a/src/operators/op_param.h +++ b/src/operators/op_param.h @@ -985,6 +985,28 @@ class MultiClassNMSParam : public OpParam { }; #endif +#ifdef POLYGONBOXTRANSFORM_OP +template +class PolygonBoxTransformParam : public OpParam { + typedef typename DtypeTensorTrait::gtype GType; + typedef typename DtypeTensorTrait::rtype RType; + + public: + PolygonBoxTransformParam(const VariableNameMap &inputs, + const VariableNameMap &outputs, + const AttributeMap &attrs, const Scope &scope) { + input_ = InputFrom(inputs, scope); + output_ = OutputFrom(outputs, scope); + } + const RType *Input() const { return input_; } + RType *Output() const { return output_; } + + private: + RType *input_; + RType *output_; +}; +#endif + template class FeedParam : public OpParam { typedef typename DtypeTensorTrait::gtype GType; diff --git a/src/operators/polygon_box_transform_op.cpp b/src/operators/polygon_box_transform_op.cpp new file mode 100644 index 0000000000..a3eed0e2f3 --- /dev/null +++ b/src/operators/polygon_box_transform_op.cpp @@ -0,0 +1,45 @@ +/* Copyright (c) 2018 PaddlePaddle Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +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. */ + +#ifdef POLYGONBOXTRANSFORM_OP + +#include "operators/polygon_box_transform_op.h" +namespace paddle_mobile { +namespace operators { + +template +void PolygonBoxTransformOp::InferShape() const { + PADDLE_MOBILE_ENFORCE(this->param_.Input() != nullptr, + "Input (Input) of get_shape op should not be null."); + PADDLE_MOBILE_ENFORCE(this->param_.Output() != nullptr, + "Output (Output) of get_shape op should not be null."); + + auto input_dims = this->param_.Input()->dims(); + + PADDLE_MOBILE_ENFORCE(input_dims.size() == 4, "input's rank must be 4."); + PADDLE_MOBILE_ENFORCE(input_dims[1] % 2 == 0, + "input's second dimension must be even."); + + this->param_.Output()->Resize(input_dims); +} + +} // namespace operators +} // namespace paddle_mobile + +namespace ops = paddle_mobile::operators; +#ifdef PADDLE_MOBILE_CPU +REGISTER_OPERATOR_CPU(polygon_box_transform, ops::PolygonBoxTransformOp); +#endif + +#endif diff --git a/src/operators/polygon_box_transform_op.h b/src/operators/polygon_box_transform_op.h new file mode 100644 index 0000000000..e20765f715 --- /dev/null +++ b/src/operators/polygon_box_transform_op.h @@ -0,0 +1,56 @@ +/* Copyright (c) 2018 PaddlePaddle Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +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. */ + +#ifdef POLYGONBOXTRANSFORM_OP + +#pragma once + +#include + +#include "framework/operator.h" +#include "operators/kernel/polygon_box_transform_kernel.h" +#include "operators/op_param.h" + +namespace paddle_mobile { +namespace operators { + +using paddle_mobile::framework::Tensor; + +template +class PolygonBoxTransformOp + : public framework::OperatorWithKernel< + DeviceType, PolygonBoxTransformParam, + operators::PolygonBoxTransformKernel> { + public: + PolygonBoxTransformOp(const std::string &type, const VariableNameMap &inputs, + const VariableNameMap &outputs, + const framework::AttributeMap &attrs, + std::shared_ptr scope) + : framework::OperatorWithKernel< + DeviceType, PolygonBoxTransformParam, + operators::PolygonBoxTransformKernel>( + type, inputs, outputs, attrs, scope) {} + + using framework::OperatorWithKernel< + DeviceType, PolygonBoxTransformParam, + operators::PolygonBoxTransformKernel>::OperatorWithKernel; + void InferShape() const override; + + protected: +}; + +} // namespace operators +} // namespace paddle_mobile + +#endif diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index ad3b2e5fe9..89fbbf1269 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -200,6 +200,10 @@ if (NOT FOUND_MATCH) ADD_EXECUTABLE(test-multiclassnms-op operators/test_multiclass_nms_op.cpp test_helper.h test_include.h) target_link_libraries(test-multiclassnms-op paddle-mobile) + # gen test + ADD_EXECUTABLE(test-polygon-box-transform-op operators/test_polygon_box_transform_op.cpp test_helper.h test_include.h) + target_link_libraries(test-polygon-box-transform-op paddle-mobile) + # gen test ADD_EXECUTABLE(test-reshape-op operators/test_reshape_op.cpp test_helper.h test_include.h) target_link_libraries(test-reshape-op paddle-mobile) diff --git a/test/operators/test_polygon_box_transform_op.cpp b/test/operators/test_polygon_box_transform_op.cpp new file mode 100644 index 0000000000..a71177ddbd --- /dev/null +++ b/test/operators/test_polygon_box_transform_op.cpp @@ -0,0 +1,126 @@ +/* Copyright (c) 2018 PaddlePaddle Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +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. */ + +#pragma once +#include "../test_include.h" +#include "operators/polygon_box_transform_op.h" + +namespace paddle_mobile { +namespace framework { + +template +class TestPolygonBoxTransformOp { + public: + explicit TestPolygonBoxTransformOp(const Program p) : program_(p) { + if (use_optimize_) { + to_predict_program_ = program_.optimizeProgram; + } else { + to_predict_program_ = program_.originProgram; + } + const std::vector> blocks = + to_predict_program_->Blocks(); + for (auto block_desc : blocks) { + std::vector> ops = block_desc->Ops(); + for (auto op : ops) { + if (op->Type() == "polygon_box_transform") { + DLOG << " attr size: " << op->GetAttrMap().size(); + DLOG << " inputs size: " << op->GetInputs().size(); + DLOG << " input is : " << op->Input("Input")[0]; + input_var_name = op->Input("Input")[0]; + DLOG << " outputs size: " << op->GetOutputs().size(); + DLOG << " output is : " << op->Output("Output")[0]; + output_var_name = op->Output("Output")[0]; + std::shared_ptr> + op_ptr = std::make_shared< + operators::PolygonBoxTransformOp>( + op->Type(), op->GetInputs(), op->GetOutputs(), + op->GetAttrMap(), program_.scope); + ops_of_block_[*block_desc.get()].push_back(op_ptr); + return; + } + } + } + } + + std::shared_ptr predict(const Tensor &t) { + auto scope = program_.scope; + Variable *input_feed_value = scope->Var(input_var_name); + auto tensor_input = input_feed_value->GetMutable(); + tensor_input->ShareDataWith(t); + + Variable *output = scope->Var(output_var_name); + auto *output_tensor = output->GetMutable(); + + std::shared_ptr out_tensor = std::make_shared(); + out_tensor.reset(output_tensor); + + predict(t, 0); + + return out_tensor; + } + + private: + const framework::Program program_; + std::shared_ptr to_predict_program_; + std::map>>> + ops_of_block_; + bool use_optimize_ = false; + string input_var_name; + string output_var_name; + + void predict(const Tensor &t, int block_id) { + std::shared_ptr to_predict_block = + to_predict_program_->Block(block_id); + for (int j = 0; j < ops_of_block_[*to_predict_block.get()].size(); ++j) { + auto op = ops_of_block_[*to_predict_block.get()][j]; + op->Run(); + } + } +}; + +template class TestPolygonBoxTransformOp; +} // namespace framework +} // namespace paddle_mobile + +int main() { + DLOG << "----------**********----------"; + DLOG << "begin to run PolygonBoxTransform Test"; + paddle_mobile::Loader loader; + auto program = loader.Load(std::string(g_ocr)); + + paddle_mobile::framework::Tensor input; + SetupTensor(&input, {1, 8, 1, 2}, static_cast(0), + static_cast(1)); + auto *input_ptr = input.data(); + for (int i = 0; i < 16; ++i) { + *(input_ptr + i) = i; + } + DLOG << "input : "; + for (int i = 0; i < input.numel(); ++i) { + DLOG << " index " << i << " : " << input_ptr[i]; + } + + paddle_mobile::framework::TestPolygonBoxTransformOp + testPolygonBoxTransformOp(program); + + auto output = testPolygonBoxTransformOp.predict(input); + auto *output_ptr = output->data(); + + DLOG << "output : "; + for (int i = 0; i < output->numel(); ++i) { + DLOG << " index " << i << " : " << output_ptr[i]; + } + return 0; +} diff --git a/tools/op.cmake b/tools/op.cmake index 4795568b8e..161463942f 100644 --- a/tools/op.cmake +++ b/tools/op.cmake @@ -196,6 +196,7 @@ if(NOT FOUND_MATCH) set(LRN_OP ON) set(MUL_OP ON) set(MULTICLASSNMS_OP ON) + set(POLYGONBOXTRANSFORM_OP ON) set(POOL_OP ON) set(PRIORBOX_OP ON) set(RELU_OP ON) @@ -237,6 +238,7 @@ endif() # option(LRN_OP "" ON) # option(MUL_OP "" ON) # option(MULTICLASSNMS_OP "" ON) + # option(POLYGONBOXTRANSFORM_OP "" ON) # option(POOL_OP "" ON) # option(PRIORBOX_OP "" ON) # option(RELU_OP "" ON) @@ -288,6 +290,9 @@ endif() if (MULTICLASSNMS_OP) add_definitions(-DMULTICLASSNMS_OP) endif() +if (POLYGONBOXTRANSFORM_OP) + add_definitions(-DPOLYGONBOXTRANSFORM_OP) +endif() if (POOL_OP) add_definitions(-DPOOL_OP) endif() -- GitLab