将一列双精度浮点数归一化到范围为-1至1或0至255。

5
我有一组double值,它们的范围在-1.396655到1.74707之间,甚至可能更高或更低。在归一化之前,我想知道这些值的最小值和最大值。我的问题是:如何将这些值归一化为-1到1或者更好地将它们从double值转换为0到255的char值?
任何帮助都将不胜感激。
double range = (double)(max - min);
value = 255 * (value - min)/range

2
您可能会发现如何对一个整数列表进行规范化很有帮助。 - tenorsax
3
抱歉,我是个新手,有时需要帮助:(第一次被踩让我感觉很糟糕。有时候当您尝试解决问题时,您会四处搜索却找不到任何答案,或者即使找到了也无法理解。因此,我想到这个伟大的社区,知道会有友好的人试着帮助/让我理解。 - Elgoog
4个回答

5
你需要一个形如y = mx + c映射,并且需要找到mc。你有两个固定的数据点,即:
 1 = m * max + c
-1 = m * min + c

从那里开始,就是简单的代数


5

最简单的方法是将所有值都向左移,使最小值为0,即从每个数字中减去最小值。然后乘以255/(Max-Min),使移到的最大值被映射到255,并且其他所有值都按线性比例缩放。因此,我认为你的方程应该是这样的:

newval = (unsigned char) ((oldval - Min)*(255/(Max-Min)))

在强制转换成字符之前,您可能需要更仔细地四舍五入一下。


2

需要进行两项更改。

首先,将256作为限制。

其次,确保范围稍微缩小以避免获取256。

    public int GetRangedValue(double value, double min, double max)
    {
        int outputLimit = 256;

        double range = (max - min) - double.Epsilon; // Here we shorten the range slightly

        // Then we build a range such that value >= 0 and value < 1
        double rangedValue = (value - min) / range;

        return min + (int)(outputLimit * rangedValue);
    }

通过这两个改变,你将在输出中得到正确的分布。

0

当我开始使用C++进行一些卷积操作时,我解决了这个需求。

希望我的代码能为您提供有用的参考 :)

bool normalize(uint8_t*& dst, double* src, int width, int height) {
    dst = new uint8_t[sizeof(uint8_t)*width*height];
    if (dst == NULL)
        return false;
    memset(dst, 0, sizeof(uint8_t)*width*height);
    double max   = std::numeric_limits<double>::min();
    double min   = std::numeric_limits<double>::max();
    double range = std::numeric_limits<double>::max();
    double norm  = 0.0;
    //find the boundary
    for (int j=0; j<height; j++) {
        for (int i=0; i<width; i++) {
            if (src[i+j*width] > max) 
                max = src[i+j*width];
            else if (src[i+j*width] < min)
                min = src[i+j*width];
        }
    }
    //normalize double matrix to be an uint8_t matrix
    range = max - min;
    for (int j=0; j<height; j++) {
        for (int i=0; i<width; i++) {
            norm = src[i+j*width];
            norm = 255.0*(norm-min)/range;
            dst[i+j*width] = (uint8_t)norm;
        }
    }
    return true;
}

基本上输出(由“dst”接收)在[0,255]左右。


我建议不要使用这个解决方案,因为它具有很大的复杂性——两个双重循环。对于专业的解决方案,您应该考虑矢量化的解决方案。 - 404pio

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接