• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

sfml blur optymizacja

Object Storage Arubacloud
0 głosów
421 wizyt
pytanie zadane 30 maja 2015 w C i C++ przez Pan Kulomb Pasjonat (18,630 p.)
edycja 30 maja 2015 przez Pan Kulomb

Ostatnio zaimplementowałem funkcję w SFML, która rozmazywała obraz przechodząc przez obraz po wysokości i po szerokości. Zmienna n określała stopień rozmazania. Gdy np. n == 10 to funkcja obliczała piksel jako średnią kwadratu o boku 2*n + 1 ze środniem w miejscu, w którym oblicza się piksel. Jednak ta funkcja była dosyś wolna, gdy n == 10 obliczała jakieś 5s, a gdy n == 20 to jakieś 15s, obraz miał wymiary 500px na 364px.

Jak to zoptymizować bez używania GPU?

Aktualny kod:

size_t add(size_t number, int factor, size_t border)
{
    long long t = number+factor;

    if(t < 0)
        t += border;
    else if(t >= border)
        t -= border;

    return t;
}

struct colorMix
{
    unsigned r, g, b;
};

sf::Image blur(sf::Image &image, int n)
{
    sf::Image newImage = image;

    sf::Vector2u imageSize = image.getSize();

    size_t width = imageSize.x;
    size_t height = imageSize.y;

    size_t divider = n*n;
    size_t r, g, b;

    colorMix mix[width][height];

    for(size_t x = 0; x < width; ++x)
        for(size_t y = 0; y < height; ++y)
            mix[x][y].r = mix[x][y].g = mix[x][y].b = 0;

    for(size_t y = 0; y < height; ++y)
    {
        for(size_t x = 0; x < width; ++x)
        {
            sf::Color pixel = image.getPixel(x, y);

            r = pixel.r;
            g = pixel.g;
            b = pixel.b;

            for(size_t i = 0; i < n; ++i)
                for(size_t j = 0; j < n; ++j)
                {
                    size_t posX = add(x, i, width);
                    size_t posY = add(y, j, height);

                    mix[posX][posY].r += r;
                    mix[posX][posY].g += g;
                    mix[posX][posY].b += b;
                }
        }
    }

    for(size_t x = 0; x < width; ++x)
        for(size_t y = 0; y < height; ++y)
        {
            r = mix[x][y].r / divider;
            g = mix[x][y].g / divider;
            b = mix[x][y].b / divider;

            newImage.setPixel(x, y, sf::Color(r, g, b));
        }

    return newImage;
}

 

2 odpowiedzi

+1 głos
odpowiedź 30 maja 2015 przez adrian17 Ekspert (344,860 p.)

Teoretycznie dużym przyśpieszeniem mogło by być, gdybyś zamiast getPixel() czytał dane obrazu bezpośrednio, przez zdobycie wskaźnika do samego obrazu przez getPixelsPtr() i samodzielnym czytaniu jego danych. Podobnie, zamiast setPixel, mógłbys stworzyć newImage bezpośrednio z własnej tablicy z użyciem Image::create().

Z pobocznych rad:

for(size_t x = 0; x < width; ++x)
        for(size_t y = 0; y < height; ++y)
            mix[x][y].r = mix[x][y].g = mix[x][y].b = 0;

Zamiast tego możesz ustawić domyślne wartości r, g, b w samej strukturze:

struct colorMix
{
    unsigned r = 0, g = 0, b = 0;
};

Dalej:

            for(size_t i = 0; i < n; ++i)
                for(size_t j = 0; j < n; ++j)

To chyba nie jest kwadrat 2n+1 na 2n+1, nie?

    if(t < 0)
        t += border;
    else if(t >= border)
        t -= border;

Tutaj... zawijasz wokół krawędzi? Trochę to dziwne, lepiej chyba przeczytać wartość brzegową.

komentarz 30 maja 2015 przez Pan Kulomb Pasjonat (18,630 p.)
wcześniej było 2n+1, ale zmieniłem
0 głosów
odpowiedź 30 maja 2015 przez adrian17 Ekspert (344,860 p.)
Musisz raczej pokazać kod. Rozumiem, ze miałeś włączone optymalizacje? Teoretycznie można to trochę przyśpieszyć przez użycie kilku rdzeni, ale nawet bez tego to raczej nie powinno być aż tak wolne.
komentarz 30 maja 2015 przez Pan Kulomb Pasjonat (18,630 p.)
Co to znaczy, że miałem włączone optymalizacje?
komentarz 30 maja 2015 przez adrian17 Ekspert (344,860 p.)
Możesz pokazać na przykład screenshot IDE? Będzie mi łatwiej powiedzieć
komentarz 30 maja 2015 przez Pan Kulomb Pasjonat (18,630 p.)

Oto obrazek z Code::Blocks

komentarz 30 maja 2015 przez adrian17 Ekspert (344,860 p.)
(mały ten screenshot :P)

Na górze obok przycisku kompilacji masz wybór Debug / Release; to dwie przygotowane zestawy opcji dla kompilatora, Debug generuje normalny kod który łatwiej się debuguje, a Release włącza optymalizacje kompilatora. Jeśli mierzysz czas działania programu, zawsze mierz go w konfiguracji Release.

Mam też rady dotyczące kodu, napiszę je zaraz w nowej odpowiedzi.
komentarz 30 maja 2015 przez Pan Kulomb Pasjonat (18,630 p.)

WOW!! TO DZIAŁA! Tylko jest mały problem, w trybie Release pojawia się konsola i to z jakimiś błędami SFML, bo informuje mnie o jakimś joysticku, a nic w kodzie takiego nie mam.

komentarz 30 maja 2015 przez adrian17 Ekspert (344,860 p.)
W trybie Debug nie masz konsoli? Jeśli wyłączyłeś ją ręcznie wcześniej, musisz to powtórzyć dla tej konfiguracji. Robiło to się tutaj: https://puu.sh/i6eCc/f7c60cea3d.png

Co do joysticka, to był bug SFMLa, ale z tego co wiem został już naprawiony w 2.2 lub 2.3.
komentarz 30 maja 2015 przez Pan Kulomb Pasjonat (18,630 p.)
:D Nie zauważyłem wcześniej, że jest tam opcja zmiany trybu

Podobne pytania

0 głosów
2 odpowiedzi 160 wizyt
pytanie zadane 25 stycznia 2021 w HTML i CSS przez AgentTecza Obywatel (1,810 p.)
0 głosów
2 odpowiedzi 466 wizyt
pytanie zadane 15 lipca 2020 w HTML i CSS przez Marak123 Stary wyjadacz (11,190 p.)
0 głosów
0 odpowiedzi 398 wizyt
pytanie zadane 2 września 2019 w JavaScript przez dabgan Początkujący (410 p.)

92,550 zapytań

141,392 odpowiedzi

319,519 komentarzy

61,935 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...