Skip to content
Snippets Groups Projects
Commit 7b678ed9 authored by Grégoire Kubler's avatar Grégoire Kubler Committed by Olivier BICHLER
Browse files

feat : implementation of resize operator

parent a81e082c
No related branches found
No related tags found
2 merge requests!118v0.4.0,!104update Resize operator
...@@ -40,6 +40,7 @@ ...@@ -40,6 +40,7 @@
#include "aidge/backend/cpu/operator/PowImpl.hpp" #include "aidge/backend/cpu/operator/PowImpl.hpp"
#include "aidge/backend/cpu/operator/ReduceMeanImpl.hpp" #include "aidge/backend/cpu/operator/ReduceMeanImpl.hpp"
#include "aidge/backend/cpu/operator/ReduceSumImpl.hpp" #include "aidge/backend/cpu/operator/ReduceSumImpl.hpp"
#include "aidge/backend/cpu/operator/ResizeImpl.hpp"
#include "aidge/backend/cpu/operator/ReLUImpl.hpp" #include "aidge/backend/cpu/operator/ReLUImpl.hpp"
#include "aidge/backend/cpu/operator/RoundImpl.hpp" #include "aidge/backend/cpu/operator/RoundImpl.hpp"
#include "aidge/backend/cpu/operator/ScalingImpl.hpp" #include "aidge/backend/cpu/operator/ScalingImpl.hpp"
......
/********************************************************************************
* Copyright (c) 2023 CEA-List
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* SPDX-License-Identifier: EPL-2.0
*
********************************************************************************/
#ifndef AIDGE_CPU_OPERATOR_RESIZEIMPL_H_
#define AIDGE_CPU_OPERATOR_RESIZEIMPL_H_
#include "aidge/backend/cpu/operator/OperatorImpl.hpp"
#include "aidge/operator/Resize.hpp"
#include "aidge/utils/Registrar.hpp"
#include <aidge/data/Interpolation.hpp>
#include <aidge/operator/Pad.hpp>
#include <cstdint>
namespace Aidge {
// Operator implementation entry point for the backend
using ResizeImpl_cpu = OperatorImpl_cpu<
Resize_Op,
void(const void *, // input
const std::vector<DimSize_t> &, // INput dims
const std::vector<DimSize_t> &, // OUTput dims
const Interpolation::CoordinateTransformation, // coord transfo
const Interpolation::Mode, // interpolation mode
const PadBorderType, // padding mode
void *)>; // output
// Implementation entry point registration to Operator
REGISTRAR(Resize_Op, "cpu", Aidge::ResizeImpl_cpu::create);
} // namespace Aidge
#endif /* AIDGE_CPU_OPERATOR_RESIZEIMPL_H_ */
/********************************************************************************
* Copyright (c) 2023 CEA-List
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* SPDX-License-Identifier: EPL-2.0
*
********************************************************************************/
#ifndef AIDGE_CPU_OPERATOR_RESIZEIMPL_FORWARD_KERNEL_H_
#define AIDGE_CPU_OPERATOR_RESIZEIMPL_FORWARD_KERNEL_H_
#include "aidge/backend/cpu/operator/ResizeImpl.hpp"
#include <aidge/data/Data.hpp>
#include <aidge/data/half.hpp>
#include <aidge/operator/Pad.hpp>
#include <cmath>
#include <cstdint>
#include <numeric>
#include "aidge/backend/cpu/data/Interpolation.hpp"
#include "aidge/data/Interpolation.hpp"
#include "aidge/data/Tensor.hpp"
#include "aidge/utils/Registrar.hpp"
#include "aidge/utils/Types.h"
namespace Aidge {
template <typename IO>
void ResizeImpl_cpu_forward_kernel(
const void *input_,
const std::vector<DimSize_t> &inputDims,
const std::vector<DimSize_t> &outputDims,
const Interpolation::CoordinateTransformation coordTransfoMode,
const Interpolation::Mode interpMode,
const PadBorderType paddingMode,
// const double * /*roi*/,
// const float * /*scales*/,
// const int64_t * /*sizes*/,
void *output_) {
// Seting a data
const IO *input = static_cast<const IO *>(input_);
IO *output = static_cast<IO *>(output_);
DimSize_t outputLen = std::accumulate(outputDims.begin(),
outputDims.end(),
1,
std::multiplies<DimSize_t>());
std::vector<float> coordInApprox;
std::vector<DimSize_t> coordOut;
for (DimSize_t idxFlatOut = 0; idxFlatOut < outputLen; ++idxFlatOut) {
coordOut = Tensor::getCoord(outputDims, idxFlatOut);
coordInApprox =
Interpolation::untransformCoordinates(coordOut,
inputDims,
outputDims,
coordTransfoMode);
std::set<Interpolation::Point<IO>> neighbours =
InterpolationCPU::retrieveNeighbours(input,
inputDims,
coordInApprox,
paddingMode);
output[idxFlatOut] = InterpolationCPU::interpolate(coordInApprox,
neighbours,
interpMode);
}
return;
}
// Kernels registration to implementation entry point
REGISTRAR(ResizeImpl_cpu,
{{{DataType::Int16},
{DataType::Float32},
{DataType::Float32},
{DataType::Int64}},
{DataType::Int16}},
{ProdConso::inPlaceModel,
ResizeImpl_cpu_forward_kernel<int16_t>,
nullptr});
REGISTRAR(ResizeImpl_cpu,
{{{DataType::Int32},
{DataType::Float32},
{DataType::Float32},
{DataType::Int64}},
{DataType::Int32}},
{ProdConso::inPlaceModel,
ResizeImpl_cpu_forward_kernel<int32_t>,
nullptr});
REGISTRAR(ResizeImpl_cpu,
{{{DataType::Int64},
{DataType::Float32},
{DataType::Float32},
{DataType::Int64}},
{DataType::Int64}},
{ProdConso::inPlaceModel,
ResizeImpl_cpu_forward_kernel<int64_t>,
nullptr});
REGISTRAR(ResizeImpl_cpu,
{{{DataType::Float16},
{DataType::Float32},
{DataType::Float32},
{DataType::Int64}},
{DataType::Float16}},
{ProdConso::inPlaceModel,
ResizeImpl_cpu_forward_kernel<half_float::half>,
nullptr});
REGISTRAR(ResizeImpl_cpu,
{{{DataType::Float32},
{DataType::Float32},
{DataType::Float32},
{DataType::Int64}},
{DataType::Float32}},
{ProdConso::inPlaceModel,
ResizeImpl_cpu_forward_kernel<float>,
nullptr});
REGISTRAR(ResizeImpl_cpu,
{{{DataType::Float64},
{DataType::Float32},
{DataType::Float32},
{DataType::Int64}},
{DataType::Float64}},
{ProdConso::inPlaceModel,
ResizeImpl_cpu_forward_kernel<double>,
nullptr});
} // namespace Aidge
#endif /* AIDGE_CPU_OPERATOR_RESIZEIMPL_FORWARD_KERNEL_H_ */
/********************************************************************************
* Copyright (c) 2023 CEA-List
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* SPDX-License-Identifier: EPL-2.0
*
********************************************************************************/
#include "aidge/backend/cpu/operator/ResizeImpl.hpp"
#include "aidge/backend/cpu/operator/ResizeImpl_kernels.hpp"
#include "aidge/operator/Resize.hpp"
#include <cassert>
#include <cstdint>
#include <sys/stat.h>
#include "aidge/backend/OperatorImpl.hpp"
#include "aidge/utils/ErrorHandling.hpp"
namespace Aidge {
template <> void ResizeImpl_cpu::forward() {
auto &op = dynamic_cast<const Resize_Op &>(mOp);
/** @brief input #0 */
int8_t idxData = 0;
const bool input0DataPresent =
op.getInput(idxData) && !op.getInput(idxData)->undefined();
///////////////////////////////////////
// CHECKING NODE CONNECTIONS
AIDGE_ASSERT(input0DataPresent, "{}: missing data input #0", op.type());
///////////////////////////////////////
// CALL TO FORWARD
const auto impl =
Registrar<ResizeImpl_cpu>::create(getBestMatch(getRequiredSpec()));
impl.forward(op.getInput(idxData)->getImpl()->rawPtr(),
op.getInput(idxData)->dims(),
op.getOutput(0)->dims(),
op.coordinateTransformationMode(),
op.interpolationMode(),
op.paddingMode(),
op.getOutput(0)->getImpl()->rawPtr() // output pointer
);
}
template <> void Aidge::ResizeImpl_cpu::backward() {
AIDGE_THROW_OR_ABORT(
std::runtime_error,
"Backward not yet implemented for Slice_Op on backend cpu");
}
} // namespace Aidge
/********************************************************************************
* Copyright (c) 2023 CEA-List
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* SPDX-License-Identifier: EPL-2.0
*
********************************************************************************/
#include <aidge/data/Data.hpp>
#include <aidge/data/Interpolation.hpp>
#include <aidge/data/half.hpp>
#include <aidge/operator/Pad.hpp>
#include <aidge/utils/ArrayHelpers.hpp>
#include <catch2/catch_test_macros.hpp>
#include <cstdint>
#include <memory>
#include "aidge/data/Tensor.hpp"
#include "aidge/operator/OperatorTensor.hpp"
#include "aidge/operator/Resize.hpp"
#include "aidge/utils/TensorUtils.hpp"
namespace Aidge {
void setupTestResize(std::shared_ptr<Resize_Op> op,
Interpolation::Mode interpMode,
Interpolation::CoordinateTransformation coordTransfoMode,
PadBorderType paddingMode,
std::shared_ptr<Tensor> input,
std::shared_ptr<Tensor> roi,
std::shared_ptr<Tensor> scales,
std::shared_ptr<Tensor> sizes) {
////////////////////////////////////
// attributes
op->interpolationMode() = interpMode;
op->coordinateTransformationMode() = coordTransfoMode;
op->paddingMode() = paddingMode;
////////////////////////////////////
// op backend & inputs
op->setBackend("cpu");
input->setBackend("cpu");
op->associateInput(0, input);
if (scales != nullptr) {
scales->setBackend("cpu");
op->associateInput(2, scales);
if (roi != nullptr) {
roi->setBackend("cpu");
op->associateInput(1, roi);
}
} else if (sizes != nullptr) {
sizes->setBackend("cpu");
op->associateInput(3, sizes);
} else {
Log::warn("Test Resize Impl : Neither scales nor sizes provided. test "
"is excpected to crash.");
}
}
TEST_CASE("[cpu/operator] Resize(forward)", "[Resize][CPU]") {
Log::setConsoleLevel(Log::Level::Debug);
std::shared_ptr<Node> node = Resize();
auto op = std::static_pointer_cast<Resize_Op>(node->getOperator());
std::shared_ptr<Tensor> input;
std::shared_ptr<Tensor> roi;
std::shared_ptr<Tensor> scales;
std::shared_ptr<Tensor> sizes;
std::shared_ptr<Tensor> expectedOutput;
SECTION("1-sized input tensor (upscaling)") {
setupTestResize(
op,
Interpolation::Linear,
Interpolation::CoordinateTransformation::HalfPixel,
PadBorderType::Nearest,
std::make_shared<Tensor>(
Array4D<float, 1, 1, 1, 1>{{{{{0.417022}}}}}),
nullptr,
nullptr,
std::make_shared<Tensor>(Array1D<int64_t, 4>{1, 1, 2, 2}));
op->setDataType(DataType::Float32);
op->forwardDims(true);
op->forward();
expectedOutput = std::make_shared<Tensor>(Array4D<float, 1, 1, 2, 2>{
{{{{0.417022, 0.417022}, {0.417022, 0.417022}}}}});
op->getOutput(0)->print();
CHECK(approxEq<float>(*op->getOutput(0), *expectedOutput) == true);
}
SECTION("Upscaling from 5x5 to 10x10 (linear)") {
setupTestResize(
op,
Interpolation::Linear,
Interpolation::Asymmetric,
PadBorderType::Nearest,
std::make_shared<Tensor>(
Array4D<float, 1, 1, 5, 5>{{{{{7.20324516e-01,
1.14374816e-04,
3.02332580e-01,
1.46755889e-01,
9.23385918e-02},
{1.86260208e-01,
3.45560730e-01,
3.96767467e-01,
5.38816750e-01,
4.19194520e-01},
{6.85219526e-01,
2.04452246e-01,
8.78117442e-01,
2.73875929e-02,
6.70467496e-01},
{4.17304814e-01,
5.58689833e-01,
1.40386939e-01,
1.98101491e-01,
8.00744593e-01},
{9.68261600e-01,
3.13424170e-01,
6.92322612e-01,
8.76389146e-01,
8.94606650e-01}}}}}
),
nullptr,
nullptr,
std::make_shared<Tensor>(Array1D<int64_t, 4>{1, 1, 10, 10}));
op->setDataType(DataType::Float32);
op->forwardDims(true);
op->forward();
expectedOutput = std::make_shared<Tensor>(
Array4D<float, 1, 1, 10, 10>{{{{{7.20324516e-01,
3.60219449e-01,
1.14374816e-04,
1.51223481e-01,
3.02332580e-01,
2.24544227e-01,
1.46755889e-01,
1.19547240e-01,
9.23385918e-02,
9.23385918e-02},
{4.53292370e-01,
3.13064963e-01,
1.72837555e-01,
2.61193782e-01,
3.49550009e-01,
3.46168160e-01,
3.42786312e-01,
2.99276441e-01,
2.55766571e-01,
2.55766571e-01},
{1.86260208e-01,
2.65910476e-01,
3.45560730e-01,
3.71164083e-01,
3.96767467e-01,
4.67792094e-01,
5.38816750e-01,
4.79005635e-01,
4.19194520e-01,
4.19194520e-01},
{4.35739875e-01,
3.55373204e-01,
2.75006473e-01,
4.56224471e-01,
6.37442470e-01,
4.60272312e-01,
2.83102185e-01,
4.13966596e-01,
5.44831038e-01,
5.44831038e-01},
{6.85219526e-01,
4.44835901e-01,
2.04452246e-01,
5.41284859e-01,
8.78117442e-01,
4.52752531e-01,
2.73875929e-02,
3.48927557e-01,
6.70467496e-01,
6.70467496e-01},
{5.51262140e-01,
4.66416597e-01,
3.81571054e-01,
4.45411623e-01,
5.09252191e-01,
3.10998380e-01,
1.12744540e-01,
4.24175322e-01,
7.35606015e-01,
7.35606015e-01},
{4.17304814e-01,
4.87997323e-01,
5.58689833e-01,
3.49538386e-01,
1.40386939e-01,
1.69244215e-01,
1.98101491e-01,
4.99423027e-01,
8.00744593e-01,
8.00744593e-01},
{6.92783237e-01,
5.64420104e-01,
4.36057001e-01,
4.26205903e-01,
4.16354775e-01,
4.76800054e-01,
5.37245333e-01,
6.92460477e-01,
8.47675622e-01,
8.47675622e-01},
{9.68261600e-01,
6.40842915e-01,
3.13424170e-01,
5.02873421e-01,
6.92322612e-01,
7.84355879e-01,
8.76389146e-01,
8.85497928e-01,
8.94606650e-01,
8.94606650e-01},
{9.68261600e-01,
6.40842915e-01,
3.13424170e-01,
5.02873421e-01,
6.92322612e-01,
7.84355879e-01,
8.76389146e-01,
8.85497928e-01,
8.94606650e-01,
8.94606650e-01}}}}});
Log::notice("Expected result : dims = {}", expectedOutput->dims());
expectedOutput->print();
Log::notice("\nActual result: dims = {}", op->getOutput(0)->dims());
op->getOutput(0)->print();
CHECK(approxEq<float>(*op->getOutput(0),
*expectedOutput,
1e-5f,
1e-5f) == true);
}
}
} // namespace Aidge
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment