熱力圖是數(shù)據(jù)可視化項(xiàng)目中忧陪,比較常用的顯示方式厘托。通過顏色變化程度,他可以直觀反應(yīng)出熱點(diǎn)分布流炕,區(qū)域聚集等數(shù)據(jù)信息澎现。
項(xiàng)目概述
我們的項(xiàng)目任務(wù)是統(tǒng)計(jì)場館中參觀者的實(shí)時(shí)區(qū)域分布情況,通過熱力圖顯示出來每辟。我們考慮采用WPF作為數(shù)據(jù)顯示部分剑辫。
實(shí)現(xiàn)原理
熱力圖實(shí)現(xiàn)過程就是通過簡單的數(shù)學(xué)變化,將離散的點(diǎn)信息映射到最終圖像上的過程渠欺。
實(shí)現(xiàn)過程如下:
為離散點(diǎn)信息創(chuàng)建一個(gè)Mask妹蔽。Mask是一個(gè)圓形區(qū)域,半徑為該點(diǎn)可以對最終熱力圖像產(chǎn)生影響的區(qū)域半徑挠将。中心點(diǎn)的權(quán)重為1胳岂,越向邊緣輻射,權(quán)重越低舔稀,邊緣部分的權(quán)重為0乳丰。Mask的漸變過程可以考慮多種形式,如線性變化内贮,二次曲線等产园。
將所有離散點(diǎn)Mask進(jìn)行疊加,產(chǎn)生一幅灰度圖像夜郁。相鄰Mask的重疊部分進(jìn)行權(quán)重累加操作什燕,最終灰度圖中每個(gè)像素點(diǎn)的數(shù)值大小就是所有和其有關(guān)的Mask中的權(quán)重之和。 離散點(diǎn)密度越高的地方拂酣,灰度圖種像素點(diǎn)數(shù)值越高秋冰,即圖像越亮。
根據(jù)具體項(xiàng)目不同婶熬,可考慮將權(quán)重乘上一個(gè)固定系數(shù)剑勾。
將生成的灰度圖映射到彩色圖像上。
映射對于關(guān)系
灰度圖 | 彩色圖 |
---|---|
0% | (0赵颅,0虽另,0)(Black) |
25% | (0,0饺谬,255)(Blue) |
50% | (0捂刺,255谣拣,0)(Green) |
75% | (255,255族展,0)(Yellow) |
100% | (255森缠,0, 0)(Red) |
將灰度圖百分百映射到彩色圖的Alpha通道上仪缸,可以增加色彩的透明感覺贵涵。
pixels[i, j, 3] = (byte)(gray[i, j]*255);
參考代碼(C# .net)
void getGrayMap()
{
for (int i = 0; i < height; i++)
for (int j = 0; j < width; j++)
{
gray[i, j] = 0.0f;
}
foreach (Point p in pointList)
{
int _X = (int)p.X;
int _Y = (int)p.Y;
int _startX = (_X >= radius) ? 0 : radius - _X;
int _endX = (_X < width - radius) ? radius * 2 + 1 : radius + width - _X - 1;
int _startY = (_Y >= radius) ? 0 : radius - _Y;
int _endY = (_Y < height - radius) ? radius * 2 + 1 : radius + height - _Y - 1;
for (int i = _startX; i < _endX; i++)
for (int j = _startY; j < _endY; j++)
{
gray[_Y - radius + j, _X - radius + i] += mask[j, i];
}
}
}
void getColorMap()
{
Color c1; //= new Color();
Color c2;// = new Color();
float procent = 0.0f ;
for (int i=0; i<height; i++)
for (int j=0; j<width; j++)
{
if (gray[i, j] >= 1.0f)
{
gray[i, j] = 1.0f;
c1 = colorMap[2];
c2 = colorMap[3];
procent = 1.0f;
}
else if (gray[i, j] >= 0.75f)
{
c1 = colorMap[2];
c2 = colorMap[3];
procent = (gray[i, j] - 0.75f) / 0.25f;
}
else if (gray[i, j] >= 0.5f)
{
c1 = colorMap[1];
c2 = colorMap[2];
procent = (gray[i, j] - 0.5f) / 0.25f;
}
else if (gray[i, j] >= 0.25f)
{
c1 = colorMap[0];
c2 = colorMap[1];
procent = (gray[i, j] - 0.25f) / 0.25f;
}
else
{
c2 = colorMap[0];
c1 = colorMap[4];
procent = (gray[i, j]) / 0.25f;
}
pixels[i, j, 0] = (byte)(c2.B * procent + c1.B * (1.0f - procent));
pixels[i, j, 1] = (byte)(c2.G * procent + c1.G * (1.0f - procent));
pixels[i, j, 2] = (byte)(c2.R * procent + c1.R * (1.0f - procent));
pixels[i, j, 3] = (byte)(gray[i, j]*255);
}
}
顯示效果
參考資料
http://hmfly.info/2012/09/11/heatmap%EF%BC%88%E7%83%AD%E5%9B%BE%EF%BC%89%E7%9A%84%E5%8E%9F%E7%90%86%E5%92%8C%E5%AE%9E%E7%8E%B0/
http://www.cnblogs.com/Gildor/archive/2010/05/13/1734649.html