iOS GLSL. Czy istnieje sposób na utworzenie histogramu obrazu przy użyciu shadera GLSL?

W innym miejscu Stoskoverflow zadano pytanie dotyczące histogramu depthbuffer - Utwórz teksturę histogramu bufora głębi za pomocą GLSL .

Piszę aplikację do przetwarzania obrazów na iOS i jestem zaintrygowany tym pytaniem, ale niejasna jest udzielona odpowiedź. Czy możliwe jest utworzenie histogramu obrazu za pomocą GPU przez GLSL?

Author: Community, 2012-04-25

2 answers

Tak, jest. Nie jest to oczywiście najlepsze podejście, ale jest to rzeczywiście najlepsze dostępne w systemie iOS, ponieważ OpenCL nie jest obsługiwany. Stracisz elegancję, a Twój kod prawdopodobnie nie będzie tak prosty, ale prawie wszystkie funkcje OpenCL można osiągnąć za pomocą shaderów.

Jeśli to pomoże, DirectX11 zawiera przykład FFT dla shaderów obliczeniowych. Zobacz informacje o wydaniu DX11 August SDK.

 0
Author: ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-04-26 16:36:21

Tak, jest, chociaż jest to trochę trudniejsze niż myślisz na iOS. Jest to czerwony histogram wygenerowany i wykreślony w całości na GPU, działający w oparciu o transmisję wideo na żywo:

Histogram czerwony GPU

Sugestia Tommy ' ego w pytaniu, które podajesz, jest świetnym punktem wyjścia, podobnie jak ta praca Scheuermanna i Hensleya . Sugerowane jest użycie rozpraszania do tworzenia histogramu dla kanałów kolorów na obrazie. Rozpraszanie jest procesem, w którym mijasz w siatce punktów do cieniowania wierzchołków, a następnie niech ten cieniujący odczyta kolor w tym punkcie. Wartość pożądanego kanału koloru w tym punkcie jest następnie zapisywana jako współrzędna X (z 0 dla współrzędnych Y i z). Następnie moduł cieniowania fragmentów rysuje półprzezroczysty punkt o szerokości 1 piksela na tej współrzędnej w celu.

Ten cel to obraz o wysokości 1 piksela, szerokości 256 pikseli, z każdą pozycją szerokości reprezentującą jeden kolorowy Pojemnik. Pisząc punkt o niskim Alfa kanał (lub niskie wartości RGB), a następnie za pomocą mieszania addytywnego można gromadzić wyższą wartość dla każdego pojemnika na podstawie liczby wystąpień określonej wartości koloru na obrazie. Te piksele histogramu można następnie odczytać do późniejszego przetworzenia.

[4]} główny problem z robieniem tego w shaderach na iOS polega na tym, że pomimo raporty są przeciwne , Apple wyraźnie stwierdza, że Tekstura czyta w cieniowaniu wierzchołków nie będzie działać na iOS. Próbowałem tego ze wszystkimi urządzeniami z iOS 5.0 i żaden z nich były w stanie wykonywać odczyty tekstur w cieniowaniu wierzchołków (ekran po prostu robi się czarny, bez błędów GL).

Aby to obejść, odkryłem, że mogę odczytać surowe piksele mojego wejściowego obrazu (poprzez glReadPixels() lub szybsze buforowanie tekstur ) i przekazać te bajty jako dane wierzchołków z typem GL_UNSIGNED_BYTE. Poniższy kod dokonuje tego:

glReadPixels(0, 0, inputTextureSize.width, inputTextureSize.height, GL_RGBA, GL_UNSIGNED_BYTE, vertexSamplingCoordinates);

[self setFilterFBO];

[filterProgram use];

glClearColor(0.0, 0.0, 0.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT);

glBlendEquation(GL_FUNC_ADD);
glBlendFunc(GL_ONE, GL_ONE);
glEnable(GL_BLEND);

glVertexAttribPointer(filterPositionAttribute, 4, GL_UNSIGNED_BYTE, 0, (_downsamplingFactor - 1) * 4, vertexSamplingCoordinates);
glDrawArrays(GL_POINTS, 0, inputTextureSize.width * inputTextureSize.height / (CGFloat)_downsamplingFactor);

glDisable(GL_BLEND);

W powyższym kodzie zauważysz, że stosuję krok do próbkowania tylko ułamka pikseli obrazu. Dzieje się tak dlatego, że najniższy poziom krycia lub skali szarości, który można zapisać, wynosi 1/256, co oznacza, że każdy pojemnik zostanie maksymalnie wyczerpany raz więcej niż 255 pikseli na tym obrazie ma tę wartość koloru. Dlatego musiałem zmniejszyć liczbę przetwarzanych pikseli, aby wprowadzić zakres histogramu w tym ograniczonym oknie. Szukam sposobu na rozszerzenie tego zakresu dynamicznego.

Shadery używane do tego celu są następujące, zaczynając od wierzchołka shadera:
 attribute vec4 position;

 void main()
 {
     gl_Position = vec4(-1.0 + (position.x * 0.0078125), 0.0, 0.0, 1.0);
     gl_PointSize = 1.0;
 }

I kończąc na fragment shader:

 uniform highp float scalingFactor;

 void main()
 {
     gl_FragColor = vec4(scalingFactor);
 }

Działającą implementację tego można znaleźć w moim open source GPUImage frameworku. Chwyć i uruchom przykład FilterShowcase, aby zobaczyć analizę histogramu i kreślenie dla siebie.

Istnieją pewne problemy z wydajnością tej implementacji, ale był to jedyny sposób, w jaki mogłem myśleć o zrobieniu tego na GPU na iOS. Jestem otwarty na inne propozycje.

 33
Author: Brad Larson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:45:33