chore: import upstream snapshot with attribution

This commit is contained in:
wehub-resource-sync
2026-07-13 12:47:05 +08:00
commit 4f3b7da785
7394 changed files with 2005594 additions and 0 deletions
@@ -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