<commit_before>/*

PICCANTE
The hottest HDR imaging library!
http://vcg.isti.cnr.it/piccante

Copyright (C) 2014
Visual Computing Laboratory - ISTI CNR
http://vcg.isti.cnr.it
First author: <NAME>

This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this
file, You can obtain one at http://mozilla.org/MPL/2.0/.

*/

#ifndef PIC_METRICS_SSIM_INDEX_HPP
#define PIC_METRICS_SSIM_INDEX_HPP

#include <math.h>

#include "../base.hpp"
#include "../image.hpp"
#include "../metrics/base.hpp"

#include "../util/indexed_array.hpp"
#include "../util/array.hpp"
#include "../util/std_util.hpp"

#include "../filtering/filter_luminance.hpp"
#include "../filtering/filter_gaussian_2d.hpp"
#include "../filtering/filter_downsampler_2d.hpp"
#include "../filtering/filter_ssim.hpp"

namespace pic {

class SSIMIndex
{
public:
    float K0, K1, sigma_window, dynamic_range;
    bool bDownsampling;

    FilterLuminance flt_lum;
    FilterGaussian2D flt_gauss2D;
    FilterSSIM flt_ssim;

    SSIMIndex()
    {
        update(0.01f, 0.03f, 1.5f, -1.0f, true);
    }

    /**
     * @brief update
     * @param K0
     * @param K1
     * @param sigma_window
     * @param dynamic_range
     * @param bDownsampling
     */
    void update(float K0 = 0.01f, float  K1 = 0.03f, float  sigma_window = 1.5f, float dynamic_range = -1.0f, bool bDownsampling = true)
    {
        this->K0 = K0;
        this->K1 = K1;
        this->sigma_window = sigma_window;
        this->dynamic_range = dynamic_range;
        this->bDownsampling = bDownsampling;

        flt_gauss2D.update(sigma_window);
    }

    /**
     * @brief getDynamicRange
     * @param img
     * @return
     */
    static float getDynamicRange(Image *img)
    {
        float ret = -1.0f;

        if(img == NULL) {
            return ret;
        }

        if(!img->isValid()) {
            return ret;
        }

        float *min_val_v = img->getMinVal(NULL, NULL);
        float *max_val_v = img->getMaxVal(NULL, NULL);

        int ind;
        float min_val = Arrayf::getMin(min_val_v, img->channels, ind);
        float max_val = Arrayf::getMax(max_val_v, img->channels, ind);

        if(min_val <= 0.0f) {
            IntCoord coord;
            IndexedArray::findSimple(img->data, img->size(), IndexedArray::bFuncNotNeg, coord);
            min_val = IndexedArray::min(img->data, coord);

            if(min_val <= 0.0f) {
                min_val = 1.0f / 255.0f;
            }

            if(max_val > min_val) {
                ret = max_val / min_val;
            } else {
                ret = min_val / max_val;
            }

            return ret;
        }

        if(min_val_v != NULL) {
            delete[] min_val_v;
        }

        if(max_val_v != NULL) {
            delete[] max_val_v;
        }

        return ret;
    }

    /**
     * @brief execute
     * @param ori
     * @param cmp
     */
    Image *execute(ImageVec imgIn, float &ssim_index, Image *ssim_map = NULL)
    {
        ssim_index = -1.0f;

        bool bCheckInput = ImageVecCheck(imgIn, 2) && ImageVecCheckSimilarType(imgIn);

        if(!bCheckInput) {
            return ssim_map;
        }

        Image *ori = imgIn[0];
        Image *cmp = imgIn[1];

        Image *ori_d = NULL;
        Image *cmp_d = NULL;

        bool bAllocated = false;
        if(bDownsampling) {
            float f = MAX(1.0f, lround(MIN(ori->widthf, ori->heightf) / 256.0f));

            #ifdef PIC_DEBUG
                printf("\nDownsampling factor: %f\n", f);
            #endif

            if(f > 1.0f) {
                ori_d = FilterDownSampler2D::execute(ori, NULL, 1.0f / f);
                cmp_d = FilterDownSampler2D::execute(cmp, NULL, 1.0f / f);

                ori = ori_d;
                cmp = cmp_d;

                bAllocated = true;
            }
        }

        Image *L_ori = flt_lum.Process(Single(ori), NULL);
        Image *L_cmp = flt_lum.Process(Single(cmp), NULL);


        if(dynamic_range <= 0.0f) {
            dynamic_range = getDynamicRange(L_ori);
        }

        float C0 = K0 * dynamic_range;
        C0 = C0 * C0;
<commit_msg>Update ssim_index.hpp<commit_after>/*

PICCANTE
The hottest HDR imaging library!
http://vcg.isti.cnr.it/piccante

Copyright (C) 2014
Visual Computing Laboratory - ISTI CNR
http://vcg.isti.cnr.it
First author: <NAME>

This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this
file, You can obtain one at http://mozilla.org/MPL/2.0/.

*/

#ifndef PIC_METRICS_SSIM_INDEX_HPP
#define PIC_METRICS_SSIM_INDEX_HPP

#include <math.h>

#include "../base.hpp"
#include "../image.hpp"
#include "../metrics/base.hpp"

#include "../util/indexed_array.hpp"
#include "../util/array.hpp"
#include "../util/std_util.hpp"

#include "../filtering/filter_luminance.hpp"
#include "../filtering/filter_gaussian_2d.hpp"
#include "../filtering/filter_downsampler_2d.hpp"
#include "../filtering/filter_ssim.hpp"

namespace pic {

class SSIMIndex
{
public:
    float K0, K1, sigma_window, dynamic_range;
    bool bDownsampling;

    FilterLuminance flt_lum;
    FilterGaussian2D flt_gauss2D;
    FilterSSIM flt_ssim;

    SSIMIndex()
    {
        update(0.01f, 0.03f, 1.5f, -1.0f, true);
    }

    /**
     * @brief update
     * @param K0
     * @param K1
     * @param sigma_window
     * @param dynamic_range
     * @param bDownsampling
     */
    void update(float K0 = 0.01f, float  K1 = 0.03f, float  sigma_window = 1.5f, float dynamic_range = -1.0f, bool bDownsampling = true)
    {
        this->K0 = K0;
        this->K1 = K1;
        this->sigma_window = sigma_window;
        this->dynamic_range = dynamic_range;
        this->bDownsampling = bDownsampling;

        flt_gauss2D.update(sigma_window);
    }

    /**
     * @brief getDynamicRange
     * @param img
     * @return
     */
    static float getDynamicRange(Image *img)
    {
        float ret = -1.0f;

        if(img == NULL) {
            return ret;
        }

        if(!img->isValid()) {
            return ret;
        }

        float *min_val_v = img->getMinVal(NULL, NULL);
        float *max_val_v = img->getMaxVal(NULL, NULL);

        int ind;
        float min_val = Arrayf::getMin(min_val_v, img->channels, ind);
        float max_val = Arrayf::getMax(max_val_v, img->channels, ind);

        if(min_val <= 0.0f) {
            IntCoord coord;
            IndexedArray::findSimple(img->data, img->size(), IndexedArray::bFuncNotNeg, coord);
            min_val = IndexedArray::min(img->data, coord);

            if(min_val <= 0.0f) {
                min_val = 1.0f / 255.0f;
            }

            if(max_val > min_val) {
                ret = max_val / min_val;
            } else {
                ret = min_val / max_val;
            }

            return ret;
        }

        if(min_val_v != NULL) {
            delete[] min_val_v;
        }

        if(max_val_v != NULL) {
            delete[] max_val_v;
        }

        return ret;
    }

    /**
     * @brief execute
     * @param ori
     * @param cmp
     */
    Image *execute(ImageVec imgIn, float &ssim_index, Image *ssim_map = NULL)
    {
        ssim_index = -1.0f;

        bool bCheckInput = ImageVecCheck(imgIn, 2) && ImageVecCheckSimilarType(imgIn);

        if(!bCheckInput) {
            return ssim_map;
        }

        Image *ori = imgIn[0];
        Image *cmp = imgIn[1];

        Image *ori_d = NULL;
        Image *cmp_d = NULL;

        bool bAllocated = false;
        if(bDownsampling) {
            float f = MAX(1.0f, lround(MIN(ori->widthf, ori->heightf) / 256.0f));

            #ifdef PIC_DEBUG
                printf("\nDownsampling factor: %f\n", f);
            #endif

            if(f > 1.0f) {
                ori_d = FilterDownSampler2D::execute(ori, NULL, 1.0f / f);
                cmp_d = FilterDownSampler2D::execute(cmp, NULL, 1.0f / f);

                ori = ori_d;
                cmp = cmp_d;

                bAllocated = true;
            }
        }

        Image *L_ori = flt_lum.Process(Single(ori), NULL);
        Image *L_cmp = flt_lum.Process(Single(cmp), NULL);

        if(dynamic_range <= 0.0f) {
            dynamic_range = getDynamicRange(L_ori);
        }

        float C0 = K0 * dynamic_range;
        C0 = C0 * C0;

{'fraction_non_alphanumeric': 0.12432819777857398, 'fraction_numerical': 0.01934790397706915, 'mean_word_length': 1.8796423658872077, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 41, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4798599', 'n_tokens_mistral': 3050, 'n_tokens_neox': 2854, 'n_words': 619}