C++:热图 (BMP) 的数学函数
C++: Mathematical function for Heatmap (BMP)
我正在尝试编写一个从力源生成热图的程序。截至目前,我使用每个像素中的力,使用高斯分布(或简单地 exp(-(x*x))
)计算颜色化合物。规范它总是给我一些颜色后,图片看起来像这样:
这有两个来源,位于蓝点的中心。
它看起来很酷,但颜色之间的过渡一点也不流畅,并且如您所见,它有黑线。我尝试绕过指数函数,使它们不那么陡峭,并将它们归一化为总计始终等于 255。这是我使用它得到的最好结果。
所以,我的问题:有没有比 e^-x² 更适合这个问题的函数?或者,有什么我可以添加到函数中以使其更流畅的过渡吗?
万一有人想要代码示例,这是我用来编写 bmp 的函数:
void Field::toBmp(std::ofstream& fp)
{
BmpWriter::writeHeader(x_dim, y_dim, fp);
char buffer[x_dim*y_dim*3 + 54];
int myconst = 10;
int normalizer;
const int MAX = 1000;
unsigned int pow = 0;
for(unsigned int index = 0; index < y_dim; index++)
{
for(unsigned int counter = 0; counter < x_dim; counter++)
{
pow = calculateForce(counter, index) * myconst;
if(pow > MAX)
{
buffer[(index*x_dim + counter)*3 + 0] = 0X00;
buffer[(index*x_dim + counter)*3 + 1] = 0X00;
buffer[(index*x_dim + counter)*3 + 2] = 0XFF;
}
else
{
std::cout << pow << '\n';
buffer[(index*x_dim + counter)*3 + 0] = 255*exp((-std::pow((pow),2.0)/(256*256)));
buffer[(index*x_dim + counter)*3 + 1] = 255*exp((-std::pow((pow-(MAX/2),2.0))/(256*256));
buffer[(index*x_dim + counter)*3 + 2] = 255*exp((-std::pow((pow-MAX),2.0)/(256*256)));
normalizer = 255/(buffer[(index*x_dim + counter)*3 + 2]
+ buffer[(index*x_dim + counter)*3 + 1]
+ buffer[(index*x_dim + counter)*3 + 2] + 0.01);
buffer[(index*x_dim + counter)*3 + 2] *= normalizer;
buffer[(index*x_dim + counter)*3 + 1] *= normalizer;
buffer[(index*x_dim + counter)*3 + 0] *= normalizer;
}
}
}
fp.write(buffer, x_dim*y_dim*3);
}
对于颜色插值,在 RGB-space 中进行插值并不是最佳选择。我会使用 HSV 或 HSL (https://en.wikipedia.org/wiki/HSL_and_HSV)。这样做,您可以将饱和度和亮度或饱和度和亮度设置为恒定值,然后将您的数据映射到各种色调。您将逐个像素地执行此操作(根据每个像素的色调生成每个像素的颜色),然后应用 HSL 或 HSV 到 RGB 转换函数来为您的 BMP 找到该像素的 RGB(这些很容易通过 google).
我正在尝试编写一个从力源生成热图的程序。截至目前,我使用每个像素中的力,使用高斯分布(或简单地 exp(-(x*x))
)计算颜色化合物。规范它总是给我一些颜色后,图片看起来像这样:
这有两个来源,位于蓝点的中心。
它看起来很酷,但颜色之间的过渡一点也不流畅,并且如您所见,它有黑线。我尝试绕过指数函数,使它们不那么陡峭,并将它们归一化为总计始终等于 255。这是我使用它得到的最好结果。
所以,我的问题:有没有比 e^-x² 更适合这个问题的函数?或者,有什么我可以添加到函数中以使其更流畅的过渡吗?
万一有人想要代码示例,这是我用来编写 bmp 的函数:
void Field::toBmp(std::ofstream& fp)
{
BmpWriter::writeHeader(x_dim, y_dim, fp);
char buffer[x_dim*y_dim*3 + 54];
int myconst = 10;
int normalizer;
const int MAX = 1000;
unsigned int pow = 0;
for(unsigned int index = 0; index < y_dim; index++)
{
for(unsigned int counter = 0; counter < x_dim; counter++)
{
pow = calculateForce(counter, index) * myconst;
if(pow > MAX)
{
buffer[(index*x_dim + counter)*3 + 0] = 0X00;
buffer[(index*x_dim + counter)*3 + 1] = 0X00;
buffer[(index*x_dim + counter)*3 + 2] = 0XFF;
}
else
{
std::cout << pow << '\n';
buffer[(index*x_dim + counter)*3 + 0] = 255*exp((-std::pow((pow),2.0)/(256*256)));
buffer[(index*x_dim + counter)*3 + 1] = 255*exp((-std::pow((pow-(MAX/2),2.0))/(256*256));
buffer[(index*x_dim + counter)*3 + 2] = 255*exp((-std::pow((pow-MAX),2.0)/(256*256)));
normalizer = 255/(buffer[(index*x_dim + counter)*3 + 2]
+ buffer[(index*x_dim + counter)*3 + 1]
+ buffer[(index*x_dim + counter)*3 + 2] + 0.01);
buffer[(index*x_dim + counter)*3 + 2] *= normalizer;
buffer[(index*x_dim + counter)*3 + 1] *= normalizer;
buffer[(index*x_dim + counter)*3 + 0] *= normalizer;
}
}
}
fp.write(buffer, x_dim*y_dim*3);
}
对于颜色插值,在 RGB-space 中进行插值并不是最佳选择。我会使用 HSV 或 HSL (https://en.wikipedia.org/wiki/HSL_and_HSV)。这样做,您可以将饱和度和亮度或饱和度和亮度设置为恒定值,然后将您的数据映射到各种色调。您将逐个像素地执行此操作(根据每个像素的色调生成每个像素的颜色),然后应用 HSL 或 HSV 到 RGB 转换函数来为您的 BMP 找到该像素的 RGB(这些很容易通过 google).