Как рассчитать цветность изображения в галогениде?

#c #image-processing #halide

Вопрос:

В настоящее время я оцениваю, является ли галогенид хорошим выбором для моих программ. В качестве короткого примера с галоидом Hello я хотел преобразовать изображение rgb в пространство hsl. Однако при попытке я застрял на первом этапе.

Чтобы преобразовать в hsl, мне сначала нужно будет рассчитать цветовое изображение. Это разница между максимальным и минимальным значением канала для данного пикселя. Я попытался найти что-то подобное в документации, но мне это не удалось. Как бы я сделал это в галогениде?

В C это было бы что-то вроде:

 for (auto y = 0; y < image.height();   y)
    for (auto x = 0; x < image.width();   x)
    {
        auto maximum = 0;
        auto minimum = 255;
        for (auto c = 0; c < image.channels();   c)
        {
            if (image(x, y, c) < minimum)
                minimum = image(x, y, c);
            if (image(x, y, c) > maximum)
                maximum = image(x, y, c);
        }
        chroma(x, y) = maximum - minimum;
    }
 

Ответ №1:

Вот пример галогенидной программы для преобразования из RGB в HSL:

 #include <Halide.h>
#include <halide_image_io.h>
using namespace Halide;
using namespace Halide::Tools;

int main(int argc, char *argv[]) {
    Buffer<float> input = load_and_convert_image(argv[1]);

    Func max_channels, min_channels, chroma, result_hsl;
    Var x, y, c;

    Expr R = input(x, y, 0);
    Expr G = input(x, y, 1);
    Expr B = input(x, y, 2);

    max_channels(x, y) = max(R, G, B);
    min_channels(x, y) = min(R, G, B);
    chroma(x, y) = max_channels(x, y) - min_channels(x, y);

    Expr V = max_channels(x, y);
    Expr C = chroma(x, y);

    Expr H = select(C == 0, 0,
                    R == V, 60 * (0   (G - B) / C),
                    G == V, 60 * (2   (B - R) / C),
                    60 * (4   (R - G) / C)) /
             360;
    Expr L = V - C / 2;
    Expr S = (V - L) / min(L, 1 - L);

    result_hsl(x, y, c) = select(
            c == 0, H,
            c == 1, S,
            L);

    result_hsl
            .bound(c, 0, 3)
            .reorder(c, x, y)
            .unroll(c, 3);

    Buffer<float> result = result_hsl.realize({input.width(), input.height(), 3});

    convert_and_save_image(result, argv[2]);
}
 

а вот и CMakeLists.txt Я использовал, чтобы построить это:

 cmake_minimum_required(VERSION 3.20)
project(rgb_to_hsl)

find_package(Halide REQUIRED)

add_executable(rgb_to_hsl main.cpp)
target_link_libraries(rgb_to_hsl PRIVATE Halide::Halide Halide::ImageIO)
 

Здесь могут быть ошибки с фактическим преобразованием HSL, но оно все равно должно демонстрировать большие идеи. Обратите внимание на одну нелогичную вещь здесь: мы bound() и unroll() измерение канала (после reorder() того, как оно самое внутреннее), чтобы избежать каких-либо накладных расходов на цикл / ветвление для этой математики.

Комментарии:

1. Есть ли какой-либо способ написать это без явного определения input(x, y, 0) ,… Если возможно, я хотел бы использовать это в качестве еще одной переменной цикла.

2. @jan.sende Я не совсем понимаю, о чем ты говоришь. Я не определяю это явно (т. Е. Как определение обновления)

3. Извините, я не очень хорошо выражаю свой вопрос. В данный момент вы выбираете цветовой канал, вставляя его вручную 0 . Возможно ли это сделать с переменной, такой как x и y ? То есть, могу ли я как-то рассчитать max_channel в общем виде, не предполагая трехканального изображения? (Я хотел бы знать, как вычислять max_channel на изображении n -канала, где n известен только во время выполнения.)

4. В этом случае вам придется использовать домен сокращения, но это не имеет смысла для rgb -> hsl, который предполагает 3 канала…

5. Хорошо. Вернул вопрос назад и разделил многоканальную часть на отдельную.