如何计算卤化物中的色度图像?
How to calculate chroma image in Halide?
我目前正在评估 Halide 是否适合我的课程。作为一个简短的 Hello Halide 示例,我想将 rgb 图像转换为 hsl space。然而,在尝试的时候,我卡在了第一阶段。
为了转换为 hsl,我需要先计算 chroma 图像。这是给定像素的最大和最小通道值之间的差异。我试图在文档中找到类似的东西,但我找不到。我如何在 Halide 中执行此操作?
在 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;
}
下面是一个将 RGB 转换为 HSL 的 Halide 程序示例:
#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()
-ing 最里面之后)以避免该数学的任何循环/分支开销。
我目前正在评估 Halide 是否适合我的课程。作为一个简短的 Hello Halide 示例,我想将 rgb 图像转换为 hsl space。然而,在尝试的时候,我卡在了第一阶段。
为了转换为 hsl,我需要先计算 chroma 图像。这是给定像素的最大和最小通道值之间的差异。我试图在文档中找到类似的东西,但我找不到。我如何在 Halide 中执行此操作?
在 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;
}
下面是一个将 RGB 转换为 HSL 的 Halide 程序示例:
#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()
-ing 最里面之后)以避免该数学的任何循环/分支开销。