How do I normalize an image? - math

If I have a series of pixels, which range from say -500 to +1000, how would I normalize all the pixels on the same gradient so that they fall between a specific range, say 0 and 255?

Some pseudocode like this would scale values linearly from one range to another
oldmin=-500
oldmax=1000
oldrange=oldmax-oldmin;
newmin=0
newmax=255;
newrange=newmax-newmin;
foreach(oldvalue)
{
//where in the old scale is this value (0...1)
scale=(oldvalue-oldmin)/oldrange;
//place this scale in the new range
newvalue=(newrange*scale)+newmin
}

Your question isn't very clear so I'm going to assume that you're doing some kind of image processing and the results you get are values from -500 to 1000 and now you need to save the color to a file where every value needs to be between 0 and 255.
How you do this is really very dependent in the application, what is really the meaning of the results and what exactly you want to do. The two main options are:
clamp the values - anything under 0 you replace by 0 and anything above 255 you replace by 255. You'll want to do this, for instance, if your image processing is some kind of interpolation which really shouldn't reach these values
Linear normalization - linearly may your minimal value to 0 and your maximal value to 255. Of course you'll first need to find the minimum and maximum. You do:
v = (origv - min)/(max - min) * 255.0
What this does is first map the values to [0,1] and then stretch them back to [0,255].
A third option is to mix and match between these two options. Your application might demand that you treat negative values as unneeded values and clamp them to 0 and positive values to linearly map to [0,255].

First make it all positive. If the minimum is -500 then add 500 to all values. Then the minimum would be 0, and the maximum would be 1500.
Then it is just a rule of three and you have it:
[value in 0,255] = 255*(Pixel/1500)

Some pseudo code may help:
foreach( pixel_value in pixel_values): # between -500 and 1000
position = (pixel_value + 500) / 1500 # gives you a 0 to 1 decimal
new_value = int(postion * 255) # or instead of casting, you could round it off
That's python code by the way.

Create two variables, MinInputValue and MaxInputValue. Initialize MinInputValue to a very large positive number (higher than the largest pixel value you ever expect to see) and MaxInputValue to a very large negative number (lower than the lowest pixel value you ever expect to see).
Loop over every pixel in the image. For each pixel, if the pixel value PixelValue is lower than MinInputValue, set MinInputValue to PixelValue. If the pixel value is higher than MaxInputValue, set MaxInputValue to PixelValue.
Create a new variable, InputValueRange, and set it to MaxInputValue - MinInputValue.
Once this is done, loop over every pixel in the image again. For each pixel PixelValue, calculate the output pixel value as 255.0 * (PixelValue - MinInputValue) / InputValueRange. You can assign this new value back to the original PixelValue, or you can set the corresponding pixel in an output image of the same size.

Related

Math calculation formula

I'm trying to get to a formula that gives me a number inside a range, from a increment-able number x that i'm giving to it.
Sure that this can be easily done with a program, inside a loop, but i want to know if is possible to archive this just by make a calculation.
For example, in this case the range is from 10-50, and if x = 10 (number to increment) and the actual position of it is 40, for example, in this case the value will be 50. Now if i give a value x of 15 i want it to give me 15, since the value 50 has been reached and the sum as to restart from 10.
Is there a solution for this case?
Thanks.

Octave: Values inside a matrix that are close

I have a vector that is being filled with random numbers within this range [0,1]. I want to somehow accept only the vectors, in which an element inside of it has a maximum deviation of 0,02 from its previous one and its next one.
For example I have the below vector [3,1]. This is acceptable, because the deviation of the 2nd element, between the first and the third element is not bigger than 0,02. Vector is not always consisted of 3 rows, it could be more.
**Vector**
0.32957
0.33097
0.33946
This is what i thought:
n=4
P=rand(1,n);
sort(P,"ascend");
for L=2:n
while P(L-1)-P(L)>0.02
P=rand(1,n);
endwhile
endfor
Vectorize this!
isvalid=~any(diff(sort(a))>0.02);
sort(a) : if its not sorted, sort
diff() : take the difference between adjacent elements
___ >0.02: Check if any of those differences is bigger than what you accept
~any(): if any is bigger, then return zero, "not valid".
From your code, it seems that there may be more to the question than what you ask, you seem to have the XY problem. You want to create a random vector that has the properties that you describe. You seem to be using uniform random numbers, so let me propose a way to generate your vector where your conditions are always true.
a(1)=rand(1); %or any other way to generate a first value.
length=100; %desired length.
a(2:length)=rand(length-1,1)*0.02; %generate random numbers never bigger than 0.02
a=cumsum(a); %cumulative sum
This ensures the vector is increasing in value, and never increasing more than 0.02

Convert a vector(x,y,z) coordinate into an integer between 0 and 32767

Pretty simple question - can someone provide a formula that takes 3 numbers (x,y,z) and converts them into a single integer between 0 and 32767.
1,1,2 and 2,1,1 shouldn't be the same resulting value (simply adding the numbers up isn't what I want) but compressing an infinite number of x,y,z into a small range of numbers obviously will get the same values back quite often.
The formula also needs to work on large numbers like 5000,5000,1000
If you need to go between 0 and 131068 that would be fine, but it shouldn't be much more than that.
One solution I can think of is to take each x,y,z and assign them each to a range of 5 bits in the 2^15 possible values in [0, 32767]. One way of doing this is taking each x,y,z modulo 2^5 (to compress them into the requisite 5 bits) and then set the bits of the result accordingly. The end result should look something like
def compress(x,y,z):
x %= 32
y %= 32
z %= 32
return x + (y<<5) + (z<<10)
print (compress(5000,5000,1000))
>>> 8456
Obviously this approach has colliding outputs very often (whenever x, y or z are the same modulo 32), but as you said this is pretty unavoidable.

How can I modify this (simple) equation to produce my desired result?

I have a database of 817 items, each given a "rank" of 1 to 817 (the smaller the number, the "better" the item). This rank is based off of many factors that indicate quality.
Now, I need to assign a "value" to these items, with the item at rank 1 being valued the most, and the value decreasing with rank (non-linear).
The easiest first attempt was to simply choose an arbitrary base (100,000) and divide by the rank:
$value = 100000 / $rank;
/**
* Rank : Value
* 1 : 100,000
* 2 : 50,000
* 3 : 33,333
* etc.
*/
This produces exponential decay, as shown in the red line in this image:
However, I wish to value these items in a manner that looks more like the blue line above. How can I change my formula to achieve this?
Try 1/sqrt(x) (i.e, pow(x, -1/2)) for starters. If that's still not slow enough, try a smaller fractional power.
Why don't you go with linear?
value = n - rank
where n is the count of your items, i.e. 817.
I haven't tried but use exponent instead of dividing by 1000 of a base 2.
UPDATES
value = 2 pow (n-rank)

Maths Range To Percentage

i need a bit of help with some maths.
I have a range 0 - 127 and i want to convert it into percentage.
So 0% = 0 and 100% = 127 and every number inbetween.
How would i do this?
Edit:
Thanks to what jon posted, i came up with:
$percent * 127 / 100
While Jon's answer was not incorrect, the answer given by belisarius was more complete, in that it allowed for a range of numbers beginning and ending with any number, and not necessarily starting with 0.
Here's a little better way to represent the formula:
percentage = (value - min) / (max - min)
If you want to represent the percentage as a whole number instead of a decimal, simply multiply the result by 100.
And here's the reverse (going from a percentage to a value):
value = ((max - min) * percentage) + min
The percentage here is a decimal. If your percentage is a whole number, simply divide it by 100 before inserting in this formula.
Generally, if you have numbers in the interval [a,b], to get the percentage inside your interval, the formula is:
percentage = 100 * (x-a) / (b-a)
Where x is your value
If you want to go from a value to a percentage, eg from 63.5 to 50%, divide your value by 127 & multiply by 100.
If you want to go the other way, eg from 50% to 63.5, it's the reverse: divide your percentage by 100 & multiply by 127.

Resources