Hi all,
I intend to create an effect of heat map to detect the amount of people walking in an area like this:
But until now I only can draw pixels using vector2.
Anybody know any tutorial or information on how to do the effect?
Greetings.
Hi all,
I intend to create an effect of heat map to detect the amount of people walking in an area like this:
But until now I only can draw pixels using vector2.
Anybody know any tutorial or information on how to do the effect?
Greetings.
A heatmap is usually drawn by taking all data in an area into account.
So lets say you have an array of Vector2/3 values which represents your recorded data. There are basically two ways to calculate the intensity for each pixel in your heatmap:
In the end you should have an actual map where the hot areas have the highest value. Now just scale the values to fit in a 0-1 range and use a [Gradient][1] to give each pixel a color.
edit
This [question actually has been asked quite a few times][2] now. Did you actually search? ^^
2. edit
Here’s an example class i just written:
public class Heatmap
{
private float[] samples;
private float[] circle;
private int width;
private int height;
private int radius;
// returns the highest sample
private float MaxValue
{
get
{
float v = 0f;
for (int i = 0; i < samples.Length; i++)
if (samples *> v)*
v = samples*;*
return v;
}
}
public Heatmap(int aWidth, int aHeight, int aRadius)
{
width = aWidth;
height = aHeight;
radius = aRadius;
samples = new float[aWidth * aHeight];
CreateCircleMap();
}
// creates our circle map that is “copied” into our map
void CreateCircleMap()
{
circle = new float[radius * radius * 4];
for(int x = -radius; x < radius; x++)
{
for(int y = -radius; y < radius; y++)
{
float l = (xx+yy) / (float)(radius*radius);
float v = 0f;
if (l < 1f)
v = 1f - l;
circle[x + radius + radius * 2 * y] = v;
}
}
}
public void AddPoint(Vector2 aPos)
{
int px = Mathf.RoundToInt(aPos.x);
int py = Mathf.RoundToInt(aPos.y);
for (int x = -radius; x < radius; x++)
{
for (int y = -radius; y < radius; y++)
{
int ix = px + x;
int iy = py + y;
if (ix < 0 || iy < 0 || ix >= width || iy >= height)
continue;
samples[ix + iy * width] += circle[x + radius + radius * 2 * y];
}
}
}
public Texture2D GetImage(Gradient aGradient)
{
Texture2D tex = new Texture2D(width, height,TextureFormat.ARGB32, false);
float scale = 1f / MaxValue;
Color[] colors = new Color[samples.Length];
for (int i = 0; i < colors.Length; i++)
colors = aGradient.Evaluate(samples * scale);
tex.SetPixels(colors);
tex.Apply();
return tex;
}
}
I haven’t tested the class but it mainly should show what i ment. So you create a new Heatmap with your desired width and height (which directly referes to the resulting image), and the size of the “circle” area that is added to the map for each point.
You can put your data into the heatmap with the “AddPoint” method where the point has to be already in pixel coordinates.
You can, at any time, create a texture out of the heatmap data by using “GetImage”. GetImage takes a Gradient as parameter. That Gradient specifies which areas will be black / transparent and which are white. Keep in mind that “0” represents nothing/ transparent (first color in the gradient) while “1” means the last color in the gradient.
AddPoint shouldn’t be too slow, however
*[1]: http://docs.unity3d.com/ScriptReference/Gradient.html*_
*[2]: Google
What you’re probably going to want to do is render to a down-sampled screen buffer, then blur it and scale it up to screen space. Then you can do the drawing like you have in the screenshot, but it will look like the desired effect.
Look up RenderTargets to learn how to render to a separate buffer.