# Getting normal map of an image

I'm trying to achieve the results in this tutorial: Link

So far, I was be able to do that;

with these;

    public PixelMap GetNormalMap(double strength)
{
var newMap = new PixelMap(Width, Height);

for (int i = 1; i < Width - 1; i++)
{
for (int j = 1; j < Height - 1; j++)
{
/*
[ a b c ]
[ d x e ]
[ f g h ]
*/
var a = this[i - 1, j - 1].Intensity;
var b = this[i, j - 1].Intensity;
var c = this[i + 1, j - 1].Intensity;
var d = this[i - 1, j].Intensity;
var e = this[i + 1, j].Intensity;
var f = this[i - 1, j + 1].Intensity;
var g = this[i, j + 1].Intensity;
var h = this[i + 1, j + 1].Intensity;

// sobel filter
double dX = (c + 2.0 * e + h) - (a + 2.0 * d + f);
double dY = (a + 2.0 * b + c) - (f + 2.0 * g + h);
double dZ = 1.0 / strength;

var v = new Vector3D(dX, dY, dZ);
v.Normalize();

newMap[i, j] = new Pixel(Pixel.Map(v.X), Pixel.Map(v.Y), Pixel.Map(v.Z), this[i, j].A);
}
}

return newMap;
}

public double Intensity
{
get { return (R + G + B) / (3.0 * 255); }
}

public static byte Map(double value)
{
return (byte)((value + 1.0) * (255 / 2.0));
}


The first issue is that the normal map colors are different on my image. Also, I was not be able to understand how the get the image in D (can be found in the middle of the linked article). I can upload all the code if the functions above are not enough.

Normal map after alpha map;

That is not really an accurate normal map, by the way. You are just sort of assuming that the regions of the image where the luminance varies correspond with surface contours. That is frequently the case, but not necessarily - particularly in a subject this filthy, there will be a lot of dirty areas that appear to a sobel filter as contours rather than just dark dirt stains.

Generating a normal map using a sobel filter usually involves a heightmap image (in the article you linked, you will notice that the silhouettes in figure A are a single color and that the resulting normal map only varies where that color transitions from white to black).

I think you might get more desirable results (the kind seen in the article you linked to) if you use the alpha channel instead of the "intensity" of the color image. You might also do a blur (figure B) before feeding it through the Sobel filter to achieve the same sort of results as figure C.

• I updated the question and added the new image with alpa map and blur. Dec 4, 2014 at 20:46
• @Cem: What happens if you use this instead: double dX = (f + 2.0 * g + h) - (a + 2.0 * b + c); double dY = (c + 2.0 * e + h) - (a + 2.0 * d + f);? Dec 4, 2014 at 21:00
• I got this s2.postimg.org/eo8987uih/Capture.png Dec 4, 2014 at 21:03
• @Cem: I suspect your RGB channels are winding up BGR at some point. Are you sure the channel layout is the same in your imaging software as you are writing here? To quickly confirm, I would manually swap the blue and red channels. newMap[i, j] = new Pixel(Pixel.Map(v.Z), Pixel.Map(v.Y), Pixel.Map(v.X), this[i, j].A); Dec 4, 2014 at 21:07
• Yes you are right :) I corrected it. s29.postimg.org/ihvlcm9nr/Capture.png Dec 4, 2014 at 21:13