| 
									
										
										
										
											2020-11-05 16:41:56 +08:00
										 |  |  | //
 | 
					
						
							|  |  |  | //  GeometryImageOp.cpp
 | 
					
						
							|  |  |  | //  MNN
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | //  Created by MNN on 2020/05/07.
 | 
					
						
							|  |  |  | //  Copyright © 2018, Alibaba Group Holding Limited
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "ConvertUtils.hpp"
 | 
					
						
							|  |  |  | #include "geometry/GeometryComputer.hpp"
 | 
					
						
							|  |  |  | #include "geometry/GeometryComputerUtils.hpp"
 | 
					
						
							|  |  |  | #include "shape/SizeComputer.hpp"
 | 
					
						
							|  |  |  | namespace MNN { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-30 10:02:52 +08:00
										 |  |  | static flatbuffers::Offset<Op> makeInterp(flatbuffers::FlatBufferBuilder& builder, const InterpInfo* info, int resizeType, const Op* op, OpType type) { | 
					
						
							| 
									
										
										
										
											2022-09-07 15:56:08 +08:00
										 |  |  |     flatbuffers::Offset<flatbuffers::String> temp; | 
					
						
							|  |  |  |     if (nullptr != op->name()) { | 
					
						
							|  |  |  |         temp = builder.CreateString(op->name()->str()); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2022-09-27 17:07:23 +08:00
										 |  |  |     InterpBuilder intp3DB(builder); | 
					
						
							| 
									
										
										
										
											2022-09-07 15:56:08 +08:00
										 |  |  |     intp3DB.add_resizeType(resizeType); | 
					
						
							|  |  |  |     intp3DB.add_widthScale(info->widthScale); | 
					
						
							|  |  |  |     intp3DB.add_heightScale(info->heightScale); | 
					
						
							|  |  |  |     intp3DB.add_depthScale(info->depthScale); | 
					
						
							|  |  |  |     intp3DB.add_heightOffset(info->heightOffset); | 
					
						
							|  |  |  |     intp3DB.add_widthOffset(info->widthOffset); | 
					
						
							|  |  |  |     intp3DB.add_depthOffset(info->depthOffset); | 
					
						
							|  |  |  |     auto offsetInterp3D = intp3DB.Finish().Union(); | 
					
						
							|  |  |  |     OpBuilder opB(builder); | 
					
						
							| 
									
										
										
										
											2022-09-30 10:02:52 +08:00
										 |  |  |     opB.add_type(type); | 
					
						
							| 
									
										
										
										
											2022-09-07 15:56:08 +08:00
										 |  |  |     opB.add_main(offsetInterp3D); | 
					
						
							| 
									
										
										
										
											2022-09-27 17:07:23 +08:00
										 |  |  |     opB.add_main_type(OpParameter_Interp); | 
					
						
							| 
									
										
										
										
											2022-09-07 15:56:08 +08:00
										 |  |  |     if (nullptr != op->name()) { | 
					
						
							|  |  |  |         opB.add_name(temp); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return opB.Finish(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-05 16:41:56 +08:00
										 |  |  | class GeometryImageOp : public GeometryComputer { | 
					
						
							|  |  |  | public: | 
					
						
							|  |  |  |     virtual bool onCompute(const Op* op, const std::vector<Tensor*>& inputs, const std::vector<Tensor*>& outputs, | 
					
						
							|  |  |  |                            Context& context, CommandBuffer& res) const override { | 
					
						
							|  |  |  |         auto newOutputs   = outputs; | 
					
						
							|  |  |  |         auto newInputs    = inputs; | 
					
						
							|  |  |  |         auto originOutput = outputs[0]; | 
					
						
							|  |  |  |         auto output       = originOutput; | 
					
						
							|  |  |  |         auto inputDes     = TensorUtils::getDescribe(newInputs[0]); | 
					
						
							|  |  |  |         auto format       = inputDes->dimensionFormat; | 
					
						
							|  |  |  |         if (MNN_DATA_FORMAT_NC4HW4 != format) { | 
					
						
							|  |  |  |             std::shared_ptr<Tensor> newInput(new Tensor(newInputs[0], Tensor::CAFFE_C4, false)); | 
					
						
							|  |  |  |             ConvertUtils::compute(newInputs[0], newInput.get(), res); | 
					
						
							|  |  |  |             newInputs[0] = newInput.get(); | 
					
						
							|  |  |  |             res.extras.emplace_back(std::move(newInput)); | 
					
						
							|  |  |  |             std::shared_ptr<Tensor> newOutput(new Tensor(originOutput, Tensor::CAFFE_C4, false)); | 
					
						
							|  |  |  |             output        = newOutput.get(); | 
					
						
							|  |  |  |             newOutputs[0] = output; | 
					
						
							|  |  |  |             res.extras.emplace_back(newOutput); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (OpType_Resize == op->type()) { | 
					
						
							|  |  |  |             // Turn resize to interp
 | 
					
						
							| 
									
										
										
										
											2021-02-07 10:45:07 +08:00
										 |  |  |             InterpInfo info; | 
					
						
							|  |  |  |             info.widthScale = (float)inputs[0]->width() / (float)outputs[0]->width(); | 
					
						
							|  |  |  |             info.heightScale = (float)inputs[0]->height() / (float)outputs[0]->height(); | 
					
						
							|  |  |  |             flatbuffers::FlatBufferBuilder builder; | 
					
						
							| 
									
										
										
										
											2022-09-30 10:02:52 +08:00
										 |  |  |             builder.Finish(makeInterp(builder, &info, 2, op, OpType_Interp)); | 
					
						
							| 
									
										
										
										
											2021-06-11 17:17:13 +08:00
										 |  |  |             res.command.emplace_back(GeometryComputerUtils::makeCommand(builder, {newInputs[0]}, newOutputs)); | 
					
						
							| 
									
										
										
										
											2020-11-05 16:41:56 +08:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2022-09-30 10:02:52 +08:00
										 |  |  |         else if (OpType_Interp == op->type() && inputs[0]->dimensions() <= 4) { | 
					
						
							| 
									
										
										
										
											2020-11-05 16:41:56 +08:00
										 |  |  |             // Compute cord transform for interp
 | 
					
						
							|  |  |  |             auto resize                           = op->main_as_Interp(); | 
					
						
							|  |  |  |             auto inW = inputs[0]->width(); | 
					
						
							|  |  |  |             auto inH = inputs[0]->height(); | 
					
						
							|  |  |  |             auto outW = outputs[0]->width(); | 
					
						
							|  |  |  |             auto outH = outputs[0]->height(); | 
					
						
							| 
									
										
										
										
											2021-02-07 10:45:07 +08:00
										 |  |  |             InterpInfo info; | 
					
						
							| 
									
										
										
										
											2021-09-03 19:22:30 +08:00
										 |  |  |             bool computeScale = true; | 
					
						
							|  |  |  |             if (inputs.size() > 1 && inputs[1]->getType().code == halide_type_float) { | 
					
						
							|  |  |  |                 computeScale = false; | 
					
						
							|  |  |  |                 info.heightScale = 1.0f / inputs[1]->host<float>()[2]; | 
					
						
							|  |  |  |                 if (inputs[0]->dimensions() >= 4) { | 
					
						
							|  |  |  |                     info.widthScale = 1.0f / inputs[1]->host<float>()[3]; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2022-09-30 10:02:52 +08:00
										 |  |  |             const int defaultDepth = 10; | 
					
						
							|  |  |  |             _ConverterInterp(resize, &info, inW, inH, defaultDepth, outW, outH, defaultDepth, computeScale); | 
					
						
							| 
									
										
										
										
											2021-02-07 10:45:07 +08:00
										 |  |  |             flatbuffers::FlatBufferBuilder builder; | 
					
						
							| 
									
										
										
										
											2022-09-30 10:02:52 +08:00
										 |  |  |             builder.Finish(makeInterp(builder, &info, resize->resizeType(), op, OpType_Interp)); | 
					
						
							| 
									
										
										
										
											2021-06-11 17:17:13 +08:00
										 |  |  |             res.command.emplace_back(GeometryComputerUtils::makeCommand(builder, {newInputs[0]}, newOutputs)); | 
					
						
							| 
									
										
										
										
											2023-06-16 09:42:45 +08:00
										 |  |  |         } else if (OpType_Interp == op->type() && inputs[0]->dimensions() == 5) { | 
					
						
							| 
									
										
										
										
											2022-09-07 15:56:08 +08:00
										 |  |  |             // Compute cord transform for interp
 | 
					
						
							| 
									
										
										
										
											2022-09-27 17:07:23 +08:00
										 |  |  |             auto resize                           = op->main_as_Interp(); | 
					
						
							| 
									
										
										
										
											2022-09-30 10:02:52 +08:00
										 |  |  |             auto inShape = newInputs[0]->shape(); | 
					
						
							|  |  |  |             auto outShape = newOutputs[0]->shape(); | 
					
						
							| 
									
										
										
										
											2022-09-07 15:56:08 +08:00
										 |  |  |             auto inW = inShape[4]; | 
					
						
							|  |  |  |             auto inH = inShape[3]; | 
					
						
							|  |  |  |             auto inD = inShape[2]; | 
					
						
							|  |  |  |             auto outW = outShape[4]; | 
					
						
							|  |  |  |             auto outH = outShape[3]; | 
					
						
							|  |  |  |             auto outD = outShape[2]; | 
					
						
							| 
									
										
										
										
											2022-09-30 10:02:52 +08:00
										 |  |  |             InterpInfo info; | 
					
						
							| 
									
										
										
										
											2022-09-07 15:56:08 +08:00
										 |  |  |             bool computeScale = true; | 
					
						
							|  |  |  |             if (inputs.size() > 1 && inputs[1]->getType().code == halide_type_float) { | 
					
						
							|  |  |  |                 computeScale = false; | 
					
						
							|  |  |  |                 info.depthScale = 1.0f / inputs[1]->host<float>()[2]; | 
					
						
							| 
									
										
										
										
											2022-09-30 10:02:52 +08:00
										 |  |  |                 info.heightScale = 1.0f / inputs[1]->host<float>()[3]; | 
					
						
							|  |  |  |                 info.widthScale = 1.0f / inputs[1]->host<float>()[4]; | 
					
						
							| 
									
										
										
										
											2022-09-07 15:56:08 +08:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2022-09-30 10:02:52 +08:00
										 |  |  |             _ConverterInterp(resize, &info, inW, inH, inD, outW, outH, outD, computeScale); | 
					
						
							| 
									
										
										
										
											2022-09-07 15:56:08 +08:00
										 |  |  |             flatbuffers::FlatBufferBuilder builder; | 
					
						
							| 
									
										
										
										
											2022-09-30 10:02:52 +08:00
										 |  |  |             builder.Finish(makeInterp(builder, &info, resize->resizeType(), op, OpType_Interp3D)); | 
					
						
							| 
									
										
										
										
											2022-09-07 15:56:08 +08:00
										 |  |  |             res.command.emplace_back(GeometryComputerUtils::makeCommand(builder, {newInputs[0]}, newOutputs)); | 
					
						
							| 
									
										
										
										
											2020-11-05 16:41:56 +08:00
										 |  |  |         } else { | 
					
						
							| 
									
										
										
										
											2024-04-19 11:58:21 +08:00
										 |  |  |             std::shared_ptr<Command> cmdP(new Command); | 
					
						
							| 
									
										
										
										
											2021-11-30 10:10:53 +08:00
										 |  |  |             auto& cmd = *cmdP;; | 
					
						
							| 
									
										
										
										
											2020-11-05 16:41:56 +08:00
										 |  |  |             cmd.op      = op; | 
					
						
							|  |  |  |             cmd.inputs  = std::move(newInputs); | 
					
						
							|  |  |  |             cmd.outputs = std::move(newOutputs); | 
					
						
							| 
									
										
										
										
											2021-11-30 10:10:53 +08:00
										 |  |  |             res.command.emplace_back(std::move(cmdP)); | 
					
						
							| 
									
										
										
										
											2020-11-05 16:41:56 +08:00
										 |  |  |         } | 
					
						
							|  |  |  |         if (originOutput != output) { | 
					
						
							|  |  |  |             ConvertUtils::compute(output, originOutput, res); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         return true; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void _create() { | 
					
						
							|  |  |  |     std::shared_ptr<GeometryComputer> comp(new GeometryImageOp); | 
					
						
							|  |  |  |     GeometryComputer::registerGeometryComputer( | 
					
						
							| 
									
										
										
										
											2020-11-19 14:21:51 +08:00
										 |  |  |         comp, { | 
					
						
							|  |  |  |         OpType_ConvInt8, | 
					
						
							|  |  |  |         OpType_DepthwiseConvInt8, | 
					
						
							|  |  |  |         OpType_ConvolutionDepthwise, | 
					
						
							|  |  |  |         OpType_DeconvolutionDepthwise, | 
					
						
							|  |  |  |         OpType_Pooling, | 
					
						
							|  |  |  |         OpType_Interp, | 
					
						
							| 
									
										
										
										
											2022-09-07 15:56:08 +08:00
										 |  |  |         OpType_Interp3D, | 
					
						
							| 
									
										
										
										
											2020-11-19 14:21:51 +08:00
										 |  |  |         OpType_Resize, | 
					
						
							|  |  |  |         OpType_Int8ToFloat, | 
					
						
							|  |  |  |         OpType_FloatToInt8 | 
					
						
							|  |  |  |     }); | 
					
						
							| 
									
										
										
										
											2020-11-05 16:41:56 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | REGISTER_GEOMETRY(GeometryImageOp, _create); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } // namespace MNN
 |