🎨
Siv3D | tinycolormap を使って数値をカラーマップで可視化する
数値を色を使って可視化する
2 次元配列に格納された数値を可視化するにはカラーマップが便利です。最小値が白、最大値が黒になるようなグレースケールでマッピングするのが一番簡単ですが、もっと工夫されたカラーマップを利用すると、細かい変化が強調され、より繊細な情報を読み取れる可能性が高くなります。
tinycolormap という C++ ライブラリは、Matlab で使われているカラーマップと、人間の視覚・色覚特性を考慮してデザインされたいくつかのカラーマップを作成するための変換テーブルと変換関数のコレクションを提供しています。
tinycolormap が提供するカラーマップ
Matlab ベース のカラーマップ
Name | Sample |
---|---|
Parula | |
Heat | |
Hot | |
Jet | |
Gray |
Matplotlib)
視覚・色覚特性を考慮したカラーマップ (Name | Sample |
---|---|
Magma | |
Inferno | |
Plasma | |
Viridis | |
Cividis |
GitHub の contributions グラフのようなカラーマップ
Name | Sample |
---|---|
Github |
Turbo カラーマップ
Name | Sample |
---|---|
Turbo |
OpenSiv3D で tinycolormap を使う
tinycolormap は v0.6.0 以降の OpenSiv3D に標準で組み込まれています。API は次の 2 つです
- カラーマップの種類を示す列挙型
ColormapType
- [0.0, 1.0] の範囲(それ以外の場合 [0.0, 1.0] の範囲にクランプされます)の値
x
をカラーマップcolormapType
に基づいて RGB カラーに変換するColor ColorMap01(double x, ColormapType colormapType)
関数およびColorF ColorMap01F(double x, ColormapType colormapType)
関数
# include <Siv3D.hpp> // OpenSiv3D v0.6.3
// 右上のミニカラーマップ用のグリッド
Grid<double> GenerateMinimapGrid(const Size& size)
{
Grid<double> grid(size);
for (auto&& p : step(grid.size()))
{
grid[p] = p.x / (size.x - 1.0);
}
return grid;
}
// Perlin Noise で作られるメインのグリッド
Grid<double> GenerateGrid(const Size& size)
{
Grid<double> grid(size);
PerlinNoise noise{ RandomUint32() };
for (auto&& p : step(grid.size()))
{
grid[p] = noise.octave2D0_1(p * 0.005, 4);
}
return grid;
}
// グリッドをカラーマップに変換
Image ToImage(const Grid<double>& grid, ColormapType colormapType)
{
Image image(grid.size());
for (auto&& p : step(grid.size()))
{
const double value = grid[p];
image[p] = Colormap01(value, colormapType);
}
return image;
}
void Main()
{
const Font font{ 12, Typeface::Bold };
constexpr Rect MinimapRect{ 620, 20, 160, 20 };
const Grid<double> minimapGrid{ GenerateMinimapGrid(MinimapRect.size) };
const Array<String> colormapNames
{
U"Parula", U"Heat", U"Jet", U"Turbo", U"Hot", U"Gray", U"Magma",
U"Inferno", U"Plasma", U"Viridis", U"Cividis", U"Github"
};
size_t colormapIndex = 0;
constexpr Size GridSize{ 600, 600 };
Grid<double> grid{ GenerateGrid(GridSize) };
DynamicTexture texture{ ToImage(grid, ColormapType{ static_cast<uint8>(colormapIndex) }) };
DynamicTexture minimapTexture{ ToImage(minimapGrid, ColormapType{ static_cast<uint8>(colormapIndex) }) };
while (System::Update())
{
// 右上のミニカラーマップを描画
MinimapRect(minimapTexture).draw().drawFrame(0, 1);
font(U"0.0").drawAt(MinimapRect.bl().movedBy(0, 8));
font(U"0.5").drawAt(MinimapRect.bottomCenter().movedBy(0, 8));
font(U"1.0").drawAt(MinimapRect.br().movedBy(0, 8));
// カラーマップの種類を選択するラジオボタン
if (SimpleGUI::RadioButtons(colormapIndex, colormapNames, Vec2{ 620, 60 }, 160))
{
texture.fill(ToImage(grid, ColormapType{ static_cast<uint8>(colormapIndex) }));
minimapTexture.fill(ToImage(minimapGrid, ColormapType{ static_cast<uint8>(colormapIndex) }));
}
// ノイズの再生成
if (SimpleGUI::Button(U"New noise", Vec2{ 620, 550 }, 160))
{
grid = GenerateGrid(GridSize);
texture.fill(ToImage(grid, ColormapType{ static_cast<uint8>(colormapIndex) }));
}
// メインのカラーマップの描画
texture.draw();
}
}
Discussion