.[ ČeskéHry.cz ].
Resize obrázku - Lanczos

 
odeslat nové téma   Odpovědět na téma    Obsah fóra České-Hry.cz -> C / C++
Zobrazit předchozí téma :: Zobrazit následující téma  
Autor Zpráva
perry



Založen: 28. 07. 2009
Příspěvky: 870

PříspěvekZaslal: 17. únor 2020, 19:05:37    Předmět: Resize obrázku - Lanczos Odpovědět s citátem

Nestává se mi to často, ale totálně jsem se zaseknul u resamplování obrázku pomocí Lanczos filtru a nemůžu najít, co mám blbě:


kód:
std::vector<uint8_t> ResizeLanczos(
    const std::vector<uint8_t> & input, size_t inputW, size_t inputH,
    size_t newW, size_t newH,
    size_t kernelSize){

    std::vector<uint8_t> resizedData;
    resizedData.resize(newW * newH);

    double xRatio = inputW / static_cast<double>(newW);
    double yRatio = inputH / static_cast<double>(newH);

    for (size_t y = 0; y < newH; y++){
        size_t yW = y * newW;

        double y0 = y * yRatio;
        size_t yy_start = static_cast<size_t>(std::max(std::floor(y0) - kernelSize + 1, 0.0));
        size_t yy_stop = std::min(yy_start + (2 * kernelSize - 1), inputH);

        for (size_t x = 0; x < newW; x++){

            double x0 = x * xRatio;
            size_t xx_start = static_cast<size_t>(std::max(std::floor(x0) - kernelSize + 1, 0.0));
            size_t xx_stop = std::min(xx_start + (2 * kernelSize - 1), inputW);

            //====================
            //interpolation kernel
            double q = 0;
            double weight = 0;
            for (size_t yy = yy_start; yy < yy_stop; yy++){

                for (size_t xx = xx_start; xx < xx_stop; xx++){                 
                    double wX = LanczosKernel1d(x0 - xx, kernelSize);
                    double wY = LanczosKernel1d(y0 - yy, kernelSize);     
                    q += input[xx + yy * inputW] * wX * wY; 
                    weight += wX * wY;               
                }                         
            }

            //============
            resizedData[x + yW] = static_cast<uint8_t>(q / weight);
        }
    }

    return resizedData);
}


A vlastní Lanczos funkce:
kód:

double LanczosKernel1d(double x, double n) {
    static const double PI = 3.1415927410125732421875;

    if ((x > -0.00001) && (x < 0.00001)) return 1; 
    if (std::abs(x) >= n) return 0;

    //use normalized sinc
    double pix = PI * x;
    return n * (std::sin(pix) * std::sin(pix / n)) / (pix * pix);
}


jako obrázek to zmenší, obsahově tam je co má být, ale celé je to takové "hnusné" a zubaté. Např. čáry nejsou čáry, ale přerušované linky.



Vlevo jak by to mělo vypadat, vpravo jak to vypadne z mého

Nedělal někdo neco podobného, nebo nevidí tam někdo něco totálně blbě. Koukám do toho celý den a už vážně nevím Sad
_________________
Perry.cz
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu Zobrazit autorovi WWW stránky
mar



Založen: 16. 06. 2012
Příspěvky: 530

PříspěvekZaslal: 18. únor 2020, 09:53:52    Předmět: Odpovědět s citátem

protože neclampuješ výstup! jinak mi ten tvůj kód funguje v pohodě

plus bys byl hodný, kdybys to zaokrouhlil, tj. +0.5, až pak převést na byte
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu
perry



Založen: 28. 07. 2009
Příspěvky: 870

PříspěvekZaslal: 18. únor 2020, 10:24:13    Předmět: Odpovědět s citátem

Díky... na clamping jsem zapomněl, nicméně výstup je pořád stejně "zubatý" a "kostičkovaný", nikoliv hladký.

Filtr jako takový je možná OK, spíš ta celková logika resizování obrázku jo možná divná, protože vygumuje detaily.
_________________
Perry.cz
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu Zobrazit autorovi WWW stránky
mar



Založen: 16. 06. 2012
Příspěvky: 530

PříspěvekZaslal: 18. únor 2020, 10:34:01    Předmět: Odpovědět s citátem

děláš upsampling nebo downsampling? jak veliký je kernel?

pár nápadů, co by možná mohly pomoct s laděním?:
- když ve filtru vrátíš jedničku, budeš to mít celé máznuté bez kostiček?
- sampluješ opravdu symetricky?
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu
perry



Založen: 28. 07. 2009
Příspěvky: 870

PříspěvekZaslal: 18. únor 2020, 10:43:32    Předmět: Odpovědět s citátem

Downsampling.

Nicméně zkoušel jsem porovnat ještě s openCV a tam je ten výsledek více-méně stejný.

Spíše je asi problém s logikou toho downsamplingu jako takového, kde prostě jemné kontury zmizí, nebo se "nakostičkují". Asi není dobrý nápad na downsampling používat nějaké kernely a vzít jenom průměr z nějakého okolí bude lepší.

Vstupní obrázek mám 8431x6878 a zmenšuju ho scale factorem 0.125 na 1053x859.
_________________
Perry.cz
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu Zobrazit autorovi WWW stránky
mar



Založen: 16. 06. 2012
Příspěvky: 530

PříspěvekZaslal: 18. únor 2020, 10:56:28    Předmět: Odpovědět s citátem

Tak to bych uřízl vstup, aby byl dělitelný osmi a udělal bych jednoduchý box filter s gamma korekcí (pokud je potřeba) (=zprůměrovat), bude to navíc rychlejší
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu
perry



Založen: 28. 07. 2009
Příspěvky: 870

PříspěvekZaslal: 18. únor 2020, 11:04:31    Předmět: Odpovědět s citátem

Díky.. zkusil jsem a vypadá to o hodně lépe a jak jsi říkal, i to běží rychle. Na upsampling pak ten Lanczos vypadá ok.
_________________
Perry.cz
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu Zobrazit autorovi WWW stránky
Zobrazit příspěvky z předchozích:   
odeslat nové téma   Odpovědět na téma    Obsah fóra České-Hry.cz -> C / C++ Časy uváděny v GMT + 1 hodina
Strana 1 z 1

 
Přejdi na:  
Nemůžete odesílat nové téma do tohoto fóra
Nemůžete odpovídat na témata v tomto fóru
Nemůžete upravovat své příspěvky v tomto fóru
Nemůžete mazat své příspěvky v tomto fóru
Nemůžete hlasovat v tomto fóru


Powered by phpBB © 2001, 2005 phpBB Group


Vzhled udelal powermac
Styl "vykraden" z phpBB stylu MonkiDream - upraveno by rezna