我正在尝试将一个数字范围转换为另一个数字,保持比率.数学不是我的强项.
我有一个图像文件,其中点值可能在-16000.00到16000.00之间,尽管典型范围可能要小得多.我想要做的是将这些值压缩到整数范围0-100,其中0是最小点的值,100是最大值的值.中间的所有点都应该保持相对比率,即使丢失了一些精度我想在python中这样做,但即使是一般算法也应该足够.我宁愿一个算法,其中最小/最大或任一范围可被调整(即,在第二范围可以是-50℃至800,而不是0到100).
jer*_*jvl 476
NewValue = (((OldValue - OldMin) * (NewMax - NewMin)) / (OldMax - OldMin)) + NewMin
Run Code Online (Sandbox Code Playgroud)
或者更具可读性:
OldRange = (OldMax - OldMin)
NewRange = (NewMax - NewMin)
NewValue = (((OldValue - OldMin) * NewRange) / OldRange) + NewMin
Run Code Online (Sandbox Code Playgroud)
或者,如果要保护旧范围为0(OldMin = OldMax)的情况:
OldRange = (OldMax - OldMin)
if (OldRange == 0)
NewValue = NewMin
else
{
NewRange = (NewMax - NewMin)
NewValue = (((OldValue - OldMin) * NewRange) / OldRange) + NewMin
}
Run Code Online (Sandbox Code Playgroud)
请注意,在这种情况下,我们不得不随意选择一个可能的新范围值.根据上下文,明智的选择可能是:NewMin(见样本),NewMax或(NewMin + NewMax) / 2
cle*_*tus 59
这是一个简单的线性转换.
new_value = ( (old_value - old_min) / (old_max - old_min) ) * (new_max - new_min) + new_min
Run Code Online (Sandbox Code Playgroud)
因此,在-16000到16000的范围内将10000转换为0到100的新范围,可以得到:
old_value = 10000
old_min = -16000
old_max = 16000
new_min = 0
new_max = 100
new_value = ( ( 10000 - -16000 ) / (16000 - -16000) ) * (100 - 0) + 0
= 81.25
Run Code Online (Sandbox Code Playgroud)
小智 20
实际上有些情况下上面的答案会破裂.如错误的输入值,错误的输入范围,负输入/输出范围.
def remap( x, oMin, oMax, nMin, nMax ):
#range check
if oMin == oMax:
print "Warning: Zero input range"
return None
if nMin == nMax:
print "Warning: Zero output range"
return None
#check reversed input range
reverseInput = False
oldMin = min( oMin, oMax )
oldMax = max( oMin, oMax )
if not oldMin == oMin:
reverseInput = True
#check reversed output range
reverseOutput = False
newMin = min( nMin, nMax )
newMax = max( nMin, nMax )
if not newMin == nMin :
reverseOutput = True
portion = (x-oldMin)*(newMax-newMin)/(oldMax-oldMin)
if reverseInput:
portion = (oldMax-x)*(newMax-newMin)/(oldMax-oldMin)
result = portion + newMin
if reverseOutput:
result = newMax - portion
return result
#test cases
print remap( 25.0, 0.0, 100.0, 1.0, -1.0 ), "==", 0.5
print remap( 25.0, 100.0, -100.0, -1.0, 1.0 ), "==", -0.25
print remap( -125.0, -100.0, -200.0, 1.0, -1.0 ), "==", 0.5
print remap( -125.0, -200.0, -100.0, -1.0, 1.0 ), "==", 0.5
#even when value is out of bound
print remap( -20.0, 0.0, 100.0, 0.0, 1.0 ), "==", -0.2
Run Code Online (Sandbox Code Playgroud)
有一个条件,当您检查的所有值都相同时,@ jerryjvl的代码将返回NaN.
if (OldMin != OldMax && NewMin != NewMax):
return (((OldValue - OldMin) * (NewMax - NewMin)) / (OldMax - OldMin)) + NewMin
else:
return (NewMax + NewMin) / 2
Run Code Online (Sandbox Code Playgroud)
我没有为此挖掘BNF,但是 Arduino 文档有一个很好的功能示例,并且它是细分的。我可以通过简单地添加一个 def 重命名来重新映射(因为 map 是内置的)并删除类型转换和花括号(即只删除所有的“long”),从而在 Python 中使用它。
原来的
long map(long x, long in_min, long in_max, long out_min, long out_max)
{
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}
Run Code Online (Sandbox Code Playgroud)
Python
def remap(x, in_min, in_max, out_min, out_max):
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min
Run Code Online (Sandbox Code Playgroud)
https://www.arduino.cc/en/reference/map
这里有一些简短的 Python 函数,可让您轻松复制和粘贴,包括缩放整个列表的函数。
def scale_number(unscaled, to_min, to_max, from_min, from_max):
return (to_max-to_min)*(unscaled-from_min)/(from_max-from_min)+to_min
def scale_list(l, to_min, to_max):
return [scale_number(i, to_min, to_max, min(l), max(l)) for i in l]
Run Code Online (Sandbox Code Playgroud)
可以这样使用:
scale_list([1,3,4,5], 0, 100)
Run Code Online (Sandbox Code Playgroud)
[0.0, 50.0, 75.0, 100.0]
就我而言,我想缩放对数曲线,如下所示:
scale_list([math.log(i+1) for i in range(5)], 0, 50)
Run Code Online (Sandbox Code Playgroud)
[0.0, 21.533827903669653, 34.130309724299266, 43.06765580733931, 50.0]
使用Numpy和interp功能,您可以将值从旧范围转换为新范围:
>>> import numpy as np
>>> np.interp(0, [-16000,16000], [0,100])
50.0
Run Code Online (Sandbox Code Playgroud)
您还可以尝试它来映射值列表:
>>> np.interp([-16000,0,12000] ,[-16000,16000], [0,100])
array([ 0. , 50. , 87.5])
Run Code Online (Sandbox Code Playgroud)
考虑我们的范围在(OMin, Omax)之间,并且我们有一个在此范围内的值X
我们想将其转换为比例 (NMin,NMax)
我们知道 X,我们需要找到 Y,比率必须相同:
=> (Y-NMin)/(NMax-NMin) = (X-OMin)/(OMax-OMin)
=> (Y-NMin)/NewRange = (X-OMin)/OldRange
=> Y = ((X-OMin)*NewRange)/oldRange)+NMin Answer
Run Code Online (Sandbox Code Playgroud)
实际上我们可以这样写这个方程:
private fun convertScale(oldValueToConvert:Int): Float {
// Old Scale 50-100
val oldScaleMin = 50
val oldScaleMax = 100
val oldScaleRange= (oldScaleMax - oldScaleMin)
//new Scale 0-1
val newScaleMin = 0.0f
val newScaleMax = 1.0f
val newScaleRange= (newScaleMax - newScaleMin)
return ((oldValueToConvert - oldScaleMin)* newScaleRange/ oldScaleRange) + newScaleMin
}
Run Code Online (Sandbox Code Playgroud)
爪哇
/**
*
* @param x
* @param inMin
* @param inMax
* @param outMin
* @param outMax
* @return
*/
private long normalize(long x, long inMin, long inMax, long outMin, long outMax) {
long outRange = outMax - outMin;
long inRange = inMax - inMin;
return (x - inMin) *outRange / inRange + outMin;
}
Run Code Online (Sandbox Code Playgroud)
用法:
float brightness = normalize(progress, 0, 10, 0,255);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
172378 次 |
| 最近记录: |