5

I have a list of doubles in the range of anywhere between -1.396655 to 1.74707 could even be higher or lower, either way I would know what the Min and Max value is before normalizing. My question is How can I normalize these values between -1 to 1 or even better yet convert them from double values to char values of 0 to 255

Any help would be appreciated.

double range = (double)(max - min);
value = 255 * (value - min)/range
Elgoog
  • 2,205
  • 7
  • 36
  • 48
  • 2
    You may find [How to normalize a list of int values](http://stackoverflow.com/q/1226587/1048330) helpful. – tenorsax Apr 29 '12 at 22:49
  • 3
    Sorry i am a noob and I need help every now and then :( my first down votes... Makes me feel rubbish. Sometimes when your trying to work something out, you search high and low and cant find anything or if you do you just cant grasp it, so I think of this great community and I know that someone friendly will try and help / make me understand. – Elgoog Apr 29 '12 at 22:49

4 Answers4

5

You need a mapping of the form y = mx + c, and you need to find an m and a c. You have two fixed data-points, i.e.:

 1 = m * max + c
-1 = m * min + c

From there, it's simple algebra.

Oliver Charlesworth
  • 267,707
  • 33
  • 569
  • 680
4

The easiest thing is to first shift all the values so that min is 0, by subtracting Min from each number. Then multiply by 255/(Max-Min), so that the shifted Max will get mapped to 255, and everything else will scale linearly. So I believe your equation would look like this:

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

You may want to round a bit more carefully before casting to char.

happydave
  • 7,127
  • 1
  • 26
  • 25
2

There are two changes to be made.

First, use 256 as the limit.

Second, make sure your range is scaled back slightly to avoid getting 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);
    }

With these two changes, you will get the correct distribution in your output.

Sean Vikoren
  • 1,084
  • 1
  • 13
  • 24
0

I solved this need when I dived into doing some convolution stuff using C++.

Hopefully my code can have you a useful reference :)

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;
}

Basically output (calley receives by 'dst') is around [0, 255].

Mou
  • 145
  • 1
  • 6
  • I would recommend to not using this sollution, becase it has big complexity - two double for loops. For professional sollutions you should consider vectorized sollution. – 404pio Apr 06 '22 at 09:41