Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 745
Muhammad Omer Avatar asked Oct 10 '13 14:10

Muhammad Omer


2 Answers

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 )

like image 134
Jordi Cruzado Avatar answered Nov 02 '22 22:11

Jordi Cruzado


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.        ]]])
like image 43
Koyadovic Avatar answered Nov 02 '22 22:11

Koyadovic