Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BrightnessContrast operator #1188

Merged
merged 47 commits into from
Sep 25, 2019
Merged
Show file tree
Hide file tree
Changes from 41 commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
175b768
first impl
szalpal Aug 8, 2019
67ecae2
wip
szalpal Aug 13, 2019
ca22d38
wip
szalpal Aug 14, 2019
0bc93c5
wip
szalpal Aug 14, 2019
09f84b2
wip
szalpal Aug 14, 2019
dab3536
wip
szalpal Aug 16, 2019
b9a6700
swap output and input in bricon_cpu
szalpal Aug 16, 2019
e28f50b
wip
szalpal Aug 16, 2019
fe5d742
rename
szalpal Aug 19, 2019
93fb518
wip
szalpal Aug 19, 2019
4735bb1
first impl
szalpal Aug 8, 2019
a1c6120
wip
szalpal Aug 13, 2019
9b33163
wip
szalpal Aug 14, 2019
f90d642
wip
szalpal Aug 14, 2019
026ea07
wip
szalpal Aug 14, 2019
2f99aeb
wip
szalpal Aug 16, 2019
3101bc9
swap output and input in bricon_cpu
szalpal Aug 16, 2019
b36e873
wip
szalpal Aug 16, 2019
0237760
rename
szalpal Aug 19, 2019
615bde0
wip
szalpal Aug 19, 2019
3aa2201
first impl
szalpal Aug 8, 2019
d95cde5
wip
szalpal Aug 13, 2019
3103c9e
wip
szalpal Aug 14, 2019
289ac75
wip
szalpal Aug 14, 2019
10bbed7
wip
szalpal Aug 14, 2019
e8ef7cf
wip
szalpal Aug 16, 2019
cc53f98
swap output and input in bricon_cpu
szalpal Aug 16, 2019
3f0f84d
wip
szalpal Aug 16, 2019
370a83b
rename
szalpal Aug 19, 2019
5462d4f
wip
szalpal Aug 19, 2019
4b147b0
wip, some weird error
szalpal Aug 20, 2019
2056384
Merge branch 'bricon_op' of github.com:szalpal/DALI into bricon_op
szalpal Aug 21, 2019
3ed1f6c
Merge branch 'bricon_op' of github.com:szalpal/DALI into bricon_op
szalpal Aug 21, 2019
122d154
working
szalpal Aug 21, 2019
7abd61f
lint
szalpal Aug 21, 2019
0d8a6f2
docs
szalpal Aug 21, 2019
1f63950
fix warning
szalpal Aug 21, 2019
f07d894
dali_type_switch -> type_switch
szalpal Aug 26, 2019
c28402b
Merge branch 'master' into bricon_op
szalpal Sep 17, 2019
f31167b
review
szalpal Sep 17, 2019
0a6cc20
lint
szalpal Sep 17, 2019
43cb965
review
szalpal Sep 18, 2019
5e2a9c8
fixing warnings
szalpal Sep 18, 2019
c058a6c
review
szalpal Sep 18, 2019
0a66242
review
szalpal Sep 23, 2019
90bd1eb
review
szalpal Sep 23, 2019
cc4f7d6
Update dali/pipeline/operators/color/brightness_contrast.h
szalpal Sep 25, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions dali/kernels/imgproc/color_manipulation/brightness_contrast.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@
namespace dali {
namespace kernels {

template<typename InputType, typename OutputType, size_t ndims = 3>
class BrightnessContrastCPU {
template<typename OutputType, typename InputType, size_t ndims = 3>
szalpal marked this conversation as resolved.
Show resolved Hide resolved
class BrightnessContrastCpu {
private:
static constexpr size_t spatial_dims = ndims - 1;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,18 +76,26 @@ class BrightnessContrastCpuTest : public ::testing::Test {
};


using TestTypes = std::tuple<uint8_t, int8_t, uint16_t, int16_t, int32_t, float>;
using TestTypes = std::tuple<uint8_t, int16_t, int32_t, float>;
INPUT_OUTPUT_TYPED_TEST_SUITE(BrightnessContrastCpuTest, TestTypes);

namespace {

template <class GtestTypeParam>
using TheKernel = BrightnessContrastCpu<typename GtestTypeParam::Out, typename GtestTypeParam::In>;
szalpal marked this conversation as resolved.
Show resolved Hide resolved

} // namespace



TYPED_TEST(BrightnessContrastCpuTest, check_kernel) {
BrightnessContrastCPU<typename TypeParam::In, typename TypeParam::Out> kernel;
TheKernel<TypeParam> kernel;
check_kernel<decltype(kernel)>();
}


TYPED_TEST(BrightnessContrastCpuTest, SetupTestAndCheckKernel) {
BrightnessContrastCPU<typename TypeParam::In, typename TypeParam::Out> kernel;
TheKernel<TypeParam> kernel;
constexpr auto ndims = std::remove_reference_t<decltype(*this)>::ndims;
KernelContext ctx;
InTensorCPU<typename TypeParam::In, ndims> in(this->input_.data(), this->shape_);
Expand All @@ -98,7 +106,7 @@ TYPED_TEST(BrightnessContrastCpuTest, SetupTestAndCheckKernel) {


TYPED_TEST(BrightnessContrastCpuTest, RunTest) {
BrightnessContrastCPU<typename TypeParam::In, typename TypeParam::Out> kernel;
TheKernel<TypeParam> kernel;
constexpr auto ndims = std::remove_reference_t<decltype(*this)>::ndims;
KernelContext ctx;
InTensorCPU<typename TypeParam::In, ndims> in(this->input_.data(), this->shape_);
Expand All @@ -117,7 +125,7 @@ TYPED_TEST(BrightnessContrastCpuTest, RunTest) {


TYPED_TEST(BrightnessContrastCpuTest, RunTestWithRoi) {
BrightnessContrastCPU<typename TypeParam::In, typename TypeParam::Out> kernel;
TheKernel<TypeParam> kernel;
constexpr auto ndims = std::remove_reference_t<decltype(*this)>::ndims;
KernelContext ctx;
InTensorCPU<typename TypeParam::In, ndims> in(this->input_.data(), this->shape_);
Expand Down
40 changes: 40 additions & 0 deletions dali/pipeline/operators/color/brightness_contrast.cu
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "dali/pipeline/operators/color/brightness_contrast.h"

namespace dali {
namespace brightness_contrast {

DALI_REGISTER_OPERATOR(BrightnessContrast, BrightnessContrast<CPUBackend>, CPU)

DALI_REGISTER_OPERATOR(BrightnessContrast, BrightnessContrast<GPUBackend>, GPU)


DALI_SCHEMA(BrightnessContrast)
.DocStr(R"code(Change the brightness and contrast of the image.
Additionally, this operator can change the type of data.)code")
szalpal marked this conversation as resolved.
Show resolved Hide resolved
.NumInput(1)
.NumOutput(1)
.AddOptionalArg(detail::kBrightness,
Copy link
Contributor

@jantonguirao jantonguirao Aug 28, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I personally dislike the use of the constant here. I'd like to see the name of the argument here

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The string with argument name needs to be used multiple times in implementation of operator. In this case, I want to have it as a constant, no a magic string

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was thinking about that problem. I'd rather make it belong to Operator class than to detail namespace. I would at least change that.

Still it's not aligned with the rest of the code base.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed to spec::kBrightness

R"code(Set additive brightness delta. 0 denotes no-op)code", .0f,
true)
.AddOptionalArg(detail::kContrast,
R"code(Set multiplicative contrast delta. 1 denotes no-op)code",
1.f, true)
.AddOptionalArg(detail::kOutputType, R"code(Set output data type)code", DALI_INT16);


} // namespace brightness_contrast
} // namespace dali
193 changes: 193 additions & 0 deletions dali/pipeline/operators/color/brightness_contrast.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
// Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef DALI_PIPELINE_OPERATORS_COLOR_BRIGHTNESS_CONTRAST_H_
#define DALI_PIPELINE_OPERATORS_COLOR_BRIGHTNESS_CONTRAST_H_

#include <vector>
#include <memory>
#include <string>
#include "dali/core/static_switch.h"
#include "dali/pipeline/data/views.h"
#include "dali/pipeline/operators/common.h"
#include "dali/pipeline/operators/operator.h"
#include "dali/kernels/imgproc/color_manipulation/brightness_contrast.h"
#include "dali/kernels/imgproc/color_manipulation/brightness_contrast_gpu.h"
#include "dali/kernels/kernel_manager.h"

namespace dali {
namespace brightness_contrast {

namespace detail {

const std::string kBrightness = "brightness_delta"; // NOLINT
szalpal marked this conversation as resolved.
Show resolved Hide resolved
const std::string kContrast = "contrast_delta"; // NOLINT
const std::string kOutputType = "output_type"; // NOLINT


template <typename Backend, typename Out, typename In, size_t ndims>
struct Kernel {
using type = kernels::BrightnessContrastCpu<Out, In, ndims>;
};


template <typename Out, typename In, size_t ndims>
struct Kernel<GPUBackend, Out, In, ndims> {
using type = kernels::brightness_contrast::BrightnessContrastGpu<Out, In, ndims>;
};


template <typename Backend>
struct ArgumentType {
static_assert(
std::is_same<Backend, CPUBackend>::value || std::is_same<Backend, GPUBackend>::value,
"Unsupported Backend");
using type = float;
};


template <>
struct ArgumentType<GPUBackend> {
using type = std::vector<float>;
};


/**
* Select proper type for argument (for either sample processing or batch processing cases)
*/
template <typename Backend>
using argument_t = typename ArgumentType<Backend>::type;


/**
* Chooses proper kernel (CPU or GPU) for given template parameters
*/
template <typename Backend, typename OutputType, typename InputType, size_t ndims>
szalpal marked this conversation as resolved.
Show resolved Hide resolved
using BrightnessContrastKernel = typename Kernel<Backend, OutputType, InputType, ndims>::type;


/**
* Assign argument, whether it is a single value (for sample-wise processing)
* or vector of values (for batch processing, where every argument is defined per-sample)
*/
template <typename Backend>
void assign_argument_value(const OpSpec &, const std::string &, argument_t<Backend> &) {
DALI_FAIL("Unsupported Backend. You may want to write your own specialization.");
}


template <>
void assign_argument_value<CPUBackend>(const OpSpec &spec, const std::string &arg_name,
argument_t<CPUBackend> &arg) {
std::vector<float> tmp;
GetSingleOrRepeatedArg(spec, tmp, arg_name);
arg = tmp[0];
}


template <>
void assign_argument_value<GPUBackend>(const OpSpec &spec, const std::string &arg_name,
argument_t<GPUBackend> &arg) {
GetSingleOrRepeatedArg(spec, arg, arg_name);
}

} // namespace detail


template <typename Backend>
class BrightnessContrast : public Operator<Backend> {
public:
explicit BrightnessContrast(const OpSpec &spec) :
Operator<Backend>(spec),
output_type_(spec.GetArgument<DALIDataType>(detail::kOutputType)) {
detail::assign_argument_value<Backend>(spec, detail::kBrightness, brightness_);
detail::assign_argument_value<Backend>(spec, detail::kContrast, contrast_);
if (std::is_same<Backend, GPUBackend>::value) {
kernel_manager_.Resize(1, 1);
} else {
kernel_manager_.Resize(num_threads_, batch_size_);
}
}


~BrightnessContrast() = default;
szalpal marked this conversation as resolved.
Show resolved Hide resolved


DISABLE_COPY_MOVE_ASSIGN(BrightnessContrast);


protected:
bool CanInferOutputs() const override {
return true;
}


bool SetupImpl(std::vector<::dali::OutputDesc> &output_desc,
const ::dali::workspace_t<Backend> &ws) override {
const auto &input = ws.template InputRef<Backend>(0);
const auto &output = ws.template OutputRef<Backend>(0);
output_desc.resize(1);

TYPE_SWITCH(output_type_, type2id, OutputType, (uint8_t, int16_t, int32_t, float), (
jantonguirao marked this conversation as resolved.
Show resolved Hide resolved
{
TypeInfo type;
type.SetType<OutputType>(output_type_);
output_desc[0] = {input.shape(), type};
}
), DALI_FAIL("Unsupported image type")) // NOLINT
return true;
}

/**
* So that compiler wouldn't complain, that
szalpal marked this conversation as resolved.
Show resolved Hide resolved
* "overloaded virtual function `dali::Operator<dali::CPUBackend>::RunImpl` is only partially
* overridden in class `dali::brightness_contrast::BrightnessContrast<dali::CPUBackend>`"
*/
using Operator<Backend>::RunImpl;
jantonguirao marked this conversation as resolved.
Show resolved Hide resolved


void RunImpl(Workspace<Backend> &ws) {
const auto &input = ws.template Input<Backend>(0);
auto &output = ws.template Output<Backend>(0);

TYPE_SWITCH(input.type().id(), type2id, InputType, (uint8_t, int16_t, int32_t, float), (
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DALI_TYPE_SWITCH_WITH_FP16 ?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Regarding types, that are supported here, I followed requirements, so I'd like to manually specify types, that are supported

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It says:

Output types: [u8, i8, u16, i16, u32, i32, f32]
Input types: [u8, i8, u16, i16, u32, i32, f32]

you are not covering all the cases.

In my opinion, there is no reason for not using the DALI_TYPE_SWITCH_WITH_FP16 here and cover all available types

TYPE_SWITCH(output_type_, type2id, OutputType, (uint8_t, int16_t, int32_t, float), (
{
using BrightnessContrastKernel =
detail::BrightnessContrastKernel<Backend, OutputType, InputType, 3>;
auto tvin = view<const InputType, 3>(input);
auto tvout = view<OutputType, 3>(output);
kernel_manager_.Initialize<BrightnessContrastKernel>();
kernels::KernelContext ctx;
kernel_manager_.Setup<BrightnessContrastKernel>(ws.data_idx(),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's your opinion on calling kernel::Setup in Operator::SetupImpl`?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Generally speaking, I'd say that it should be this way. However, here we have a special case. Meaning, it's not necessary to call Setup in SetupImpl. On the other hand, implementing it this way would require major change with duplicating TYPE_SWITCHes, which obfuscates the code. While it would be possible to do this implementation without such duplication, the abstraction layer for this is not ready yet and will require some time to evolve. Keeping all this in mind, plus taking into account, that this PR is already quite a time here (I already rebased it twice), I'd like to merge it now and, when it proves to be necessary, add the abstraction layer later.

ctx, tvin, brightness_, contrast_);
kernel_manager_.Run<BrightnessContrastKernel>(ws.thread_idx(), ws.data_idx(),
ctx, tvout, tvin, brightness_, contrast_);
}
), DALI_FAIL("Unsupported output type")) // NOLINT
), DALI_FAIL("Unsupported input type")) // NOLINT
}


private:
USE_OPERATOR_MEMBERS();
detail::argument_t<Backend> brightness_, contrast_;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe personal preference:
A little bit of an overkill in my opinion. I'd rather have vector<float> all the time and get rid of argument_t. It will just have 1 element for CPUBackend and more than that for GPUBackend

DALIDataType output_type_;
kernels::KernelManager kernel_manager_;
};

} // namespace brightness_contrast
} // namespace dali

#endif // DALI_PIPELINE_OPERATORS_COLOR_BRIGHTNESS_CONTRAST_H_
Loading