/*
 * Copyright (c) 2017-2019 Arm Limited.
 *
 * SPDX-License-Identifier: MIT
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to
 * deal in the Software without restriction, including without limitation the
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 * sell copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
#include "HOGDescriptor.h"

#include "Derivative.h"
#include "Magnitude.h"
#include "Phase.h"

namespace arm_compute
{
namespace test
{
namespace validation
{
namespace reference
{
namespace
{
template <typename T>
void hog_orientation_compute(const SimpleTensor<T> &mag, const SimpleTensor<T> &phase, std::vector<T> &bins, const HOGInfo &hog_info)
{
    const Size2D &cell_size = hog_info.cell_size();
    const size_t  num_bins  = hog_info.num_bins();

    float phase_scale = (PhaseType::SIGNED == hog_info.phase_type() ? num_bins / 360.0f : num_bins / 180.0f);
    phase_scale *= (PhaseType::SIGNED == hog_info.phase_type() ? 360.0f / 255.0f : 1.0f);

    int row_idx = 0;
    for(size_t yc = 0; yc < cell_size.height; ++yc)
    {
        for(size_t xc = 0; xc < cell_size.width; xc++)
        {
            const float mag_value   = mag[(row_idx + xc)];
            const float phase_value = phase[(row_idx + xc)] * phase_scale + 0.5f;
            const float w1          = phase_value - floor(phase_value);

            // The quantised phase is the histogram index [0, num_bins - 1]
            // Check limit of histogram index. If hidx == num_bins, hidx = 0
            const auto hidx = static_cast<unsigned int>(phase_value) % num_bins;

            // Weighted vote between 2 bins
            bins[hidx] += mag_value * (1.0f - w1);
            bins[(hidx + 1) % num_bins] += mag_value * w1;
        }

        row_idx += cell_size.width;
    }
}

template <typename T>
void hog_block_normalization_compute(SimpleTensor<T> &block, SimpleTensor<T> &desc, const HOGInfo &hog_info, uint32_t block_idx)
{
    const int         num_bins_per_block = desc.num_channels();
    const HOGNormType norm_type          = hog_info.normalization_type();
    const Coordinates id                 = index2coord(desc.shape(), block_idx);

    float sum = 0.0f;

    // Calculate sum
    for(int i = 0; i < num_bins_per_block; ++i)
    {
        const float val = block[i];
        sum += (norm_type == HOGNormType::L1_NORM) ? std::fabs(val) : val * val;
    }

    // Calculate normalization scale
    float scale = 1.0f / (std::sqrt(sum) + num_bins_per_block * 0.1f);

    if(norm_type == HOGNormType::L2HYS_NORM)
    {
        // Reset sum
        sum = 0.0f;
        for(int i = 0; i < num_bins_per_block; ++i)
        {
            float val = block[i] * scale;

            // Clip scaled input_value if over l2_hyst_threshold
            val = fmin(val, hog_info.l2_hyst_threshold());
            sum += val * val;
            block[i] = val;
        }

        // We use the same constants of OpenCV
        scale = 1.0f / (std::sqrt(sum) + 1e-3f);
    }

    for(int i = 0; i < num_bins_per_block; ++i)
    {
        block[i] *= scale;
        reinterpret_cast<float *>(desc(id))[i] = block[i];
    }
}
} // namespace

template <typename T, typename U, typename V>
void hog_orientation_binning(const SimpleTensor<T> &mag, const SimpleTensor<U> &phase, SimpleTensor<V> &hog_space, const HOGInfo &hog_info)
{
    const Size2D &cell_size = hog_info.cell_size();

    const size_t num_bins     = hog_info.num_bins();
    const size_t shape_width  = hog_space.shape().x() * hog_info.cell_size().width;
    const size_t shape_height = hog_space.shape().y() * hog_info.cell_size().height;

    TensorShape cell_shape(cell_size.width, cell_size.height);

    SimpleTensor<V> mag_cell(cell_shape, DataType::F32);
    SimpleTensor<V> phase_cell(cell_shape, DataType::F32);

    int cell_idx = 0;
    int y_offset = 0;

    // Traverse shape
    for(auto sy = cell_size.height; sy <= shape_height; sy += cell_size.height)
    {
        int x_offset = 0;
        for(auto sx = cell_size.width; sx <= shape_width; sx += cell_size.width)
        {
            int row_idx  = 0;
            int elem_idx = 0;

            // Traverse cell
            for(auto y = 0u; y < cell_size.height; ++y)
            {
                for(auto x = 0u; x < cell_size.width; ++x)
                {
                    int shape_idx        = x + row_idx + x_offset + y_offset;
                    mag_cell[elem_idx]   = mag[shape_idx];
                    phase_cell[elem_idx] = phase[shape_idx];
                    elem_idx++;
                }

                row_idx += shape_width;
            }

            // Partition magnitude values into bins based on phase values
            std::vector<V> bins(num_bins);
            hog_orientation_compute(mag_cell, phase_cell, bins, hog_info);

            for(size_t i = 0; i < num_bins; ++i)
            {
                hog_space[cell_idx * num_bins + i] = bins[i];
            }

            x_offset += cell_size.width;
            cell_idx++;
        }

        y_offset += (cell_size.height * shape_width);
    }
}

template <typename T>
void hog_block_normalization(SimpleTensor<T> &desc, const SimpleTensor<T> &hog_space, const HOGInfo &hog_info)
{
    const Size2D  cells_per_block        = hog_info.num_cells_per_block();
    const Size2D  cells_per_block_stride = hog_info.num_cells_per_block_stride();
    const Size2D &block_size             = hog_info.block_size();
    const Size2D &block_stride           = hog_info.block_stride();
    const size_t  num_bins               = hog_info.num_bins();

    const size_t shape_width          = hog_space.shape().x() * hog_info.cell_size().width;
    const size_t shape_height         = hog_space.shape().y() * hog_info.cell_size().height;
    const size_t num_bins_per_block_x = cells_per_block.width * num_bins;

    // Tensor representing single block
    SimpleTensor<T> block(TensorShape{ 1u, 1u }, DataType::F32, cells_per_block.area() * num_bins);

    uint32_t block_idx      = 0;
    int      block_y_offset = 0;

    // Traverse shape
    for(auto sy = block_size.height; sy <= shape_height; sy += block_stride.height)
    {
        int block_x_offset = 0;
        for(auto sx = block_size.width; sx <= shape_width; sx += block_stride.width)
        {
            int cell_y_offset = 0;
            int elem_idx      = 0;

            // Traverse block
            for(auto y = 0u; y < cells_per_block.height; ++y)
            {
                for(auto x = 0u; x < num_bins_per_block_x; ++x)
                {
                    int idx         = x + cell_y_offset + block_x_offset + block_y_offset;
                    block[elem_idx] = hog_space[idx];
                    elem_idx++;
                }

                cell_y_offset += hog_space.shape().x() * num_bins;
            }

            // Normalize block and write to descriptor
            hog_block_normalization_compute(block, desc, hog_info, block_idx);

            block_x_offset += cells_per_block_stride.width * num_bins;
            block_idx++;
        }

        block_y_offset += cells_per_block_stride.height * num_bins * hog_space.shape().x();
    }
}

template <typename T, typename U>
SimpleTensor<T> hog_descriptor(const SimpleTensor<U> &src, BorderMode border_mode, U constant_border_value, const HOGInfo &hog_info)
{
    SimpleTensor<int16_t> grad_x;
    SimpleTensor<int16_t> grad_y;

    // Create tensor info for HOG descriptor
    TensorInfo      desc_info(hog_info, src.shape().x(), src.shape().y());
    SimpleTensor<T> desc(desc_info.tensor_shape(), DataType::F32, desc_info.num_channels());

    // Create HOG space tensor (num_cells_x, num_cells_y)
    TensorShape hog_space_shape(src.shape().x() / hog_info.cell_size().width,
                                src.shape().y() / hog_info.cell_size().height);

    // For each cell a histogram with a num_bins is created
    TensorInfo      info_hog_space(hog_space_shape, hog_info.num_bins(), DataType::F32);
    SimpleTensor<T> hog_space(info_hog_space.tensor_shape(), DataType::F32, info_hog_space.num_channels());

    // Calculate derivative
    std::tie(grad_x, grad_y) = derivative<int16_t>(src, border_mode, constant_border_value, GradientDimension::GRAD_XY);

    // For each cell create histogram based on magnitude and phase
    hog_orientation_binning(magnitude(grad_x, grad_y, MagnitudeType::L2NORM),
                            phase(grad_x, grad_y, hog_info.phase_type()),
                            hog_space,
                            hog_info);

    // Normalize histograms based on block size
    hog_block_normalization(desc, hog_space, hog_info);

    return desc;
}

template void hog_orientation_binning(const SimpleTensor<int16_t> &mag, const SimpleTensor<uint8_t> &phase, SimpleTensor<float> &hog_space, const HOGInfo &hog_info);
template void hog_block_normalization(SimpleTensor<float> &desc, const SimpleTensor<float> &hog_space, const HOGInfo &hog_info);
template SimpleTensor<float> hog_descriptor(const SimpleTensor<uint8_t> &src, BorderMode border_mode, uint8_t constant_border_value, const HOGInfo &hog_info);
} // namespace reference
} // namespace validation
} // namespace test
} // namespace arm_compute
