我正在尝试将一个数字范围转换为另一个数字,保持比率.数学不是我的强项.
我有一个图像文件,其中点值可能在-16000.00到16000.00之间,尽管典型范围可能要小得多.我想要做的是将这些值压缩到整数范围0-100,其中0是最小点的值,100是最大值的值.中间的所有点都应该保持相对比率,即使丢失了一些精度我想在python中这样做,但即使是一般算法也应该足够.我宁愿一个算法,其中最小/最大或任一范围可被调整(即,在第二范围可以是-50℃至800,而不是0到100).
jer*_*jvl 476
NewValue = (((OldValue - OldMin) * (NewMax - NewMin)) / (OldMax - OldMin)) + NewMin
或者更具可读性:
OldRange = (OldMax - OldMin)  
NewRange = (NewMax - NewMin)  
NewValue = (((OldValue - OldMin) * NewRange) / OldRange) + NewMin
或者,如果要保护旧范围为0(OldMin = OldMax)的情况:
OldRange = (OldMax - OldMin)
if (OldRange == 0)
    NewValue = NewMin
else
{
    NewRange = (NewMax - NewMin)  
    NewValue = (((OldValue - OldMin) * NewRange) / OldRange) + NewMin
}
请注意,在这种情况下,我们不得不随意选择一个可能的新范围值.根据上下文,明智的选择可能是:NewMin(见样本),NewMax或(NewMin + NewMax) / 2
cle*_*tus 59
这是一个简单的线性转换.
new_value = ( (old_value - old_min) / (old_max - old_min) ) * (new_max - new_min) + new_min
因此,在-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
小智 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
有一个条件,当您检查的所有值都相同时,@ jerryjvl的代码将返回NaN.
if (OldMin != OldMax && NewMin != NewMax):
    return (((OldValue - OldMin) * (NewMax - NewMin)) / (OldMax - OldMin)) + NewMin
else:
    return (NewMax + NewMin) / 2
我没有为此挖掘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;
}
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
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]
可以这样使用:
scale_list([1,3,4,5], 0, 100)
[0.0, 50.0, 75.0, 100.0]
就我而言,我想缩放对数曲线,如下所示:
scale_list([math.log(i+1) for i in range(5)], 0, 50)
[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
您还可以尝试它来映射值列表:
>>> np.interp([-16000,0,12000] ,[-16000,16000], [0,100])
array([ 0. , 50. , 87.5])
考虑我们的范围在(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
   
实际上我们可以这样写这个方程:
 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
    }
爪哇
/**
     * 
     * @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;
        }
用法:
float brightness = normalize(progress, 0, 10, 0,255);