chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,140 @@
|
||||
/* ******************************************************************************
|
||||
*
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Apache License, Version 2.0 which is available at
|
||||
* https://www.apache.org/licenses/LICENSE-2.0.
|
||||
*
|
||||
* See the NOTICE file distributed with this work for additional
|
||||
* information regarding copyright ownership.
|
||||
* 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.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
******************************************************************************/
|
||||
|
||||
//
|
||||
// @author George A. Shulinok <sgazeos@gmail.com>
|
||||
//
|
||||
|
||||
#include <system/op_boilerplate.h>
|
||||
#if NOT_EXCLUDED(OP_adjust_contrast)
|
||||
|
||||
#include <array/NDArrayFactory.h>
|
||||
#include <ops/declarable/headers/parity_ops.h>
|
||||
|
||||
namespace sd {
|
||||
namespace ops {
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
CONFIGURABLE_OP_IMPL(adjust_contrast, 1, 1, true, 0, 0) {
|
||||
auto input = INPUT_VARIABLE(0);
|
||||
auto output = OUTPUT_VARIABLE(0);
|
||||
|
||||
// just skip op if input is empty
|
||||
if (input->isEmpty()) return Status::OK;
|
||||
|
||||
REQUIRE_TRUE(block.numT() > 0 || block.width() > 1, 0, "ADJUST_CONTRAST: Scale factor required");
|
||||
REQUIRE_TRUE(input->rankOf() > 2, 0, "ADJUST_CONTRAST: op expects rank of input array to be >= 3, but got %i instead",
|
||||
input->rankOf());
|
||||
|
||||
|
||||
NDArray* factor = nullptr;
|
||||
|
||||
if (block.width() > 1)
|
||||
factor = INPUT_VARIABLE(1);
|
||||
else {
|
||||
factor = new NDArray(output->dataType(), block.launchContext());
|
||||
#ifdef HAS_DOUBLE
|
||||
factor->p(0, static_cast<double>(T_ARG(0)));
|
||||
#elif defined(HAS_FLOAT32)
|
||||
factor->p(0, static_cast<float>(T_ARG(0)));
|
||||
#else
|
||||
#error "No floating-point type available for adjust_contrast operation"
|
||||
#endif
|
||||
}
|
||||
|
||||
// fill up axes vector first
|
||||
std::vector<LongType> axes(input->rankOf() - 1);
|
||||
for (size_t i = 0; i < axes.size(); ++i) axes[i] = i;
|
||||
// mean as reduction for last dimension set
|
||||
auto* mean = input->reduceAlongDimension(reduce::Mean, &axes);
|
||||
auto* part1 = (*input) - (*mean);
|
||||
auto* part2 = (*part1) * (*factor);
|
||||
delete part1;
|
||||
auto* part3 = (*part2) + (*mean);
|
||||
delete part2;
|
||||
delete mean;
|
||||
// this is contrast calculation
|
||||
output->assign(part3);
|
||||
delete part3;
|
||||
|
||||
return Status::OK;
|
||||
}
|
||||
|
||||
DECLARE_TYPES(adjust_contrast) {
|
||||
getOpDescriptor()->setAllowedInputTypes(ANY)->setAllowedOutputTypes({ALL_FLOATS})->setSameMode(true);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
CONFIGURABLE_OP_IMPL(adjust_contrast_v2, 1, 1, true, 0, 0) {
|
||||
auto input = INPUT_VARIABLE(0);
|
||||
auto output = OUTPUT_VARIABLE(0);
|
||||
// just skip op if input is empty
|
||||
if (input->isEmpty()) return Status::OK;
|
||||
|
||||
REQUIRE_TRUE(input->rankOf() > 2, 0,
|
||||
"ADJUST_CONTRAST_V2: op expects rank of input array to be >= 3, but got %i instead", input->rankOf());
|
||||
REQUIRE_TRUE(block.numT() > 0 || block.width() > 1, 0, "ADJUST_CONTRAST_V2: Scale factor required");
|
||||
|
||||
NDArray* factor = nullptr;
|
||||
auto size = input->sizeAt(-2) * input->sizeAt(-3);
|
||||
auto channels = input->sizeAt(-1);
|
||||
int sizeChannels = sd::math::sd_max<int>(1,size * channels);
|
||||
auto batch = input->lengthOf() / sizeChannels;
|
||||
std::vector<LongType> shape = {batch, size, channels};
|
||||
auto* input3D = input->reshape(input->ordering(), shape);
|
||||
auto* output3D = input->reshape(input->ordering(), shape);
|
||||
|
||||
if (block.width() > 1) {
|
||||
factor = INPUT_VARIABLE(1);
|
||||
}
|
||||
else {
|
||||
factor = new NDArray(output->dataType(), block.launchContext());
|
||||
#ifdef HAS_DOUBLE
|
||||
factor->p(0, static_cast<double>(T_ARG(0)));
|
||||
#elif defined(HAS_FLOAT32)
|
||||
factor->p(0, static_cast<float>(T_ARG(0)));
|
||||
#else
|
||||
#error "No floating-point type available for adjust_contrast_v2 operation"
|
||||
#endif
|
||||
}
|
||||
|
||||
std::vector<LongType> axes({1}); // dim 1 of pseudoresult
|
||||
// mean as reduction for last dimension set over size (dim 1) of result3D
|
||||
auto* mean = input3D->reduceAlongDimension(reduce::Mean, &axes);
|
||||
// result as (x - mean) * factor + mean
|
||||
auto* temp = input3D->ulike();
|
||||
std::vector<LongType> zeroTwo = {0, 2};
|
||||
input3D->applyBroadcast(broadcast::Subtract,&zeroTwo, mean, temp);
|
||||
temp->applyScalarArr(scalar::Multiply, factor, temp);
|
||||
temp->applyBroadcast(broadcast::Add, &zeroTwo, mean, output3D);
|
||||
output->assign(output3D);
|
||||
delete temp;
|
||||
delete mean;
|
||||
delete input3D;
|
||||
delete output3D;
|
||||
return Status::OK;
|
||||
}
|
||||
|
||||
DECLARE_TYPES(adjust_contrast_v2) {
|
||||
getOpDescriptor()->setAllowedInputTypes({ALL_FLOATS})->setAllowedOutputTypes({ALL_FLOATS})->setSameMode(true);
|
||||
}
|
||||
|
||||
} // namespace ops
|
||||
} // namespace sd
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,92 @@
|
||||
/* ******************************************************************************
|
||||
*
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Apache License, Version 2.0 which is available at
|
||||
* https://www.apache.org/licenses/LICENSE-2.0.
|
||||
*
|
||||
* See the NOTICE file distributed with this work for additional
|
||||
* information regarding copyright ownership.
|
||||
* 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.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
******************************************************************************/
|
||||
|
||||
//
|
||||
// @author raver119@gmail.com
|
||||
// @author Yurii Shyrma (iuriish@yahoo.com)
|
||||
//
|
||||
|
||||
#include <system/op_boilerplate.h>
|
||||
#if NOT_EXCLUDED(OP_adjust_hue)
|
||||
|
||||
#include <ops/declarable/headers/parity_ops.h>
|
||||
#include <ops/declarable/helpers/adjust_hue.h>
|
||||
|
||||
namespace sd {
|
||||
namespace ops {
|
||||
|
||||
CONFIGURABLE_OP_IMPL(adjust_hue, 1, 1, true, 0, 0) {
|
||||
auto input = INPUT_VARIABLE(0);
|
||||
auto output = OUTPUT_VARIABLE(0);
|
||||
|
||||
// just skip op if input is empty
|
||||
if (input->isEmpty()) return Status::OK;
|
||||
|
||||
const int rank = input->rankOf();
|
||||
const int arg_size = block.getIArguments()->size();
|
||||
const LongType dimC = arg_size > 0 ? (INT_ARG(0) >= 0 ? INT_ARG(0) : INT_ARG(0) + rank) : rank - 1;
|
||||
|
||||
REQUIRE_TRUE(block.numT() > 0 || block.width() > 1, 0, "ADJUST_HUE: delta factor is required !");
|
||||
REQUIRE_TRUE(rank >= 3, 0, "ADJUST_HUE: op expects rank of input array to be >= 3, but got %i instead", rank);
|
||||
if (arg_size > 0) {
|
||||
REQUIRE_TRUE(dimC >= 0 && dimC < rank, 0, "Index of the Channel dimension out of range: %i not in [%i,%i) ",
|
||||
INT_ARG(0), -rank, rank);
|
||||
}
|
||||
REQUIRE_TRUE(input->sizeAt(dimC) == 3, 0,
|
||||
"ADJUST_HUE: operation expects image with 3 channels (R, G, B), but got %i instead",
|
||||
input->sizeAt(dimC));
|
||||
|
||||
NDArray* delta = nullptr;
|
||||
|
||||
if (block.width() > 1)
|
||||
delta = INPUT_VARIABLE(1);
|
||||
else {
|
||||
delta = new NDArray(output->dataType(), block.launchContext());
|
||||
#ifdef HAS_DOUBLE
|
||||
delta->p(0, static_cast<double>(T_ARG(0)));
|
||||
#elif defined(HAS_FLOAT32)
|
||||
delta->p(0, static_cast<float>(T_ARG(0)));
|
||||
#else
|
||||
#error "No floating-point type available for adjust_hue operation"
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef HAS_DOUBLE
|
||||
auto deltaVal = delta->e<double>(0);
|
||||
#elif defined(HAS_FLOAT32)
|
||||
auto deltaVal = delta->e<float>(0);
|
||||
#else
|
||||
#error "No floating-point type available for adjust_hue operation"
|
||||
#endif
|
||||
|
||||
REQUIRE_TRUE(-1. <= deltaVal && deltaVal <= 1., 0,
|
||||
"ADJUST_HUE: parameter delta must be within [-1, 1] interval, but got %f instead", delta);
|
||||
|
||||
helpers::adjustHue(block.launchContext(), input, delta, output, dimC);
|
||||
|
||||
if (block.width() == 1) delete delta;
|
||||
|
||||
return Status::OK;
|
||||
}
|
||||
|
||||
DECLARE_TYPES(adjust_hue) { getOpDescriptor()->setAllowedInputTypes(ANY)->setSameMode(true); }
|
||||
|
||||
} // namespace ops
|
||||
} // namespace sd
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,81 @@
|
||||
/* ******************************************************************************
|
||||
*
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Apache License, Version 2.0 which is available at
|
||||
* https://www.apache.org/licenses/LICENSE-2.0.
|
||||
*
|
||||
* See the NOTICE file distributed with this work for additional
|
||||
* information regarding copyright ownership.
|
||||
* 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.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
******************************************************************************/
|
||||
|
||||
//
|
||||
// @author raver119@gmail.com
|
||||
//
|
||||
|
||||
#include <system/op_boilerplate.h>
|
||||
#if NOT_EXCLUDED(OP_adjust_saturation)
|
||||
|
||||
#include <array/NDArrayFactory.h>
|
||||
#include <ops/declarable/headers/parity_ops.h>
|
||||
#include <ops/declarable/helpers/adjust_saturation.h>
|
||||
|
||||
namespace sd {
|
||||
namespace ops {
|
||||
|
||||
CONFIGURABLE_OP_IMPL(adjust_saturation, 1, 1, true, 0, 0) {
|
||||
auto input = INPUT_VARIABLE(0);
|
||||
auto output = OUTPUT_VARIABLE(0);
|
||||
|
||||
// just skip op if input is empty
|
||||
if (input->isEmpty()) return Status::OK;
|
||||
|
||||
const int rank = input->rankOf();
|
||||
const int arg_size = block.getIArguments()->size();
|
||||
const int dimC = arg_size > 0 ? (INT_ARG(0) >= 0 ? INT_ARG(0) : INT_ARG(0) + rank) : rank - 1;
|
||||
|
||||
REQUIRE_TRUE(rank >= 3, 0, "ADJUST_SATURATION: op expects rank of input array to be >= 3, but got %i instead", rank);
|
||||
if (arg_size > 0) {
|
||||
REQUIRE_TRUE(dimC >= 0 && dimC < rank, 0, "Index of the Channel dimension out of range: %i not in [%i,%i) ",
|
||||
INT_ARG(0), -rank, rank);
|
||||
}
|
||||
REQUIRE_TRUE(input->sizeAt(dimC) == 3, 0,
|
||||
"ADJUST_SATURATION: operation expects image with 3 channels (R, G, B), but got %i instead",
|
||||
input->sizeAt(dimC));
|
||||
REQUIRE_TRUE(block.numT() > 0 || block.width() > 1, 0, "ADJUST_SATURATION: scale factor is required !");
|
||||
|
||||
NDArray* factor = nullptr;
|
||||
|
||||
if (block.width() > 1)
|
||||
factor = INPUT_VARIABLE(1);
|
||||
else {
|
||||
factor = new NDArray(output->dataType(), block.launchContext());
|
||||
#ifdef HAS_DOUBLE
|
||||
factor->p(0, static_cast<double>(T_ARG(0)));
|
||||
#elif defined(HAS_FLOAT32)
|
||||
factor->p(0, static_cast<float>(T_ARG(0)));
|
||||
#else
|
||||
#error "No floating-point type available for adjust_saturation operation"
|
||||
#endif
|
||||
}
|
||||
|
||||
helpers::adjustSaturation(block.launchContext(), input, factor, output, dimC);
|
||||
|
||||
if (block.width() == 1) delete factor;
|
||||
|
||||
return Status::OK;
|
||||
}
|
||||
|
||||
DECLARE_TYPES(adjust_saturation) { getOpDescriptor()->setAllowedInputTypes(ANY)->setSameMode(true); }
|
||||
|
||||
} // namespace ops
|
||||
} // namespace sd
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,109 @@
|
||||
/* ******************************************************************************
|
||||
*
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Apache License, Version 2.0 which is available at
|
||||
* https://www.apache.org/licenses/LICENSE-2.0.
|
||||
*
|
||||
* See the NOTICE file distributed with this work for additional
|
||||
* information regarding copyright ownership.
|
||||
* 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.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
******************************************************************************/
|
||||
|
||||
//
|
||||
// @author sgazeos@gmail.com
|
||||
//
|
||||
|
||||
#include <system/op_boilerplate.h>
|
||||
#if NOT_EXCLUDED(OP_crop_and_resize)
|
||||
|
||||
#include <ops/declarable/CustomOperations.h>
|
||||
#include <ops/declarable/helpers/crop_and_resize.h>
|
||||
|
||||
namespace sd {
|
||||
namespace ops {
|
||||
CUSTOM_OP_IMPL(crop_and_resize, 4, 1, false, 0, 0) {
|
||||
auto image = INPUT_VARIABLE(0);
|
||||
auto boxes = INPUT_VARIABLE(1);
|
||||
auto boxIndexes = INPUT_VARIABLE(2);
|
||||
|
||||
auto output = OUTPUT_VARIABLE(0);
|
||||
int width;
|
||||
int height;
|
||||
int method = 0; // bilinear
|
||||
#ifdef HAS_DOUBLE
|
||||
double extrapolationVal = 0.;
|
||||
#elif defined(HAS_FLOAT32)
|
||||
float extrapolationVal = 0.0f;
|
||||
#else
|
||||
#error "No floating-point type available for crop_and_resize operation"
|
||||
#endif
|
||||
|
||||
auto newImageSize = INPUT_VARIABLE(3);
|
||||
REQUIRE_TRUE(output->dataType() == image->dataType(), 0,
|
||||
"crop_and_resize: Source images and output should have the same data type.");
|
||||
REQUIRE_TRUE(newImageSize->lengthOf() == 2, 0, "crop_and_resize: Resize params is a pair of values, not %i.",
|
||||
newImageSize->lengthOf());
|
||||
// REQUIRE_TRUE(block.numI() <= 1, 0, "crop_and_resize: Resize params already given by the second param. Int params
|
||||
// are expensive."); width = int(newImageSize->getScalar(0)); height = int(newImageSize->getScalar(1));
|
||||
if (block.numI() == 1) {
|
||||
method = INT_ARG(0);
|
||||
}
|
||||
|
||||
if (block.numT() == 1) {
|
||||
#ifdef HAS_DOUBLE
|
||||
extrapolationVal = static_cast<double>(T_ARG(0));
|
||||
#elif defined(HAS_FLOAT32)
|
||||
extrapolationVal = static_cast<float>(T_ARG(0));
|
||||
#else
|
||||
#error "No floating-point type available for crop_and_resize operation"
|
||||
#endif
|
||||
}
|
||||
|
||||
helpers::cropAndResizeFunctor(block.launchContext(), image, boxes, boxIndexes, newImageSize, method, extrapolationVal,
|
||||
output);
|
||||
return sd::Status::OK;
|
||||
}
|
||||
|
||||
DECLARE_SHAPE_FN(crop_and_resize) {
|
||||
auto in = inputShape->at(0);
|
||||
auto boxShape = inputShape->at(1);
|
||||
|
||||
sd::LongType outputShape[4];
|
||||
|
||||
int width;
|
||||
int height;
|
||||
auto newImageSize = INPUT_VARIABLE(3);
|
||||
REQUIRE_TRUE(newImageSize->lengthOf() == 2, 0, "crop_and_resize: Resize params is a pair of values, not %i.",
|
||||
newImageSize->lengthOf());
|
||||
// REQUIRE_TRUE(block.numI() <= 1, 0, "crop_and_resize: Resize params already given by the second param. Int params
|
||||
// are expensive.");
|
||||
width = newImageSize->e<int>(0);
|
||||
height = newImageSize->e<int>(1);
|
||||
|
||||
outputShape[0] = boxShape[1];
|
||||
outputShape[1] = width;
|
||||
outputShape[2] = height;
|
||||
outputShape[3] = in[4];
|
||||
auto desc = new ShapeDescriptor(ArrayOptions::dataType(in), shape::order(in), outputShape, 4);
|
||||
return SHAPELIST(ConstantShapeHelper::getInstance().createShapeInfo(desc));
|
||||
}
|
||||
|
||||
DECLARE_TYPES(crop_and_resize) {
|
||||
getOpDescriptor()
|
||||
->setAllowedInputTypes(0, {ALL_INTS, ALL_FLOATS})
|
||||
->setAllowedInputTypes(1, {ALL_INTS, ALL_FLOATS})
|
||||
->setAllowedInputTypes(2, {ALL_INTS})
|
||||
->setAllowedInputTypes(3, {ALL_INTS})
|
||||
->setAllowedOutputTypes({ALL_INTS, ALL_FLOATS}); // as TF
|
||||
}
|
||||
} // namespace ops
|
||||
} // namespace sd
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,74 @@
|
||||
/* ******************************************************************************
|
||||
*
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Apache License, Version 2.0 which is available at
|
||||
* https://www.apache.org/licenses/LICENSE-2.0.
|
||||
*
|
||||
* See the NOTICE file distributed with this work for additional
|
||||
* information regarding copyright ownership.
|
||||
* 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.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
******************************************************************************/
|
||||
|
||||
//
|
||||
// @author George A. Shulinok <sgazeos@gmail.com>
|
||||
//
|
||||
|
||||
#include <system/op_boilerplate.h>
|
||||
#if NOT_EXCLUDED(OP_draw_bounding_boxes)
|
||||
|
||||
#include <ops/declarable/headers/parity_ops.h>
|
||||
#include <ops/declarable/helpers/image_draw_bounding_boxes.h>
|
||||
namespace sd {
|
||||
namespace ops {
|
||||
OP_IMPL(draw_bounding_boxes, 3, 1, true) {
|
||||
auto images = INPUT_VARIABLE(0);
|
||||
auto boxes = INPUT_VARIABLE(1);
|
||||
|
||||
auto colors = (NDArray*)nullptr;
|
||||
if (block.width() > 2) // TF v.1.x ommits color set for boxes, and use color 1.0 for fill up
|
||||
colors = INPUT_VARIABLE(2); // but v.2.y require color set
|
||||
|
||||
auto output = OUTPUT_VARIABLE(0);
|
||||
REQUIRE_TRUE(images->dataType() == output->dataType(), 0,
|
||||
"draw_bounding_boxes: Input and Output types "
|
||||
"should be equals, but %d and %d occured.",
|
||||
(int)images->dataType(), (int)output->dataType());
|
||||
REQUIRE_TRUE(images->rankOf() == 4, 0, "draw_bounding_boxes: Images input should be 4D tensor, but %i occured.",
|
||||
images->rankOf());
|
||||
REQUIRE_TRUE(boxes->rankOf() == 3, 0, "draw_bounding_boxes: Boxes should be 3D tensor, but %i occured.",
|
||||
boxes->rankOf());
|
||||
if (colors) {
|
||||
REQUIRE_TRUE(colors->rankOf() == 2, 0, "draw_bounding_boxes: Color set should be 2D matrix, but %i occured.",
|
||||
colors->rankOf());
|
||||
REQUIRE_TRUE(colors->sizeAt(1) >= images->sizeAt(3), 0,
|
||||
"draw_bounding_boxes: Color set last dim "
|
||||
"should be not less than images depth, but "
|
||||
"%lld and %lld occured.",
|
||||
colors->sizeAt(1), images->sizeAt(3));
|
||||
}
|
||||
REQUIRE_TRUE(boxes->sizeAt(0) == images->sizeAt(0), 0,
|
||||
"draw_bounding_boxes: Batches for images and boxes "
|
||||
"should be the same, but %lld and %lld occured.",
|
||||
images->sizeAt(0), boxes->sizeAt(0));
|
||||
helpers::drawBoundingBoxesFunctor(block.launchContext(), images, boxes, colors, output);
|
||||
return Status::OK;
|
||||
}
|
||||
|
||||
DECLARE_TYPES(draw_bounding_boxes) {
|
||||
getOpDescriptor()
|
||||
->setAllowedInputTypes(0, {HALF, FLOAT32}) // TF allows HALF and FLOAT32 only
|
||||
->setAllowedInputTypes(1, {FLOAT32}) // as TF
|
||||
->setAllowedInputTypes(2, {FLOAT32}) // as TF
|
||||
->setAllowedOutputTypes({HALF, FLOAT32}); // TF allows HALF and FLOAT32 only
|
||||
}
|
||||
} // namespace ops
|
||||
} // namespace sd
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,96 @@
|
||||
/* ******************************************************************************
|
||||
*
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Apache License, Version 2.0 which is available at
|
||||
* https://www.apache.org/licenses/LICENSE-2.0.
|
||||
*
|
||||
* See the NOTICE file distributed with this work for additional
|
||||
* information regarding copyright ownership.
|
||||
* 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.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
******************************************************************************/
|
||||
|
||||
//
|
||||
// Created by GS <sgazeos@gmail.com> at 3/30/2018
|
||||
//
|
||||
|
||||
#include <ops/declarable/CustomOperations.h>
|
||||
#include <ops/declarable/helpers/extract_patches.h>
|
||||
#if NOT_EXCLUDED(OP_extract_image_patches)
|
||||
namespace sd {
|
||||
namespace ops {
|
||||
CUSTOM_OP_IMPL(extract_image_patches, 1, 1, false, 0, 7) {
|
||||
auto input = INPUT_VARIABLE(0);
|
||||
auto output = OUTPUT_VARIABLE(0);
|
||||
int ksizeRows = INT_ARG(0);
|
||||
int ksizeCols = INT_ARG(1);
|
||||
int kstrideRows = INT_ARG(2);
|
||||
int kstrideCols = INT_ARG(3);
|
||||
int krateRows = INT_ARG(4);
|
||||
int krateCols = INT_ARG(5);
|
||||
bool isSame = INT_ARG(6) != 0;
|
||||
|
||||
REQUIRE_TRUE(input->rankOf() == 4, 0, "extract_image_patches: The rank of input array should be 4, but %i is given",
|
||||
input->rankOf());
|
||||
|
||||
if (output->isSameShape(input))
|
||||
output->assign(input);
|
||||
else {
|
||||
output->nullify();
|
||||
helpers::extractPatches(block.launchContext(), input, output, ksizeRows, ksizeCols, kstrideRows, kstrideCols,
|
||||
krateRows, krateCols, isSame);
|
||||
}
|
||||
return Status::OK;
|
||||
}
|
||||
|
||||
DECLARE_TYPES(extract_image_patches) { getOpDescriptor()->setAllowedInputTypes(ANY)->setSameMode(true); }
|
||||
|
||||
DECLARE_SHAPE_FN(extract_image_patches) {
|
||||
auto in = inputShape->at(0);
|
||||
int outRank = shape::rank(in);
|
||||
LongType *outputShape = nullptr;
|
||||
|
||||
int ksizeRowsEffective = INT_ARG(0) + (INT_ARG(0) - 1) * (INT_ARG(4) - 1);
|
||||
int ksizeColsEffective = INT_ARG(1) + (INT_ARG(1) - 1) * (INT_ARG(5) - 1);
|
||||
|
||||
auto batchSizeDim = shape::sizeAt(in, static_cast<LongType>(0));
|
||||
auto inputRowsDim = shape::sizeAt(in, static_cast<LongType>(1));
|
||||
auto inputColsDim = shape::sizeAt(in, static_cast<LongType>(2));
|
||||
auto outputDepthDim = shape::sizeAt(in, static_cast<LongType>(3)) * INT_ARG(0) * INT_ARG(1); // last dim * ksizeRows * ksizeCols
|
||||
|
||||
auto inputRowSize = inputRowsDim;
|
||||
auto inputColSize = inputColsDim;
|
||||
LongType outRowSize;
|
||||
LongType outColSize;
|
||||
if (INT_ARG(6) == 0) {
|
||||
// Padding is "VALID":
|
||||
outRowSize = (inputRowSize - ksizeRowsEffective + INT_ARG(2)) / INT_ARG(2);
|
||||
outColSize = (inputColSize - ksizeColsEffective + INT_ARG(3)) / INT_ARG(3);
|
||||
} else {
|
||||
// Padding is "SAME":
|
||||
outRowSize = (inputRowSize + INT_ARG(2) - 1) / INT_ARG(2);
|
||||
outColSize = (inputColSize + INT_ARG(3) - 1) / INT_ARG(3);
|
||||
}
|
||||
|
||||
ALLOCATE(outputShape, block.getWorkspace(), shape::shapeInfoLength(outRank), sd::LongType);
|
||||
|
||||
outputShape[0] = outRank;
|
||||
outputShape[1] = batchSizeDim;
|
||||
outputShape[2] = outRowSize;
|
||||
outputShape[3] = outColSize;
|
||||
outputShape[4] = outputDepthDim;
|
||||
|
||||
ShapeUtils::updateStridesAndType(outputShape, in, shape::order(in));
|
||||
|
||||
return SHAPELIST(CONSTANT(outputShape));
|
||||
}
|
||||
} // namespace ops
|
||||
} // namespace sd
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,59 @@
|
||||
/* ******************************************************************************
|
||||
*
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Apache License, Version 2.0 which is available at
|
||||
* https://www.apache.org/licenses/LICENSE-2.0.
|
||||
*
|
||||
* See the NOTICE file distributed with this work for additional
|
||||
* information regarding copyright ownership.
|
||||
* 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.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
******************************************************************************/
|
||||
|
||||
//
|
||||
// @author AbdelRauf (rauf@konduit.ai)
|
||||
//
|
||||
|
||||
#include <execution/Threads.h>
|
||||
#include <helpers/ConstantTadHelper.h>
|
||||
#include <ops/declarable/CustomOperations.h>
|
||||
#include <ops/declarable/headers/images.h>
|
||||
|
||||
#if NOT_EXCLUDED(OP_hsv_to_rgb)
|
||||
namespace sd {
|
||||
namespace ops {
|
||||
|
||||
CONFIGURABLE_OP_IMPL(hsv_to_rgb, 1, 1, true, 0, 0) {
|
||||
auto input = INPUT_VARIABLE(0);
|
||||
auto output = OUTPUT_VARIABLE(0);
|
||||
|
||||
if (input->isEmpty()) return Status::OK;
|
||||
|
||||
const int rank = input->rankOf();
|
||||
const int argSize = block.getIArguments()->size();
|
||||
const int dimC = argSize > 0 ? (INT_ARG(0) >= 0 ? INT_ARG(0) : INT_ARG(0) + rank) : rank - 1;
|
||||
|
||||
REQUIRE_TRUE(rank >= 1, 0, "HSVtoRGB: Fails to meet the rank requirement: %i >= 1 ", rank);
|
||||
if (argSize > 0) {
|
||||
REQUIRE_TRUE(dimC >= 0 && dimC < rank, 0, "Index of the Channel dimension out of range: %i not in [%i,%i) ",
|
||||
INT_ARG(0), -rank, rank);
|
||||
}
|
||||
REQUIRE_TRUE(input->sizeAt(dimC) == 3, 0, "HSVtoRGB: operation expects 3 channels (H, S, V), but got %i instead",
|
||||
input->sizeAt(dimC));
|
||||
|
||||
helpers::transformHsvRgb(block.launchContext(), input, output, dimC);
|
||||
|
||||
return Status::OK;
|
||||
}
|
||||
|
||||
DECLARE_TYPES(hsv_to_rgb) { getOpDescriptor()->setAllowedInputTypes({ALL_FLOATS})->setSameMode(true); }
|
||||
|
||||
} // namespace ops
|
||||
} // namespace sd
|
||||
#endif
|
||||
@@ -0,0 +1,158 @@
|
||||
/* ******************************************************************************
|
||||
*
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Apache License, Version 2.0 which is available at
|
||||
* https://www.apache.org/licenses/LICENSE-2.0.
|
||||
*
|
||||
* See the NOTICE file distributed with this work for additional
|
||||
* information regarding copyright ownership.
|
||||
* 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.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
******************************************************************************/
|
||||
|
||||
//
|
||||
// @author sgazeos@gmail.com
|
||||
//
|
||||
|
||||
#include <system/op_boilerplate.h>
|
||||
#if NOT_EXCLUDED(OP_image_resize)
|
||||
#include <ops/declarable/CustomOperations.h>
|
||||
#include <ops/declarable/helpers/image_resize.h>
|
||||
|
||||
namespace sd {
|
||||
namespace ops {
|
||||
CUSTOM_OP_IMPL(image_resize, 2, 1, false, -2, -2) {
|
||||
auto image = INPUT_VARIABLE(0);
|
||||
auto size = INPUT_VARIABLE(1);
|
||||
|
||||
auto output = OUTPUT_VARIABLE(0);
|
||||
|
||||
int width;
|
||||
int height;
|
||||
bool antialias = false;
|
||||
REQUIRE_TRUE(size->lengthOf() == 2, 0, "image_resize: Resize params is a pair of values, not %lld.",
|
||||
size->lengthOf());
|
||||
width = size->e<int>(1);
|
||||
height = size->e<int>(0);
|
||||
if (block.numB() >= 2) {
|
||||
antialias = B_ARG(1);
|
||||
}
|
||||
bool exclude_outside = true;
|
||||
double bicubicCoefficient = helpers::KeysCubicKernelFunc<double>::KEYS_CUBIC_COEF;
|
||||
auto method = helpers::ImageResizeMethods::kResizeBilinear;
|
||||
helpers::CoordinateTransformationMode coorMode = helpers::CoordinateTransformationMode::HALF_PIXEL;
|
||||
|
||||
if (block.numB() >= 3) {
|
||||
exclude_outside = B_ARG(2);
|
||||
}
|
||||
if (block.numT() > 0) {
|
||||
bicubicCoefficient = T_ARG(0);
|
||||
}
|
||||
if (block.numI() >= 1) {
|
||||
method = (helpers::ImageResizeMethods)INT_ARG(0);
|
||||
}
|
||||
if (block.numI() >= 2) {
|
||||
coorMode = static_cast<helpers::CoordinateTransformationMode>(INT_ARG(1));
|
||||
} else if (method == helpers::ImageResizeMethods::kResizeNearest) {
|
||||
// retain old behavour
|
||||
coorMode = helpers::CoordinateTransformationMode::HALF_PIXEL_NN;
|
||||
}
|
||||
helpers::NearestMode nearestMode = helpers::NearestMode::FLOOR;
|
||||
if (method == helpers::ImageResizeMethods::kResizeNearest && block.numI() == 3) {
|
||||
nearestMode = static_cast<helpers::NearestMode>(INT_ARG(2));
|
||||
REQUIRE_TRUE(nearestMode >= helpers::NearestMode::FLOOR && nearestMode <= helpers::NearestMode::CEIL, 0,
|
||||
"image_resize: nearest Mode should be between %i and %i, but %i was given.",
|
||||
(int)helpers::NearestMode::FLOOR, (int)helpers::NearestMode::CEIL, (int)nearestMode);
|
||||
}
|
||||
REQUIRE_TRUE(method == helpers::ImageResizeMethods::kResizeNearest || output->dataType() == DataType::FLOAT32, 0,
|
||||
"image_resize: Output data type should be FLOAT32 for this method %i", (int)method);
|
||||
REQUIRE_TRUE(
|
||||
method >= helpers::ImageResizeMethods::kResizeFirst && method <= helpers::ImageResizeMethods::kResizeLast, 0,
|
||||
"image_resize: Resize method should be between %i and %i, but %i was given.",
|
||||
(int)helpers::ImageResizeMethods::kResizeFirst, (int)helpers::ImageResizeMethods::kResizeLast, (int)method);
|
||||
auto inRank = image->rankOf();
|
||||
REQUIRE_TRUE(inRank >= 3 && inRank <= 4, 0, "image_resize: Input rank should be 4 or 3, but %i given.",
|
||||
image->rankOf());
|
||||
std::vector<sd::LongType> imageShape1 = {image->sizeAt(0), image->sizeAt(1), image->sizeAt(2),image->sizeAt(3)};
|
||||
std::vector<sd::LongType> imageShape2 = {1, image->sizeAt(0), image->sizeAt(1), image->sizeAt(2)};
|
||||
auto source =
|
||||
inRank == 4
|
||||
? image->reshape(image->ordering(), imageShape1)
|
||||
: image->reshape(image->ordering(),imageShape2);
|
||||
|
||||
std::vector<sd::LongType> outputShape1 = {output->sizeAt(0), output->sizeAt(1), output->sizeAt(2),output->sizeAt(3)};
|
||||
std::vector<sd::LongType> outputShape2 = {1, output->sizeAt(0), output->sizeAt(1), output->sizeAt(2)};
|
||||
|
||||
auto target =
|
||||
inRank == 4
|
||||
? output->reshape(output->ordering(),
|
||||
outputShape1, false)
|
||||
: output->reshape(output->ordering(), outputShape2, false);
|
||||
|
||||
// inform the user about the current state of the implementation
|
||||
if (antialias && method != helpers::ImageResizeMethods::kResizeNearest) {
|
||||
REQUIRE_TRUE(coorMode == helpers::CoordinateTransformationMode::HALF_PIXEL && exclude_outside, 0,
|
||||
"antialiasing is effective only with HALF_PIXEL and exclude_outside being set true");
|
||||
}
|
||||
//
|
||||
if ((method != helpers::ImageResizeMethods::kResizeBicubic &&
|
||||
method != helpers::ImageResizeMethods::kResizeNearest)) {
|
||||
REQUIRE_TRUE(coorMode == helpers::CoordinateTransformationMode::HALF_PIXEL && exclude_outside, 0,
|
||||
"this method supports only HALF_PIXEL and exclude_outside being set true");
|
||||
}
|
||||
|
||||
auto ret = resizeFunctor(block.launchContext(), image, width, height, method, coorMode, exclude_outside,
|
||||
nearestMode, bicubicCoefficient, antialias, output);
|
||||
delete target;
|
||||
return ret;
|
||||
}
|
||||
|
||||
DECLARE_SHAPE_FN(image_resize) {
|
||||
auto in = inputShape->at(0);
|
||||
|
||||
LongType* outputShape;
|
||||
auto method = helpers::ImageResizeMethods::kResizeBilinear;
|
||||
if (block.numI() >= 1) {
|
||||
method = (helpers::ImageResizeMethods)INT_ARG(0);
|
||||
}
|
||||
|
||||
int width;
|
||||
int height;
|
||||
double ratio = shape::sizeAt(in, static_cast<LongType>(1)) / (0.0 + shape::sizeAt(in, static_cast<LongType>(2)));
|
||||
auto newImageSize = INPUT_VARIABLE(1);
|
||||
REQUIRE_TRUE(newImageSize->lengthOf() == 2, 0, "resize_bilinear: Resize params is a pair of values, not %i.",
|
||||
newImageSize->lengthOf());
|
||||
|
||||
width = newImageSize->e<int>(1);
|
||||
height = newImageSize->e<int>(0);
|
||||
if (block.numB() > 0) {
|
||||
if (B_ARG(0)) {
|
||||
width = math::sd_ceil<double, int>(height / ratio);
|
||||
}
|
||||
}
|
||||
auto dtype = FLOAT32;
|
||||
if (method == helpers::ImageResizeMethods::kResizeNearest) dtype = ArrayOptions::dataType(in);
|
||||
auto shape = ConstantShapeHelper::getInstance().createShapeInfo(
|
||||
dtype, 'c',
|
||||
shape::rank(in) == 4 ? std::vector<LongType>{in[1], height, width, in[4]}
|
||||
: std::vector<LongType>{height, width, in[4]});
|
||||
|
||||
return SHAPELIST(shape);
|
||||
}
|
||||
DECLARE_TYPES(image_resize) {
|
||||
getOpDescriptor()
|
||||
->setAllowedInputTypes(0, {ALL_INTS, ALL_FLOATS})
|
||||
->setAllowedInputTypes(1, {ALL_INTS})
|
||||
->setAllowedOutputTypes({ALL_FLOATS, ALL_INTS});
|
||||
}
|
||||
|
||||
} // namespace ops
|
||||
} // namespace sd
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,143 @@
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* *
|
||||
* *
|
||||
* * This program and the accompanying materials are made available under the
|
||||
* * terms of the Apache License, Version 2.0 which is available at
|
||||
* * https://www.apache.org/licenses/LICENSE-2.0.
|
||||
* *
|
||||
* * See the NOTICE file distributed with this work for additional
|
||||
* * information regarding copyright ownership.
|
||||
* * 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.
|
||||
* *
|
||||
* * SPDX-License-Identifier: Apache-2.0
|
||||
* *****************************************************************************
|
||||
*/
|
||||
|
||||
//
|
||||
// @author sgazeos@gmail.com
|
||||
//
|
||||
|
||||
#include <system/op_boilerplate.h>
|
||||
#if NOT_EXCLUDED(OP_resize_area)
|
||||
|
||||
#include <ops/declarable/CustomOperations.h>
|
||||
#include <ops/declarable/helpers/image_resize.h>
|
||||
|
||||
namespace sd {
|
||||
namespace ops {
|
||||
CUSTOM_OP_IMPL(resize_area, 1, 1, false, 0, -2) {
|
||||
auto image = INPUT_VARIABLE(0);
|
||||
int width;
|
||||
int height;
|
||||
|
||||
if (block.width() == 2) {
|
||||
auto size = INPUT_VARIABLE(1); // integer vector with shape {2} and content (new_height, new_width)
|
||||
REQUIRE_TRUE(size->rankOf() == 1, size->lengthOf() == 2, 0,
|
||||
"resize_area: Resize params is a pair of values, not %i.", size->lengthOf());
|
||||
size->syncToHost();
|
||||
width = size->e<int>(1);
|
||||
height = size->e<int>(0);
|
||||
} else {
|
||||
REQUIRE_TRUE(block.numI() == 2, 0,
|
||||
"resize_area: Resize params already given by the second param. Int params are expensive.");
|
||||
width = INT_ARG(1);
|
||||
height = INT_ARG(0);
|
||||
}
|
||||
|
||||
auto output = OUTPUT_VARIABLE(0);
|
||||
if (output->isEmpty()) return Status::OK;
|
||||
auto inRank = image->rankOf();
|
||||
|
||||
REQUIRE_TRUE(inRank == 3 || inRank == 4, 0, "resize_area: Source tensor should have rank 4, but %i given.", inRank);
|
||||
REQUIRE_TRUE(output->rankOf() == inRank, 0,
|
||||
"resize_area: Source tensor and output should have the same rank, but %i and %i given.", inRank,
|
||||
output->rankOf());
|
||||
REQUIRE_TRUE(width > 0, 0, "resize_area: picture width should be positive 32 bit integer, but %i given", width);
|
||||
REQUIRE_TRUE(height > 0, 0, "resize_area: picture height should be positive 32 bit integer, but %i given", height);
|
||||
REQUIRE_TRUE(image->lengthOf() > 0, 0, "resize_area: Only non-zero images allowed to processing.");
|
||||
|
||||
auto alignCorners = false;
|
||||
if (block.numB() > 0) {
|
||||
alignCorners = B_ARG(0);
|
||||
}
|
||||
std::vector<sd::LongType> imageShape1 = {image->sizeAt(0), image->sizeAt(1), image->sizeAt(2),image->sizeAt(3)};
|
||||
std::vector<sd::LongType> imageShape2 = {1, image->sizeAt(0), image->sizeAt(1), image->sizeAt(2)};
|
||||
|
||||
auto source =
|
||||
inRank == 4
|
||||
? image->reshape(image->ordering(), imageShape1)
|
||||
: image->reshape(image->ordering(), imageShape2);
|
||||
|
||||
|
||||
std::vector<sd::LongType> outputShape1 = {output->sizeAt(0), output->sizeAt(1), output->sizeAt(2),output->sizeAt(3)};
|
||||
std::vector<sd::LongType> outputShape2 = {1, output->sizeAt(0), output->sizeAt(1), output->sizeAt(2)};
|
||||
|
||||
auto target =
|
||||
inRank == 4
|
||||
? output->reshape(output->ordering(),
|
||||
outputShape1, false)
|
||||
: output->reshape(output->ordering(), outputShape2, false);
|
||||
|
||||
auto ret = helpers::resizeAreaFunctor(block.launchContext(), source, width, height, alignCorners, target);
|
||||
delete source;
|
||||
delete target;
|
||||
return ret;
|
||||
}
|
||||
|
||||
DECLARE_SHAPE_FN(resize_area) {
|
||||
auto shapeList = SHAPELIST();
|
||||
auto in = inputShape->at(0);
|
||||
|
||||
LongType* outputShape;
|
||||
auto inRank = shape::rank(in);
|
||||
int width;
|
||||
int height;
|
||||
if (block.width() == 2) {
|
||||
auto newImageSize = INPUT_VARIABLE(1);
|
||||
REQUIRE_TRUE(newImageSize->lengthOf() == 2, 0, "resize_area: Resize params is a pair of values, not %i.",
|
||||
newImageSize->lengthOf());
|
||||
REQUIRE_TRUE(block.numI() <= 1, 0,
|
||||
"resize_area: Resize params already given by the second param. Int params are expensive.");
|
||||
width = newImageSize->e<int>(1);
|
||||
height = newImageSize->e<int>(0);
|
||||
} else {
|
||||
REQUIRE_TRUE(block.numI() == 2, 0, "resize_area: Resize params ommited as pair ints nor int tensor.");
|
||||
width = INT_ARG(1);
|
||||
height = INT_ARG(0);
|
||||
}
|
||||
|
||||
REQUIRE_TRUE(inRank == 4 || inRank == 3, 0, "resize_area: Source tensor should have rank 4, but %i given.", inRank);
|
||||
|
||||
ALLOCATE(outputShape, block.getWorkspace(), shape::shapeInfoLength(inRank), sd::LongType);
|
||||
outputShape[0] = inRank;
|
||||
if (inRank == 4) {
|
||||
outputShape[1] = in[1];
|
||||
outputShape[2] = height;
|
||||
outputShape[3] = width;
|
||||
outputShape[4] = in[4];
|
||||
} else {
|
||||
outputShape[1] = height;
|
||||
outputShape[2] = width;
|
||||
outputShape[3] = in[3];
|
||||
}
|
||||
ShapeUtils::updateStridesAndType(outputShape, FLOAT32, shape::order(in));
|
||||
|
||||
shapeList->push_back(CONSTANT(outputShape));
|
||||
return shapeList;
|
||||
}
|
||||
DECLARE_TYPES(resize_area) {
|
||||
getOpDescriptor()
|
||||
->setAllowedInputTypes(0, {ALL_FLOATS, ALL_INTS})
|
||||
->setAllowedInputTypes(1, INT32)
|
||||
->setAllowedOutputTypes({FLOAT32});
|
||||
}
|
||||
|
||||
} // namespace ops
|
||||
} // namespace sd
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,150 @@
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* *
|
||||
* *
|
||||
* * This program and the accompanying materials are made available under the
|
||||
* * terms of the Apache License, Version 2.0 which is available at
|
||||
* * https://www.apache.org/licenses/LICENSE-2.0.
|
||||
* *
|
||||
* * See the NOTICE file distributed with this work for additional
|
||||
* * information regarding copyright ownership.
|
||||
* * 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.
|
||||
* *
|
||||
* * SPDX-License-Identifier: Apache-2.0
|
||||
* *****************************************************************************
|
||||
*/
|
||||
|
||||
//
|
||||
// @author sgazeos@gmail.com
|
||||
//
|
||||
|
||||
#include <system/op_boilerplate.h>
|
||||
#if NOT_EXCLUDED(OP_resize_bicubic)
|
||||
|
||||
#include <ops/declarable/CustomOperations.h>
|
||||
#include <ops/declarable/helpers/image_resize.h>
|
||||
|
||||
namespace sd {
|
||||
namespace ops {
|
||||
CUSTOM_OP_IMPL(resize_bicubic, 2, 1, false, 0, 0) {
|
||||
auto image = INPUT_VARIABLE(0);
|
||||
auto size = INPUT_VARIABLE(1); // integer vector with shape {2} and content (new_height, new_width)
|
||||
size->syncToHost();
|
||||
auto output = OUTPUT_VARIABLE(0);
|
||||
int width;
|
||||
int height;
|
||||
auto inRank = image->rankOf();
|
||||
if (output->isEmpty()) return Status::OK;
|
||||
|
||||
REQUIRE_TRUE(inRank == 3 || inRank == 4, 0, "resize_bicubic: Source tensor should have rank 4, but %i given.",
|
||||
inRank);
|
||||
REQUIRE_TRUE(output->rankOf() == inRank, 0,
|
||||
"resize_bicubic: Source tensor and output should have the same rank, but %i and %i given.", inRank,
|
||||
output->rankOf());
|
||||
REQUIRE_TRUE(size->rankOf() == 1, size->lengthOf() == 2, 0,
|
||||
"resize_bicubic: Resize params is a pair of values, not %i.", size->lengthOf());
|
||||
REQUIRE_TRUE(block.numI() <= 1, 0,
|
||||
"resize_bicubic: Resize params already given by the second param. Int params are expensive.");
|
||||
width = size->e<int>(1);
|
||||
height = size->e<int>(0);
|
||||
REQUIRE_TRUE(width > 0, 0, "resize_bicubic: picture width should be positive 32 bit integer, but %i given", width);
|
||||
REQUIRE_TRUE(height > 0, 0, "resize_bicubic: picture height should be positive 32 bit integer, but %i given", height);
|
||||
// REQUIRE_TRUE(image->sizeAt(1) > 3 && image->sizeAt(2) > 3, 0, "resize_cubic: To use bicubic algorithm need at least
|
||||
// 16 pixels as source.");
|
||||
REQUIRE_TRUE(width > 3 && height > 3, 0,
|
||||
"resize_bicubic: To use bicubic algorithm need at least 16 pixels as target.");
|
||||
REQUIRE_TRUE(image->lengthOf() > 0, 0, "resize_bicubic: Only non-zero images allowed to processing.");
|
||||
// auto method = 1; //kResizeBilinear;
|
||||
// if (block.numI() == 1) {
|
||||
// method = INT_ARG(0);
|
||||
// }
|
||||
auto alignCorners = false;
|
||||
auto halfPixelAlign = false;
|
||||
if (block.numB() > 0) {
|
||||
alignCorners = block.getBArguments()->at(0);
|
||||
if (block.numB() > 1) halfPixelAlign = block.getBArguments()->at(1);
|
||||
}
|
||||
REQUIRE_TRUE(!halfPixelAlign || (halfPixelAlign && !alignCorners), 0,
|
||||
"resize_bicubic: `half_pixel_centers' should be false or true only when `align_corners' is false");
|
||||
std::vector<sd::LongType> imageShape1 = {image->sizeAt(0), image->sizeAt(1), image->sizeAt(2),image->sizeAt(3)};
|
||||
std::vector<sd::LongType> imageShape2 = {1, image->sizeAt(0), image->sizeAt(1), image->sizeAt(2)};
|
||||
|
||||
auto source =
|
||||
inRank == 4
|
||||
? image->reshape(image->ordering(), imageShape1)
|
||||
: image->reshape(image->ordering(), imageShape2);
|
||||
|
||||
|
||||
std::vector<sd::LongType> outputShape1 = {output->sizeAt(0), output->sizeAt(1), output->sizeAt(2),output->sizeAt(3)};
|
||||
std::vector<sd::LongType> outputShape2 = {1, output->sizeAt(0), output->sizeAt(1), output->sizeAt(2)};
|
||||
|
||||
auto target =
|
||||
inRank == 4
|
||||
? output->reshape(output->ordering(),
|
||||
outputShape1, false)
|
||||
: output->reshape(output->ordering(), outputShape2, false);
|
||||
|
||||
// retain old behaviour
|
||||
helpers::CoordinateTransformationMode coorMode = halfPixelAlign ? helpers::CoordinateTransformationMode::HALF_PIXEL
|
||||
: helpers::CoordinateTransformationMode::ASYMMETRIC;
|
||||
bool exclude_outside = halfPixelAlign;
|
||||
double coef = halfPixelAlign ? helpers::KeysCubicKernelFunc<double>::KEYS_CUBIC_COEF
|
||||
: helpers::KeysCubicKernelFunc<double>::ORDINARY_COEF;
|
||||
auto ret = resizeBicubicFunctorA(block.launchContext(), source, width, height, alignCorners, coorMode,
|
||||
exclude_outside, coef, target);
|
||||
delete source;
|
||||
delete target;
|
||||
return ret;
|
||||
}
|
||||
|
||||
DECLARE_SHAPE_FN(resize_bicubic) {
|
||||
auto shapeList = SHAPELIST();
|
||||
auto in = inputShape->at(0);
|
||||
|
||||
LongType* outputShape;
|
||||
auto inRank = shape::rank(in);
|
||||
int width;
|
||||
int height;
|
||||
auto newImageSize = INPUT_VARIABLE(1);
|
||||
REQUIRE_TRUE(newImageSize->lengthOf() == 2, 0, "resize_bicubic: Resize params is a pair of values, not %i.",
|
||||
newImageSize->lengthOf());
|
||||
REQUIRE_TRUE(block.numI() <= 1, 0,
|
||||
"resize_bicubic: Resize params already given by the second param. Int params are expensive.");
|
||||
width = newImageSize->e<int>(0);
|
||||
height = newImageSize->e<int>(1);
|
||||
|
||||
REQUIRE_TRUE(inRank == 4 || inRank == 3, 0, "resize_bicubic: Source tensor should have rank 4, but %i given.",
|
||||
inRank);
|
||||
|
||||
ALLOCATE(outputShape, block.getWorkspace(), shape::shapeInfoLength(inRank), sd::LongType);
|
||||
outputShape[0] = inRank;
|
||||
if (inRank == 4) {
|
||||
outputShape[1] = in[1];
|
||||
outputShape[2] = width;
|
||||
outputShape[3] = height;
|
||||
outputShape[4] = in[4];
|
||||
} else {
|
||||
outputShape[1] = width;
|
||||
outputShape[2] = height;
|
||||
outputShape[3] = in[3];
|
||||
}
|
||||
ShapeUtils::updateStridesAndType(outputShape, FLOAT32, shape::order(in));
|
||||
|
||||
shapeList->push_back(CONSTANT(outputShape));
|
||||
return shapeList;
|
||||
}
|
||||
DECLARE_TYPES(resize_bicubic) {
|
||||
getOpDescriptor()
|
||||
->setAllowedInputTypes(0, {ALL_FLOATS, ALL_INTS})
|
||||
->setAllowedInputTypes(1, INT32)
|
||||
->setAllowedOutputTypes({FLOAT32, DOUBLE});
|
||||
}
|
||||
|
||||
} // namespace ops
|
||||
} // namespace sd
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,154 @@
|
||||
/* ******************************************************************************
|
||||
*
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Apache License, Version 2.0 which is available at
|
||||
* https://www.apache.org/licenses/LICENSE-2.0.
|
||||
*
|
||||
* See the NOTICE file distributed with this work for additional
|
||||
* information regarding copyright ownership.
|
||||
* 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.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
******************************************************************************/
|
||||
|
||||
//
|
||||
// @author sgazeos@gmail.com
|
||||
//
|
||||
|
||||
#include <system/op_boilerplate.h>
|
||||
#if NOT_EXCLUDED(OP_resize_images)
|
||||
|
||||
#include <ops/declarable/CustomOperations.h>
|
||||
#include <ops/declarable/helpers/image_resize.h>
|
||||
|
||||
namespace sd {
|
||||
namespace ops {
|
||||
CUSTOM_OP_IMPL(resize_images, 1, 1, false, 0, 0) {
|
||||
auto image = INPUT_VARIABLE(0);
|
||||
|
||||
auto output = OUTPUT_VARIABLE(0);
|
||||
int width = output->sizeAt(2);
|
||||
int height = output->sizeAt(1);
|
||||
int method = helpers::ImageResizeMethods::kResizeBilinear;
|
||||
if (block.width() > 1) {
|
||||
auto size = INPUT_VARIABLE(1);
|
||||
REQUIRE_TRUE(size->lengthOf() == 2, 0, "resize_images: Resize params is a pair of values, not %lld.",
|
||||
size->lengthOf());
|
||||
// width = size->e<int>(1);
|
||||
// height = size->e<int>(0);
|
||||
if (block.width() > 2) {
|
||||
auto methodT = INPUT_VARIABLE(2);
|
||||
|
||||
REQUIRE_TRUE(methodT->isZ() && methodT->isScalar(), 0,
|
||||
"resize_images: Method tensor should be integer scalar, but rank of %i tensor given.",
|
||||
methodT->rankOf());
|
||||
method = methodT->e<int>(0);
|
||||
} else if (block.numI() == 1) {
|
||||
method = I_ARG(0);
|
||||
}
|
||||
} else {
|
||||
REQUIRE_TRUE(block.numI() > 1 && block.numI() < 4, 0, "resize_images: Method and size should be given properly.");
|
||||
if (block.numI() == 3) { // full stack of args
|
||||
// height = I_ARG(0);
|
||||
// width = I_ARG(1);
|
||||
method = I_ARG(2);
|
||||
} else if (block.numI() == 2) {
|
||||
// height = I_ARG(0);
|
||||
// width = I_ARG(1);
|
||||
}
|
||||
}
|
||||
bool alignCorners = false;
|
||||
if (block.numB()) {
|
||||
alignCorners = B_ARG(0);
|
||||
}
|
||||
REQUIRE_TRUE(
|
||||
method >= helpers::ImageResizeMethods::kResizeFirst && method <= helpers::ImageResizeMethods::kResizeOldLast, 0,
|
||||
"resize_images: Resize method should be between %i and %i, but %i was given.",
|
||||
(int)helpers::ImageResizeMethods::kResizeFirst, (int)helpers::ImageResizeMethods::kResizeOldLast, (int)method);
|
||||
REQUIRE_TRUE(method == helpers::ImageResizeMethods::kResizeNearest || output->dataType() == DataType::FLOAT32, 0,
|
||||
"image_resize: Output data type should be FLOAT32 for this method %i", (int)method);
|
||||
|
||||
auto inRank = image->rankOf();
|
||||
REQUIRE_TRUE(inRank >= 3 && inRank <= 4, 0, "image_resize: Input rank should be 4 or 3, but %i given.", inRank);
|
||||
std::vector<sd::LongType> imageShape1 = {image->sizeAt(0), image->sizeAt(1), image->sizeAt(2),image->sizeAt(3)};
|
||||
std::vector<sd::LongType> imageShape2 = {1, image->sizeAt(0), image->sizeAt(1), image->sizeAt(2)};
|
||||
|
||||
auto source =
|
||||
inRank == 4
|
||||
? image->reshape(image->ordering(), imageShape1)
|
||||
: image->reshape(image->ordering(), imageShape2);
|
||||
|
||||
|
||||
|
||||
std::vector<sd::LongType> outputShape1 = {output->sizeAt(0), output->sizeAt(1), output->sizeAt(2),output->sizeAt(3)};
|
||||
std::vector<sd::LongType> outputShape2 = {1, output->sizeAt(0), output->sizeAt(1), output->sizeAt(2)};
|
||||
|
||||
auto target =
|
||||
inRank == 4
|
||||
? output->reshape(output->ordering(),
|
||||
outputShape1, false)
|
||||
: output->reshape(output->ordering(), outputShape2, false);
|
||||
|
||||
auto ret = resizeImagesFunctor(block.launchContext(), source, width, height,
|
||||
(helpers::ImageResizeMethods)method, alignCorners, target);
|
||||
delete source;
|
||||
delete target;
|
||||
return ret;
|
||||
}
|
||||
|
||||
DECLARE_SHAPE_FN(resize_images) {
|
||||
auto in = inputShape->at(0);
|
||||
|
||||
LongType* outputShape;
|
||||
|
||||
int width;
|
||||
int height;
|
||||
if (block.width() > 1) {
|
||||
auto size = INPUT_VARIABLE(1);
|
||||
REQUIRE_TRUE(size->lengthOf() == 2, 0, "resize_images: Resize params is a pair of values, not %lld.",
|
||||
size->lengthOf());
|
||||
width = size->e<int>(1);
|
||||
height = size->e<int>(0);
|
||||
} else {
|
||||
REQUIRE_TRUE(block.numI() > 1 && block.numI() < 4, 0, "resize_images: Method and size should be given properly.");
|
||||
if (block.numI() == 3) { // full stack of args
|
||||
height = I_ARG(0);
|
||||
width = I_ARG(1);
|
||||
} else if (block.numI() == 2) {
|
||||
height = I_ARG(0);
|
||||
width = I_ARG(1);
|
||||
}
|
||||
}
|
||||
|
||||
double ratio = shape::sizeAt(in, static_cast<LongType>(1)) / (0.0 + shape::sizeAt(in, static_cast<LongType>(2)));
|
||||
if (block.numB() > 1) {
|
||||
if (B_ARG(1)) {
|
||||
width = math::sd_ceil<double, int>(height / ratio);
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<LongType> shape;
|
||||
if (shape::rank(in) == 4)
|
||||
shape = {in[1], height, width, in[4]};
|
||||
else if (shape::rank(in) == 3)
|
||||
shape = {height, width, in[3]};
|
||||
|
||||
auto outShape = ConstantShapeHelper::getInstance().createShapeInfo(FLOAT32, shape::order(in), shape);
|
||||
return SHAPELIST(outShape);
|
||||
}
|
||||
DECLARE_TYPES(resize_images) {
|
||||
getOpDescriptor()
|
||||
->setAllowedInputTypes(0, {ALL_FLOATS, ALL_INTS})
|
||||
->setAllowedInputTypes(1, {ALL_INTS})
|
||||
->setAllowedOutputTypes({FLOAT32});
|
||||
}
|
||||
|
||||
} // namespace ops
|
||||
} // namespace sd
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,150 @@
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* *
|
||||
* *
|
||||
* * This program and the accompanying materials are made available under the
|
||||
* * terms of the Apache License, Version 2.0 which is available at
|
||||
* * https://www.apache.org/licenses/LICENSE-2.0.
|
||||
* *
|
||||
* * See the NOTICE file distributed with this work for additional
|
||||
* * information regarding copyright ownership.
|
||||
* * 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.
|
||||
* *
|
||||
* * SPDX-License-Identifier: Apache-2.0
|
||||
* *****************************************************************************
|
||||
*/
|
||||
|
||||
//
|
||||
// @author sgazeos@gmail.com
|
||||
//
|
||||
|
||||
#include <system/op_boilerplate.h>
|
||||
#if NOT_EXCLUDED(OP_resize_bilinear)
|
||||
|
||||
#include <ops/declarable/CustomOperations.h>
|
||||
#include <ops/declarable/helpers/image_resize.h>
|
||||
namespace sd {
|
||||
namespace ops {
|
||||
CUSTOM_OP_IMPL(resize_bilinear, 1, 1, false, 0, -2) {
|
||||
NDArray* image = INPUT_VARIABLE(0);
|
||||
NDArray* output = OUTPUT_VARIABLE(0);
|
||||
int width;
|
||||
int height;
|
||||
bool alignCorners = false; // - default value
|
||||
auto inRank = image->rankOf();
|
||||
if (output->isEmpty()) return Status::OK;
|
||||
|
||||
REQUIRE_TRUE(inRank == 4 || inRank == 3, 0,
|
||||
"resize_bilinear: input image should be 4D "
|
||||
"tensor, but input has rank %i",
|
||||
image->rankOf());
|
||||
REQUIRE_TRUE(inRank == output->rankOf(), 0,
|
||||
"resize_bilinear: Input and output ranks should be equals, but %i and %i occured.", inRank,
|
||||
output->rankOf());
|
||||
std::vector<sd::LongType> imageShape1 = {image->sizeAt(0), image->sizeAt(1), image->sizeAt(2),image->sizeAt(3)};
|
||||
std::vector<sd::LongType> imageShape2 = {1, image->sizeAt(0), image->sizeAt(1), image->sizeAt(2)};
|
||||
|
||||
auto source =
|
||||
inRank == 4
|
||||
? image->reshape(image->ordering(),imageShape1)
|
||||
: image->reshape(image->ordering(), imageShape2);
|
||||
|
||||
|
||||
std::vector<sd::LongType> outputShape1 = {output->sizeAt(0), output->sizeAt(1), output->sizeAt(2),output->sizeAt(3)};
|
||||
std::vector<sd::LongType> outputShape2 = {1, output->sizeAt(0), output->sizeAt(1), output->sizeAt(2)};
|
||||
|
||||
auto target =
|
||||
inRank == 4
|
||||
? output->reshape(output->ordering(),
|
||||
outputShape1, false)
|
||||
: output->reshape(output->ordering(), outputShape2, false);
|
||||
|
||||
if (block.width() > 1) {
|
||||
auto newImageSize = INPUT_VARIABLE(1);
|
||||
REQUIRE_TRUE(newImageSize->lengthOf() == 2, 0, "resize_bilinear: Resize params is a pair of values, not %i.",
|
||||
newImageSize->lengthOf());
|
||||
REQUIRE_TRUE(block.numI() <= 1, 0,
|
||||
"resize_bilinear: Resize params already given by the second param. Int params are expensive.");
|
||||
height = newImageSize->e<int>(0);
|
||||
width = newImageSize->e<int>(1);
|
||||
} else {
|
||||
REQUIRE_TRUE(block.numI() > 1, 0, "resize_bilinear: Neither resize width nor height are provided.");
|
||||
height = INT_ARG(0);
|
||||
width = INT_ARG(1);
|
||||
}
|
||||
|
||||
if (block.numB() > 0) alignCorners = B_ARG(0);
|
||||
bool halfPixelCenter = false;
|
||||
|
||||
if (block.numB() > 1) halfPixelCenter = B_ARG(1);
|
||||
|
||||
REQUIRE_TRUE(!halfPixelCenter || (halfPixelCenter && !alignCorners), 0,
|
||||
"resize_bilinear: `half_pixel_centers' should be false or true only when `align_corners' is false");
|
||||
|
||||
auto ret = helpers::resizeBilinearFunctor(block.launchContext(), inRank == 4 ? image : source, width, height,
|
||||
alignCorners, halfPixelCenter, inRank == 4 ? output : target);
|
||||
delete source;
|
||||
delete target;
|
||||
return ret;
|
||||
}
|
||||
|
||||
DECLARE_SHAPE_FN(resize_bilinear) {
|
||||
auto shapeList = SHAPELIST();
|
||||
auto in = inputShape->at(0);
|
||||
|
||||
LongType* outputShape;
|
||||
auto inRank = shape::rank(in);
|
||||
REQUIRE_TRUE(inRank == 4 || inRank == 3, 0,
|
||||
"resize_bilinear: input image should be 4D "
|
||||
"tensor, but input has rank %i",
|
||||
inRank);
|
||||
|
||||
int width;
|
||||
int height;
|
||||
if (block.width() > 1) {
|
||||
auto newImageSize = INPUT_VARIABLE(1);
|
||||
REQUIRE_TRUE(newImageSize->lengthOf() == 2, 0, "resize_bilinear: Resize params is a pair of values, not %i.",
|
||||
newImageSize->lengthOf());
|
||||
REQUIRE_TRUE(block.numI() <= 1, 0,
|
||||
"resize_bilinear: Resize params already given by the second param. Int params are expensive.");
|
||||
width = newImageSize->e<int>(0);
|
||||
height = newImageSize->e<int>(1);
|
||||
} else {
|
||||
REQUIRE_TRUE(block.numI() == 2, 0, "resize_bilinear: Neither resize width nor height are provided.");
|
||||
width = INT_ARG(0);
|
||||
height = INT_ARG(1);
|
||||
}
|
||||
|
||||
ALLOCATE(outputShape, block.getWorkspace(), shape::shapeInfoLength(inRank), sd::LongType);
|
||||
outputShape[0] = inRank;
|
||||
if (inRank == 4) {
|
||||
outputShape[1] = in[1];
|
||||
outputShape[2] = width;
|
||||
outputShape[3] = height;
|
||||
outputShape[4] = in[4];
|
||||
} else { // input shape is 3D, so result also should be 3D
|
||||
outputShape[1] = width;
|
||||
outputShape[2] = height;
|
||||
outputShape[3] = in[3];
|
||||
}
|
||||
if (DataTypeUtils::isR(ArrayOptions::dataType(in))) {
|
||||
ShapeUtils::updateStridesAndType(outputShape, in, shape::order(in));
|
||||
} else {
|
||||
ShapeUtils::updateStridesAndType(outputShape, FLOAT32, shape::order(in));
|
||||
}
|
||||
|
||||
shapeList->push_back(CONSTANT(outputShape));
|
||||
return shapeList;
|
||||
}
|
||||
DECLARE_TYPES(resize_bilinear) {
|
||||
getOpDescriptor()->setAllowedInputTypes(ANY)->setAllowedOutputTypes({ALL_FLOATS});
|
||||
}
|
||||
|
||||
} // namespace ops
|
||||
} // namespace sd
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,154 @@
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* *
|
||||
* *
|
||||
* * This program and the accompanying materials are made available under the
|
||||
* * terms of the Apache License, Version 2.0 which is available at
|
||||
* * https://www.apache.org/licenses/LICENSE-2.0.
|
||||
* *
|
||||
* * See the NOTICE file distributed with this work for additional
|
||||
* * information regarding copyright ownership.
|
||||
* * 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.
|
||||
* *
|
||||
* * SPDX-License-Identifier: Apache-2.0
|
||||
* *****************************************************************************
|
||||
*/
|
||||
|
||||
//
|
||||
// @author sgazeos@gmail.com
|
||||
//
|
||||
|
||||
#include <system/op_boilerplate.h>
|
||||
#if NOT_EXCLUDED(OP_resize_nearest_neighbor)
|
||||
|
||||
#include <ops/declarable/CustomOperations.h>
|
||||
#include <ops/declarable/helpers/image_resize.h>
|
||||
|
||||
namespace sd {
|
||||
namespace ops {
|
||||
CUSTOM_OP_IMPL(resize_nearest_neighbor, 1, 1, false, 0, -2) {
|
||||
auto image = INPUT_VARIABLE(0);
|
||||
auto output = OUTPUT_VARIABLE(0);
|
||||
auto inRank = image->rankOf();
|
||||
int width;
|
||||
int height;
|
||||
bool alignCorners = false; // - default value
|
||||
if (output->isEmpty()) return Status::OK;
|
||||
if (block.width() > 1) {
|
||||
auto newImageSize = INPUT_VARIABLE(1);
|
||||
REQUIRE_TRUE(newImageSize->lengthOf() == 2, 0,
|
||||
"resize_nearest_neighbor: Resize params is a pair of values, not %i.", newImageSize->lengthOf());
|
||||
REQUIRE_TRUE(block.numI() <= 1, 0,
|
||||
"resize_nearest_neighbor: Resize params already given by the second param. Int params are expensive.");
|
||||
height = newImageSize->e<int>(0);
|
||||
width = newImageSize->e<int>(1);
|
||||
} else {
|
||||
REQUIRE_TRUE(block.numI() >= 2, 0, "resize_nearest_neighbor: Neither resize width nor height are provided.");
|
||||
height = INT_ARG(0);
|
||||
width = INT_ARG(1);
|
||||
}
|
||||
if (block.numB() > 0) alignCorners = B_ARG(0);
|
||||
|
||||
bool halfPixelCenter = false;
|
||||
|
||||
if (block.numB() > 1) halfPixelCenter = B_ARG(1);
|
||||
REQUIRE_TRUE(width <= (1 << 24) || height <= (1 << 24), 0,
|
||||
"resize_nearest_neighbor: the image resize should be limited to 2^24 pixels both for height and width, "
|
||||
"but %d and %d were given.",
|
||||
height, width);
|
||||
REQUIRE_TRUE(inRank == 4 || inRank == 3, 0,
|
||||
"resize_nearest_neighbor: Input should be 4D tensor, but rank %i occured");
|
||||
REQUIRE_TRUE(inRank == output->rankOf(), 0,
|
||||
"resize_nearest_neighbor: Input and output ranks should be equals, but %i and %i occured.", inRank,
|
||||
output->rankOf());
|
||||
REQUIRE_TRUE(image->dataType() == output->dataType(), 0,
|
||||
"resize_nearest_neighbor: Input and output types should be the same, but `%s' occured instead.",
|
||||
DataTypeUtils::asString(output->dataType()).c_str());
|
||||
REQUIRE_TRUE(
|
||||
!halfPixelCenter || (halfPixelCenter && !alignCorners), 0,
|
||||
"resize_nearest_neighbor: `half_pixel_centers' should be false or true only when `align_corners' is false");
|
||||
REQUIRE_TRUE(((alignCorners && height > 2) || (height > 0)) && ((alignCorners && width > 1) || (width > 0)), 0,
|
||||
"resize_nearest_neighbor: Wrong input or output size to resize (width = %d, height = %d)", width,
|
||||
height);
|
||||
|
||||
std::vector<sd::LongType> imageShape = {image->sizeAt(0), image->sizeAt(1), image->sizeAt(2)};
|
||||
auto source = inRank == 4
|
||||
? image
|
||||
: image->reshape(image->ordering(), imageShape);
|
||||
std::vector<sd::LongType> outputShape = {1, output->sizeAt(0), output->sizeAt(1),output->sizeAt(2)};
|
||||
auto target = inRank == 4 ? output
|
||||
: output->reshape(output->ordering(),
|
||||
outputShape, false);
|
||||
|
||||
helpers::NearestMode nearestMode = helpers::NearestMode::FLOOR;
|
||||
if (alignCorners) {
|
||||
nearestMode = helpers::NearestMode::ROUND_PREFER_CEIL;
|
||||
}
|
||||
helpers::CoordinateTransformationMode coorMode = halfPixelCenter
|
||||
? helpers::CoordinateTransformationMode::HALF_PIXEL_NN
|
||||
: helpers::CoordinateTransformationMode::ASYMMETRIC;
|
||||
|
||||
auto ret = resizeNeighborFunctor(block.launchContext(), inRank == 4 ? image : source, width, height, coorMode,
|
||||
nearestMode, alignCorners, inRank == 4 ? output : target);
|
||||
delete source;
|
||||
delete target;
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
DECLARE_SHAPE_FN(resize_nearest_neighbor) {
|
||||
auto shapeList = SHAPELIST();
|
||||
auto in = inputShape->at(0);
|
||||
auto inRank = shape::rank(in);
|
||||
LongType* outputShape;
|
||||
|
||||
REQUIRE_TRUE(inRank == 4 || inRank == 3, 0,
|
||||
"resize_nearest_neighbor: input image should be 4D "
|
||||
"tensor, but input has rank %i",
|
||||
inRank);
|
||||
|
||||
int width;
|
||||
int height;
|
||||
if (block.width() > 1) {
|
||||
auto newImageSize = INPUT_VARIABLE(1);
|
||||
REQUIRE_TRUE(newImageSize->lengthOf() == 2, 0,
|
||||
"resize_nearest_neighbor: Resize params is a pair of values, not %i.", newImageSize->lengthOf());
|
||||
REQUIRE_TRUE(block.numI() <= 1, 0,
|
||||
"resize_nearest_neighbor: Resize params already given by the second param. Int params are expensive.");
|
||||
width = newImageSize->e<int>(0);
|
||||
height = newImageSize->e<int>(1);
|
||||
} else {
|
||||
REQUIRE_TRUE(block.numI() <= 3, 0, "resize_nearest_neighbor: Neither resize width nor height are provided.");
|
||||
width = INT_ARG(0);
|
||||
height = INT_ARG(1);
|
||||
}
|
||||
|
||||
ALLOCATE(outputShape, block.getWorkspace(), shape::shapeInfoLength(inRank), sd::LongType);
|
||||
outputShape[0] = inRank;
|
||||
if (inRank == 4) {
|
||||
outputShape[1] = in[1];
|
||||
outputShape[2] = width;
|
||||
outputShape[3] = height;
|
||||
outputShape[4] = in[4];
|
||||
} else { // input shape is 3D, so result also should be 3D
|
||||
outputShape[1] = width;
|
||||
outputShape[2] = height;
|
||||
outputShape[3] = in[3];
|
||||
}
|
||||
ShapeUtils::updateStridesAndType(outputShape, in, shape::order(in));
|
||||
|
||||
shapeList->push_back(CONSTANT(outputShape));
|
||||
return shapeList;
|
||||
}
|
||||
DECLARE_TYPES(resize_nearest_neighbor) {
|
||||
getOpDescriptor()->setAllowedInputTypes({ALL_INTS, ALL_FLOATS})->setAllowedOutputTypes({ALL_INTS, ALL_FLOATS});
|
||||
}
|
||||
|
||||
} // namespace ops
|
||||
} // namespace sd
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,80 @@
|
||||
/* ******************************************************************************
|
||||
*
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Apache License, Version 2.0 which is available at
|
||||
* https://www.apache.org/licenses/LICENSE-2.0.
|
||||
*
|
||||
* See the NOTICE file distributed with this work for additional
|
||||
* information regarding copyright ownership.
|
||||
* 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.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
******************************************************************************/
|
||||
|
||||
//
|
||||
// @author Oleh Semeniv (oleg.semeniv@gmail.com)
|
||||
//
|
||||
|
||||
#include <execution/Threads.h>
|
||||
#include <helpers/ConstantTadHelper.h>
|
||||
#include <ops/declarable/CustomOperations.h>
|
||||
#include <ops/declarable/headers/images.h>
|
||||
#if NOT_EXCLUDED(OP_rgb_to_grs)
|
||||
namespace sd {
|
||||
namespace ops {
|
||||
|
||||
CUSTOM_OP_IMPL(rgb_to_grs, 1, 1, false, 0, 0) {
|
||||
const auto input = INPUT_VARIABLE(0);
|
||||
auto output = OUTPUT_VARIABLE(0);
|
||||
|
||||
const int inRank = input->rankOf();
|
||||
const int argSize = block.getIArguments()->size();
|
||||
const int dimC = argSize > 0 ? (INT_ARG(0) >= 0 ? INT_ARG(0) : INT_ARG(0) + inRank) : inRank - 1;
|
||||
|
||||
REQUIRE_TRUE(inRank >= 1, 0, "RGBtoGrayScale: Fails to meet the inRank requirement: %i >= 1 ", inRank);
|
||||
if (argSize > 0) {
|
||||
REQUIRE_TRUE(dimC >= 0 && dimC < inRank, 0, "Index of the Channel dimension out of range: %i not in [%i,%i) ",
|
||||
INT_ARG(0), -inRank, inRank);
|
||||
}
|
||||
REQUIRE_TRUE(input->sizeAt(dimC) == 3, 0,
|
||||
"RGBGrayScale: operation expects 3 channels (R, G, B) in last dimention, but received %i instead",
|
||||
input->sizeAt(dimC));
|
||||
|
||||
helpers::transformRgbGrs(block.launchContext(), *input, *output, dimC);
|
||||
return Status::OK;
|
||||
}
|
||||
|
||||
DECLARE_TYPES(rgb_to_grs) { getOpDescriptor()->setAllowedInputTypes({ALL_INTS, ALL_FLOATS})->setSameMode(true); }
|
||||
|
||||
DECLARE_SHAPE_FN(rgb_to_grs) {
|
||||
const auto input = INPUT_VARIABLE(0);
|
||||
const int inRank = input->rankOf();
|
||||
|
||||
const int argSize = block.getIArguments()->size();
|
||||
const int dimC = argSize > 0 ? (INT_ARG(0) >= 0 ? INT_ARG(0) : INT_ARG(0) + inRank) : inRank - 1;
|
||||
|
||||
REQUIRE_TRUE(inRank >= 1, 0, "RGBtoGrayScale: Fails to meet the inRank requirement: %i >= 1 ", inRank);
|
||||
if (argSize > 0) {
|
||||
REQUIRE_TRUE(dimC >= 0 && dimC < inRank, 0, "Index of the Channel dimension out of range: %i not in [%i,%i) ",
|
||||
INT_ARG(0), -inRank, inRank);
|
||||
}
|
||||
REQUIRE_TRUE(input->sizeAt(dimC) == 3, 0,
|
||||
"RGBtoGrayScale: operation expects 3 channels (R, B, G) in last dimention, but received %i", dimC);
|
||||
|
||||
auto* inputShapeVec = input->getShapeAsVector();
|
||||
(*inputShapeVec)[dimC] = 1;
|
||||
|
||||
auto result = SHAPELIST(ConstantShapeHelper::getInstance().createShapeInfo(input->dataType(), input->ordering(), *inputShapeVec));
|
||||
delete inputShapeVec;
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace ops
|
||||
} // namespace sd
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,59 @@
|
||||
/* ******************************************************************************
|
||||
*
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Apache License, Version 2.0 which is available at
|
||||
* https://www.apache.org/licenses/LICENSE-2.0.
|
||||
*
|
||||
* See the NOTICE file distributed with this work for additional
|
||||
* information regarding copyright ownership.
|
||||
* 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.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
******************************************************************************/
|
||||
|
||||
//
|
||||
// @author AbdelRauf (rauf@konduit.ai)
|
||||
//
|
||||
|
||||
#include <execution/Threads.h>
|
||||
#include <helpers/ConstantTadHelper.h>
|
||||
#include <ops/declarable/CustomOperations.h>
|
||||
#include <ops/declarable/headers/images.h>
|
||||
#if NOT_EXCLUDED(OP_rgb_to_hsv)
|
||||
namespace sd {
|
||||
namespace ops {
|
||||
|
||||
CONFIGURABLE_OP_IMPL(rgb_to_hsv, 1, 1, true, 0, 0) {
|
||||
auto input = INPUT_VARIABLE(0);
|
||||
auto output = OUTPUT_VARIABLE(0);
|
||||
|
||||
if (input->isEmpty()) return Status::OK;
|
||||
|
||||
const int rank = input->rankOf();
|
||||
const int argSize = block.getIArguments()->size();
|
||||
const int dimC = argSize > 0 ? (INT_ARG(0) >= 0 ? INT_ARG(0) : INT_ARG(0) + rank) : rank - 1;
|
||||
|
||||
REQUIRE_TRUE(rank >= 1, 0, "RGBtoHSV: Fails to meet the rank requirement: %i >= 1 ", rank);
|
||||
if (argSize > 0) {
|
||||
REQUIRE_TRUE(dimC >= 0 && dimC < rank, 0, "Index of the Channel dimension out of range: %i not in [%i,%i) ",
|
||||
INT_ARG(0), -rank, rank);
|
||||
}
|
||||
REQUIRE_TRUE(input->sizeAt(dimC) == 3, 0, "RGBtoHSV: operation expects 3 channels (R, G, B), but got %i instead",
|
||||
input->sizeAt(dimC));
|
||||
|
||||
helpers::transformRgbHsv(block.launchContext(), input, output, dimC);
|
||||
|
||||
return Status::OK;
|
||||
}
|
||||
|
||||
DECLARE_TYPES(rgb_to_hsv) { getOpDescriptor()->setAllowedInputTypes({ALL_FLOATS})->setSameMode(true); }
|
||||
|
||||
} // namespace ops
|
||||
} // namespace sd
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,59 @@
|
||||
/* ******************************************************************************
|
||||
*
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Apache License, Version 2.0 which is available at
|
||||
* https://www.apache.org/licenses/LICENSE-2.0.
|
||||
*
|
||||
* See the NOTICE file distributed with this work for additional
|
||||
* information regarding copyright ownership.
|
||||
* 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.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
******************************************************************************/
|
||||
|
||||
//
|
||||
// @author AbdelRauf (rauf@konduit.ai)
|
||||
//
|
||||
|
||||
#include <execution/Threads.h>
|
||||
#include <helpers/ConstantTadHelper.h>
|
||||
#include <ops/declarable/CustomOperations.h>
|
||||
#include <ops/declarable/headers/images.h>
|
||||
|
||||
#if NOT_EXCLUDED(OP_rgb_to_yiq)
|
||||
namespace sd {
|
||||
namespace ops {
|
||||
|
||||
CONFIGURABLE_OP_IMPL(rgb_to_yiq, 1, 1, true, 0, 0) {
|
||||
auto input = INPUT_VARIABLE(0);
|
||||
auto output = OUTPUT_VARIABLE(0);
|
||||
|
||||
if (input->isEmpty()) return Status::OK;
|
||||
|
||||
const int rank = input->rankOf();
|
||||
const int arg_size = block.getIArguments()->size();
|
||||
const int dimC = arg_size > 0 ? (INT_ARG(0) >= 0 ? INT_ARG(0) : INT_ARG(0) + rank) : rank - 1;
|
||||
|
||||
REQUIRE_TRUE(rank >= 1, 0, "RGBtoYIQ: Fails to meet the rank requirement: %i >= 1 ", rank);
|
||||
if (arg_size > 0) {
|
||||
REQUIRE_TRUE(dimC >= 0 && dimC < rank, 0, "Index of the Channel dimension out of range: %i not in [%i,%i) ",
|
||||
INT_ARG(0), -rank, rank);
|
||||
}
|
||||
REQUIRE_TRUE(input->sizeAt(dimC) == 3, 0, "RGBtoYIQ: operation expects 3 channels (R, G, B), but got %i instead",
|
||||
input->sizeAt(dimC));
|
||||
|
||||
helpers::transformRgbYiq(block.launchContext(), input, output, dimC);
|
||||
|
||||
return Status::OK;
|
||||
}
|
||||
|
||||
DECLARE_TYPES(rgb_to_yiq) { getOpDescriptor()->setAllowedInputTypes({ALL_FLOATS})->setSameMode(true); }
|
||||
} // namespace ops
|
||||
} // namespace sd
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,59 @@
|
||||
/* ******************************************************************************
|
||||
*
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Apache License, Version 2.0 which is available at
|
||||
* https://www.apache.org/licenses/LICENSE-2.0.
|
||||
*
|
||||
* See the NOTICE file distributed with this work for additional
|
||||
* information regarding copyright ownership.
|
||||
* 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.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
******************************************************************************/
|
||||
|
||||
//
|
||||
// @author Oleh Semeniv (oleg.semeniv@gmail.com)
|
||||
//
|
||||
|
||||
#include <execution/Threads.h>
|
||||
#include <helpers/ConstantTadHelper.h>
|
||||
#include <ops/declarable/CustomOperations.h>
|
||||
#include <ops/declarable/headers/images.h>
|
||||
#if NOT_EXCLUDED(OP_rgb_to_yuv)
|
||||
namespace sd {
|
||||
namespace ops {
|
||||
|
||||
CONFIGURABLE_OP_IMPL(rgb_to_yuv, 1, 1, true, 0, 0) {
|
||||
auto input = INPUT_VARIABLE(0);
|
||||
auto output = OUTPUT_VARIABLE(0);
|
||||
|
||||
// just skip op if input is empty
|
||||
if (input->isEmpty()) return Status::OK;
|
||||
|
||||
const int rank = input->rankOf();
|
||||
const int argSize = block.getIArguments()->size();
|
||||
const int dimC = argSize > 0 ? (INT_ARG(0) >= 0 ? INT_ARG(0) : INT_ARG(0) + rank) : rank - 1;
|
||||
|
||||
REQUIRE_TRUE(rank >= 1, 0, "RGBtoYUV: Fails to meet the rank requirement: %i >= 1 ", rank);
|
||||
if (argSize > 0) {
|
||||
REQUIRE_TRUE(dimC >= 0 && dimC < rank, 0, "Index of the Channel dimension out of range: %i not in [%i,%i) ",
|
||||
INT_ARG(0), -rank, rank);
|
||||
}
|
||||
REQUIRE_TRUE(input->sizeAt(dimC) == 3, 0, "RGBtoYUV: operation expects 3 channels (R, G, B), but got %i instead",
|
||||
input->sizeAt(dimC));
|
||||
|
||||
helpers::transformRgbYuv(block.launchContext(), *input, *output, dimC);
|
||||
|
||||
return Status::OK;
|
||||
}
|
||||
|
||||
DECLARE_TYPES(rgb_to_yuv) { getOpDescriptor()->setAllowedInputTypes({ALL_FLOATS})->setSameMode(true); }
|
||||
|
||||
} // namespace ops
|
||||
} // namespace sd
|
||||
#endif
|
||||
@@ -0,0 +1,59 @@
|
||||
/* ******************************************************************************
|
||||
*
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Apache License, Version 2.0 which is available at
|
||||
* https://www.apache.org/licenses/LICENSE-2.0.
|
||||
*
|
||||
* See the NOTICE file distributed with this work for additional
|
||||
* information regarding copyright ownership.
|
||||
* 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.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
******************************************************************************/
|
||||
|
||||
//
|
||||
// @author AbdelRauf (rauf@konduit.ai)
|
||||
//
|
||||
|
||||
#include <execution/Threads.h>
|
||||
#include <helpers/ConstantTadHelper.h>
|
||||
#include <ops/declarable/CustomOperations.h>
|
||||
#include <ops/declarable/headers/images.h>
|
||||
#if NOT_EXCLUDED(OP_yiq_to_rgb)
|
||||
namespace sd {
|
||||
namespace ops {
|
||||
|
||||
CONFIGURABLE_OP_IMPL(yiq_to_rgb, 1, 1, true, 0, 0) {
|
||||
auto input = INPUT_VARIABLE(0);
|
||||
auto output = OUTPUT_VARIABLE(0);
|
||||
|
||||
if (input->isEmpty()) return Status::OK;
|
||||
|
||||
const int rank = input->rankOf();
|
||||
const int arg_size = block.getIArguments()->size();
|
||||
const int dimC = arg_size > 0 ? (INT_ARG(0) >= 0 ? INT_ARG(0) : INT_ARG(0) + rank) : rank - 1;
|
||||
|
||||
REQUIRE_TRUE(rank >= 1, 0, "YIQtoRGB: Fails to meet the rank requirement: %i >= 1 ", rank);
|
||||
if (arg_size > 0) {
|
||||
REQUIRE_TRUE(dimC >= 0 && dimC < rank, 0, "Index of the Channel dimension out of range: %i not in [%i,%i) ",
|
||||
INT_ARG(0), -rank, rank);
|
||||
}
|
||||
REQUIRE_TRUE(input->sizeAt(dimC) == 3, 0, "YIQtoRGB: operation expects 3 channels (Y, I, Q), but got %i instead",
|
||||
input->sizeAt(dimC));
|
||||
|
||||
helpers::transformYiqRgb(block.launchContext(), input, output, dimC);
|
||||
|
||||
return Status::OK;
|
||||
}
|
||||
|
||||
DECLARE_TYPES(yiq_to_rgb) { getOpDescriptor()->setAllowedInputTypes({ALL_FLOATS})->setSameMode(true); }
|
||||
|
||||
} // namespace ops
|
||||
} // namespace sd
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,60 @@
|
||||
/* ******************************************************************************
|
||||
*
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Apache License, Version 2.0 which is available at
|
||||
* https://www.apache.org/licenses/LICENSE-2.0.
|
||||
*
|
||||
* See the NOTICE file distributed with this work for additional
|
||||
* information regarding copyright ownership.
|
||||
* 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.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
******************************************************************************/
|
||||
|
||||
//
|
||||
// @author Oleh Semeniv (oleg.semeniv@gmail.com)
|
||||
//
|
||||
|
||||
#include <execution/Threads.h>
|
||||
#include <helpers/ConstantTadHelper.h>
|
||||
#include <ops/declarable/CustomOperations.h>
|
||||
#include <ops/declarable/headers/images.h>
|
||||
#if NOT_EXCLUDED(OP_yuv_to_rgb)
|
||||
namespace sd {
|
||||
namespace ops {
|
||||
|
||||
CONFIGURABLE_OP_IMPL(yuv_to_rgb, 1, 1, true, 0, 0) {
|
||||
auto input = INPUT_VARIABLE(0);
|
||||
auto output = OUTPUT_VARIABLE(0);
|
||||
|
||||
// just skip op if input is empty
|
||||
if (input->isEmpty()) return Status::OK;
|
||||
|
||||
const int rank = input->rankOf();
|
||||
const int argSize = block.getIArguments()->size();
|
||||
const int dimC = argSize > 0 ? (INT_ARG(0) >= 0 ? INT_ARG(0) : INT_ARG(0) + rank) : rank - 1;
|
||||
|
||||
REQUIRE_TRUE(rank >= 1, 0, "YUVtoRGB: Fails to meet the rank requirement: %i >= 1 ", rank);
|
||||
if (argSize > 0) {
|
||||
REQUIRE_TRUE(dimC >= 0 && dimC < rank, 0, "Index of the Channel dimension out of range: %i not in [%i,%i) ",
|
||||
INT_ARG(0), -rank, rank);
|
||||
}
|
||||
REQUIRE_TRUE(input->sizeAt(dimC) == 3, 0, "YUVtoRGB: operation expects 3 channels (Y, U, V), but got %i instead",
|
||||
input->sizeAt(dimC));
|
||||
|
||||
helpers::transformYuvRgb(block.launchContext(), *input, *output, dimC);
|
||||
|
||||
return Status::OK;
|
||||
}
|
||||
|
||||
DECLARE_TYPES(yuv_to_rgb) { getOpDescriptor()->setAllowedInputTypes({ALL_FLOATS})->setSameMode(true); }
|
||||
|
||||
} // namespace ops
|
||||
} // namespace sd
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user