Compute Library
 21.02
NECumulativeDistributionKernel.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2016-2020 Arm Limited.
3  *
4  * SPDX-License-Identifier: MIT
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to
8  * deal in the Software without restriction, including without limitation the
9  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10  * sell copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in all
14  * copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22  * SOFTWARE.
23  */
25 
26 #include "arm_compute/core/Error.h"
29 #include "arm_compute/core/ILut.h"
31 #include "arm_compute/core/Types.h"
35 
36 #include <algorithm>
37 #include <cmath>
38 #include <numeric>
39 
40 using namespace arm_compute;
41 
43  : _input(nullptr), _distribution(nullptr), _cumulative_sum(nullptr), _output(nullptr)
44 {
45 }
46 
48 {
49  return false;
50 }
51 
53 {
54  ARM_COMPUTE_ERROR_ON_NULLPTR(input, distribution, cumulative_sum, output);
56 
58 
59  ARM_COMPUTE_ERROR_ON(distribution->num_bins() != cumulative_sum->num_bins());
60  ARM_COMPUTE_ERROR_ON(distribution->num_bins() != output->num_elements());
62  ARM_COMPUTE_ERROR_ON(input->info()->data_type() != output->type());
63 
64  _input = input;
65  _distribution = distribution;
66  _cumulative_sum = cumulative_sum;
67  _output = output;
68 
69  INEKernel::configure(calculate_max_window(*input->info()));
70 }
71 
73 {
74  ARM_COMPUTE_UNUSED(info);
75  ARM_COMPUTE_UNUSED(window);
78  ARM_COMPUTE_ERROR_ON(_distribution->buffer() == nullptr);
79  ARM_COMPUTE_ERROR_ON(_cumulative_sum->buffer() == nullptr);
80  ARM_COMPUTE_ERROR_ON(_output->buffer() == nullptr);
81  ARM_COMPUTE_ERROR_ON_MSG(_distribution->num_bins() < 256, "Distribution must have 256 bins");
82 
83  // Calculate the cumulative distribution (summed histogram).
84  const uint32_t *hist = _distribution->buffer();
85  uint32_t *cumulative_sum = _cumulative_sum->buffer();
86  uint8_t *output = _output->buffer();
87 
88  // Calculate cumulative distribution
89  std::partial_sum(hist, hist + _histogram_size, cumulative_sum);
90 
91  // Get the number of pixels that have the lowest value in the input image
92  const uint32_t cd_min = *std::find_if(hist, hist + _histogram_size, [](const uint32_t &v)
93  {
94  return v > 0;
95  });
96  const uint32_t image_size = cumulative_sum[_histogram_size - 1];
97 
98  ARM_COMPUTE_ERROR_ON(cd_min > image_size);
99 
100  // Create mapping lookup table
101  if(image_size == cd_min)
102  {
103  std::iota(output, output + _histogram_size, 0);
104  }
105  else
106  {
107  const float diff = image_size - cd_min;
108 
109  for(unsigned int x = 0; x < _histogram_size; ++x)
110  {
111  output[x] = lround((cumulative_sum[x] - cd_min) / diff * 255.0f);
112  }
113  }
114 }
bool set_format_if_unknown(ITensorInfo &info, Format format)
Set the format, data type and number of channels to the specified value if the current data type is u...
Window calculate_max_window(const ValidRegion &valid_region, const Steps &steps, bool skip_border, BorderSize border_size)
const Window & window() const
The maximum window the kernel can be executed on.
Definition: IKernel.cpp:28
#define ARM_COMPUTE_ERROR_ON_TENSOR_NOT_2D(t)
Definition: Validate.h:856
void run(const Window &window, const ThreadInfo &info) override
Execute the kernel on the passed window.
1 channel, 1 U8 per channel
virtual DataType data_type() const =0
Data type used for each element of the tensor.
#define ARM_COMPUTE_ERROR_ON(cond)
If the condition is true then an error message is printed and an exception thrown.
Definition: Error.h:466
Interface for Neon tensor.
Definition: ITensor.h:36
virtual size_t num_elements() const =0
Returns the total number of elements in the LUT.
Copyright (c) 2017-2021 Arm Limited.
virtual uint32_t * buffer() const =0
Returns a pointer to the start of the distribution.
#define ARM_COMPUTE_UNUSED(...)
To avoid unused variables warnings.
Definition: Error.h:152
1D Distribution interface
Lookup Table object interface.
Definition: ILut.h:34
#define ARM_COMPUTE_ERROR_ON_MSG(cond, msg)
Definition: Error.h:456
bool is_parallelisable() const override
Indicates whether or not the kernel is parallelisable.
virtual ITensorInfo * info() const =0
Interface to be implemented by the child class to return the tensor&#39;s metadata.
std::uniform_real_distribution< float > distribution(-5.f, 5.f)
void configure(const IImage *input, const IDistribution1D *distribution, IDistribution1D *cumulative_sum, ILut *output)
Set the input and output distribution.
#define ARM_COMPUTE_ERROR_ON_UNCONFIGURED_KERNEL(k)
Definition: Validate.h:941
size_t num_bins() const
Returns the number of bins that the distribution has.
#define ARM_COMPUTE_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(t, c,...)
Definition: Validate.h:790
virtual DataType type() const =0
Returns the type of the LUT.
ScaleKernelInfo info(interpolation_policy, default_border_mode, PixelValue(), sampling_policy, false)
Information about executing thread and CPU.
Definition: CPPTypes.h:235
virtual uint8_t * buffer() const =0
Returns a pointer to the start of the LUT.
#define ARM_COMPUTE_ERROR_ON_NULLPTR(...)
Definition: Validate.h:161
Describe a multidimensional execution window.
Definition: Window.h:39
#define ARM_COMPUTE_ERROR_ON_INVALID_SUBWINDOW(f, s)
Definition: Validate.h:205