Muhammad Omer
Muhammad Omer

Reputation: 553

Normalize a vector of 3d coordinates to be in between 0 and 1

I have a huge vector of 3D coordinates and i want to normalize them so that they lie inside a cube of dimension [0,1] x [0,1] x [0,1] (i.e, each x,y,z of the coordinate should be between 0 and 1), what i am doing is dividing all the coordinates by the max length of the 3D coordinate in this vector but in this way i cant handle the coordinates with negative values. Can anyone suggest what would be the proper way to normalize these coordinates?

Upvotes: 7

Views: 24377

Answers (2)

Koyadovic
Koyadovic

Reputation: 51

As a example we define a matrix called v:

import numpy as np

v = np.array([[[-1,2,3], [4,5,6]]])
v
array([[[-1,  2,  3],
        [ 4,  5,  6]]])

And also a range:

new_range = (0, 1)
max_range = max(new_range)
min_range = min(new_range)

The first thing I do here is to see what is the current range of numbers between the minimum and the maximum. Since we want the minimum to be 0.0 and the maximum 1.0, we must divide the range (1.0 - 0.0, maximum minus the minimum), that is 1.0, between the old range of numbers.

scaled_unit = 1.0 / (np.max(v) - np.min(v))

Or generally (using the range new_range described above):

scaled_unit = (max_range - min_range) / (np.max(v) - np.min(v))

With this division one achieves what will be considered the new unit.

To convert each old value into the new one, we multiply it by the scaled unit and subtract the minimum value multiplied by the scaled unit again. Then we sum min_range:

v*scaled_unit - np.min(v)*scaled_unit + min_range
array([[[0.        , 0.42857143, 0.57142857],
        [0.71428571, 0.85714286, 1.        ]]])

Then we get all values to keep their proportions between them and yet be contained between 0.0 for the minimum value and 1.0 for the maximum. This also can be used to scale to whatever range we need.

For example:

v = np.array([[[-1,2,3], [4,5,6]]])

def scale_numpy_array(arr, min_v, max_v):
    new_range = (min_v, max_v)
    max_range = max(new_range)
    min_range = min(new_range)
    scaled_unit = (max_range - min_range) / (np.max(arr) - np.min(arr))
    return arr*scaled_unit - np.min(arr)*scaled_unit + min_range


scale_numpy_array(v, -1, 1)
array([[[-1.        , -0.14285714,  0.14285714],
        [ 0.42857143,  0.71428571,  1.        ]]])


scale_numpy_array(v, -10, -1)
array([[[-10.        ,  -6.14285714,  -4.85714286],
        [ -3.57142857,  -2.28571429,  -1.        ]]])

Upvotes: 3

Jordi Cruzado
Jordi Cruzado

Reputation: 885

just divide each component by the length of the vector:

length = sqrt( x^2 + y^2 + z^2 )

so your normalized vector is:

v = ( x / length, y / length, z / length )

Upvotes: 15

Related Questions