pátek 20. března 2026

Lineární interpolace

 


Lineární transformace je 
proces, kterému se často říká lineární interpolace nebo "mapování rozsahu" (range mapping).

Tento postup vezme tvou hodnotu z jednoho "světa" (původní rozsah) a proporcionálně ji umístí do "světa" druhého (nový rozsah).

Obecný vzorec pro přepočet

Představme si, že máš hodnotu $x$ v rozsahu $[A, B]$ a chceš ji převést na hodnotu y v rozsahu [C, D]. Vzorec vypadá následovně:

y = C + (x - A) \cdot \frac{D - C}{B - A}

Rozklad vzorce (proč to funguje):

  1. (x - A): Hodnotu nejdříve "vynuluješ". Pokud je tvá spodní hranice 50 a ty máš 60, zbyde ti 10 (vzdálenost od startu).

  2. \frac{D - C}{B - A}: Toto je poměr (škálovací faktor). Říká ti, kolik jednotek nového rozsahu připadá na jednu jednotku starého rozsahu.

  3. + C$: Nakonec výsledek posuneš o počáteční bod nového rozsahu, aby nezačínal od nuly, ale tam, kde potřebuješ.


Výpočet pro příklad:

Předpokládejme, že tvá hodnota 80 je z původního rozsahu 0 až 100 (nejčastější případ, např. procenta) a chceš ji převést do rozsahu 10 až 100.

  • x = 80

  • Původní rozsah: A = 0, B = 100

  • Nový rozsah: C = 10, D = 100

Dosazení:

y = 10 + (80 - 0) \cdot \frac{100 - 10}{100 - 0}
y = 10 + 80 \cdot \frac{90}{100}
y = 10 + 80 \cdot 0,9
y = 10 + 72 = \mathbf{82}

Tvá hodnota 80 v novém měřítku odpovídá číslu 82.

Praktické využití

Tento vzorec je "denním chlebem" programátorů (např. mapování polohy kurzoru na velikost zvuku) nebo inženýrů při kalibraci senzorů.

Tip: Pokud bys převáděl hodnotu do rozsahu 0 až 1, mluvíme o normalizaci.

V Pythonu máš několik možností, jak to vyřešit. Protože se tento výpočet používá v různých oborech, najdeš ho v knihovnách pro matematiku, grafy i strojové učení.

Tady jsou 3 nejčastější způsoby, jak to udělat:


1. NumPy: np.interp (Standard pro vědce)

Knihovna NumPy je v Pythonu základem pro veškerou matematiku. Má funkci interp, která přesně implementuje lineární interpolaci.

Python
import numpy as np

hodnota = 80
stary_rozsah = [0, 100]
novy_rozsah = [10, 100]

# Syntaxe: np.interp(hodnota, [původní_min, původní_max], [nový_min, nový_max])
vysledek = np.interp(hodnota, stary_rozsah, novy_rozsah)

print(vysledek)  # Výstup: 82.0

Výhoda: Funguje bleskově i na celé seznamy (pole) čísel najednou.


2. Jednoduchá vlastní funkce (Bez knihoven)

Pokud nechceš instalovat NumPy (který je docela "těžký"), stačí ti tato jedna řádka kódu. Je to přesně ten vzorec, který jsme si ukázali:

Python
def map_range(x, in_min, in_max, out_min, out_max):
    return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min

print(map_range(80, 0, 100, 10, 100)) # Výstup: 82.0

3. Scikit-learn: MinMaxScaler (Pro data science)

Pokud pracuješ s velkými tabulkami dat a chceš je "napasovat" do určitého rozsahu (často 0 až 1), používá se třída MinMaxScaler.

Python
from sklearn.preprocessing import MinMaxScaler
import numpy as np

data = np.array([80]).reshape(-1, 1)
scaler = MinMaxScaler(feature_range=(10, 100))
scaler.fit([[0], [100]]) # Definujeme původní hranice

vysledek = scaler.transform(data)
print(vysledek) # Výstup: [[82.]]

Proč to Python nemá v "základu"?

Python v základní knihovně math tuto funkci nemá, protože je příliš specifická pro různé obory.

  • Grafici (knihovny jako Matplotlib nebo PyQt) mají své vlastní metody.

  • Tvůrci her (např. v Pygame) tomu často říkají lerp (Linear Interpolation).

  • Datoví analytici používají zmíněný NumPy.

Zajímavost: v Arduinu (C++) se tato funkce jmenuje přímo map(). Je to úplně ten samý princip.

Arduinovská funkce map() je legendární svou jednoduchostí a v Pythonu ti pravděpodobně chybí právě tenhle přímočarý přístup.

Pokud si chceš v Pythonu vytvořit vlastní verzi, která se chová úplně stejně jako ta v C/C++, vypadala by takto:

Python
def map_value(x, in_min, in_max, out_min, out_max):
    return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min

# Použití:
vysledek = map_value(80, 0, 100, 10, 100) # vrátí 82.0

Malý rozdíl mezi C a Pythonem (Integer vs. Float)

V klasickém C (Arduinu) pracuje map() standardně s celými čísly (integery), což občas vede k zaokrouhlovacím chybám (všechno za desetinou čárkou se prostě "uřízne").

V Pythonu tento vzorec automaticky pracuje s desetinnými čísly (floaty), což je pro grafy a přesné výpočty mnohem lepší. Pokud bys ale z nějakého důvodu trval na chování jako v C, stačí výsledek obalit funkcí int() nebo použít celočíselné dělení //.


Proč je to v grafech tak silný nástroj?

Když jsi v C používal map(), pravděpodobně jsi převáděl hodnotu z analogového pinu (0 až 1023) na svítivost LED (0 až 255). V grafech je to úplně to samé, jen ty cílové souřadnice jsou pixely.

Příklad s osou X v grafu:

  • Data: Máš časovou řadu od 0 do 60 sekund.

  • Obrazovka: Tvůj graf začíná na pixelu 50 a končí na pixelu 450 (šířka 400 px).

  • Výpočet pro sekundu 30: map_value(30, 0, 60, 50, 450) ti vyplivne přesně prostředek grafu, tedy pixel 250.

Tip pro pokročilé: "Clamping"

Funkce map() v C i tento jednoduchý vzorec v Pythonu mají jednu vlastnost: nehlídají přetečení. Pokud do nich pošleš hodnotu 110 (mimo rozsah 0100), vyhodí ti výsledek mimo cílový rozsah (109).

V grafech se proto často používá kombinace s funkcí clip (nebo constrain v Arduinu):

Python
def map_with_limit(x, in_min, in_max, out_min, out_max):
    # Výpočet
    val = (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min
    # Omezení (clamping)
    return max(min(val, out_max), out_min) 


Žádné komentáře:

Okomentovat

Poznámka: Komentáře mohou přidávat pouze členové tohoto blogu.