Digitalizace grafu, aneb
Jak z grafu vyčíst hodnoty a udělat z nich opět graf?

PhDr. Mgr. Jeroným Klimeš, Ph.D. 2026-04-24

Při přípravě knihy Křesťanství vztahy a sex do tisku jsem narazil na problém, že mám jen zdrojový graf v nevalné kvalitě a potřeboval bych ho předělat na nový, úhledný, ke kterému ovšem nemám zdrojová data. Samozřejmě šlo by to udělat ve GIMP nebo Photoshopu, ale řekl jsem si, že by bylo elegantnější řešení převést graf na data, digitalizovat ho a nový graf udělat z nich. Povedlo se, proto Vám přináším postup, který se může hodit kdekomu v nejrůznějších aplikacích, například vyčítání dat z historických papírových výstupů třeba teploty či seismografu.

Zdrojový graf popisuje, že náboženské společnosti mají asi o 30 % větší životaschopnost než sekulární (viz strana 116). Tento graf jsem potřeboval předělat.

Tento graf jsem v GIMPu očistil od os a legendy a rotoval o 90°.

Toto jsem dále rozdělil na dvě čáry a převedl na černobílý obraz, které jsem uložil do separátních souborů ve formátu PPM – ascii:

Černá čára PPM Červená čára PPM

Soubor PPM má přímočarou textovou strukturu

První tři řádky jsou hlavička, kde na třetí řádce jsou rozměry obrázku.

P3
# Created by GIMP version 3.0.4 PNM plug-in
280 255 # rozměry obrázku a konec hlavičky
255 # První bod – 3x255, tedy bílý
255
255
255 # Druhý bod – 3x255, tedy bílý
255
255
0   # Třetí bod – 3x0, tedy černý
0
0
255 # Čtvrtý bod – 3x255, tedy bílý
255
255

… atd. až do 280 × 255 × 3. řádky.

První řádka obrázku je tedy 280 × 3 = 840 řádek.

Skript v Bash

Teď stačilo napsat nedlouhý skript v Bash.

Stažení Bash skriptu

#/bin/bash
radka=280 		# 280 znaku krat tri
celaradka=radka*3
hlavicka=3 # hlavicka ma 3-5 radek
i=0
counter=1
old=1000000
soubor_vstup="cerna_cara.ppm"
soubor_vystup=/dev/shm/picture_analyza_ppm_$(date +%Y-%m-%d_%H-%M-%S).txt
# shm je virtualni disk, takže neustále přepisování neničí SSD disk.

while read line
do
    ((i++))
    if [ $i -le $hlavicka  ]; then
        continue; # preskoci hlavicku
    else
        if (( ( (i - hlavicka) % celaradka ) == 1 )); then
# testuje konec řádky obrázku.
# Konec řádky je posunut o hlavičku a zbytek, tedy modulus (%) po dělení délkou
# celé řádky je 1. Začátky nových řádek budou tedy (3+280×3×n+1), kde n je
# číslo řádky obrázku. Jsou to tedy čísla 844, 1684, 2524...
# Ale to nemusím řešit, mě zajímá jen ten zbytek.

	((counter++))
            if [ $old -lt 1000000 ]; then
                echo -n "$old $counter  " >> $soubor_vystup # vyexportuje
                echo >> $soubor_vystup; # založí novou řádku obrázku
            fi
            echo -n $(( ((i-hlavicka) / celaradka ) + 1 ))" " >> $soubor_vystup;
            # vyexportuje číslo obrazovkového řádku
            counter=1
            old=1000000 # začíná neznámou/nesmyslnou barvou
            continue # načte další řádku ze souboru
        fi
    fi # konec přeskoku hlavičky.

    if [ "$line" == "$old" ]; then
        ((counter++)) # pokud je tato řádka stejná jako předchozí, zvýší čítač.
    else
        if [ $old -lt 1000000 ]; then
        # Smysluplné barvy (<256) vyexportuje bez konce řádky.
            echo -n "$old $counter  " >> $soubor_vystup
        fi
        counter=1 # založí nový čítač
        old=$line
    fi
done < $soubor_vstup # řádky načítá z tohoto souboru

Výstup ze skriptu

Přepočet černé čáry Přepočet červené čáry

S mírnou úpravou začátku a konce vypadá výstup takto:

1 255 795  0 45 255 0
2 255 753  0 87  255 0
3 255 678  0 138  255 24
4 255 600  0 192  255 48
5 255 555  0 201  255 84
6 255 528  0 153  255 159
7 255 498  0 105  255 237
8 255 468  0 90  255 282
9 255 438  0 90  255 312
10 255 411  0 90  255 339
11 255 381  0 90  255 369
12 255 351  0 90  255 399
13 255 321  0 90  255 429
14 255 297  0 87  255 456

Definice řádky:

Číslo_řádku(14) 1bílá_barva(255) #počet_1bílé(297) černá_barva(0) #počet_černé(87) 2bílá_barva(255) #počet_2bílé(456), kde 297+87+456=3*280=840

Tento skript načteme do Calcu (Excelu) a získaná čísla interpretujeme takto:

Hodnota čáry = #počet_1bílé + #počet_černé/2 = 297+87/2 = 340.5

Jinými slovy za vyčtenou hodnotu grafu považuji vzdálenost středu černé čáry od levého okraje grafu, proto jsem jej taky otočil.

Takto jsem načetl obě čáry grafu a přepočítal tak, aby byly v rozsahu y∈<0, 1> a x∈<0, 85>, popř. x∈<0, 115>, které jsem vyčetl z grafu. Jinými slovy, obrázek má rozměr třeba 280×340, tedy je musím z 280 udělat hodnoty 0 až 1 a z 340 udělat hodnoty 0 až 115. To je obyčejná trojčlenka:
stará_hodnota ku 340 se má jako nová_hodnota ku 115, tedy:
nová_hodnota=(stará_hodnota/340)*115.

Pak už je na vás, jaký program použijete na generování grafu. Já osobně jsem vcelku spokojený s Calcem, vychytávky dělám v R. Zde to byl graf typu X/Y.

Výsledný nový graf generovaný z vyextranovaných dat si stáhněte v Calc souboru i s grafem.

Pokud něco nechápete, zavolejte nebo napište email. Hlavně ale nezapomeňte poděkovat Hospodinovi za Linux a jeho tvůrce!