So I'm using WriteableBitmapEx for an app on Windows RT. I'm trying to implement edge detection on an image using the sobel operator. I have successfully applied both kernels for x and y detection onto the image using .Convolute(), but now I'm stuck adding both images to one. The problem is, that all the pixels of both images seem to have the value 0 for transparency (so the A in ARGB). I can display both images on their own without a Problem, but adding them gives me just a black picture. So my questions are:
For calrification, here's my code so far. I can display both wbmpY and wbmpX, but finalbmp is completely black.
public int[,] sobelY = new int[3, 3] { { 1, 2, 1 }, { 0, 0, 0 }, { -1, -2, -1 } };
public int[,] sobelX = new int[3, 3] { { -1, 0, 1 }, { -2, 0, 2 }, { -1, 0, 1 } };
public void trim(WriteableBitmap wbmp)
{
var graybmp = wbmp.Clone();
graybmp.ForEach(toGrayscale);
var wbmpY = graybmp.Clone();
var wbmpX = graybmp.Clone();
wbmpY = wbmpY.Convolute(sobelY, 1, 0);
wbmpX = wbmpX.Convolute(sobelX, 1, 0);
var finalbmp = combineSobel(wbmpX, wbmpY);
}
public WriteableBitmap combineSobel(WriteableBitmap img, WriteableBitmap img2)
{
int height = img.PixelHeight;
int width = img.PixelWidth;
WriteableBitmap result = img.Clone();
for (int x = 0; x < width; x++)
{
for (int y = 0; y < height; y++)
{
Color imgColor = img.GetPixel(x, y);
Color img2Color = img2.GetPixel(x, y);
Color newColor = Color.FromArgb(
Math.Min((byte)Math.Sqrt(Math.Pow(imgColor.A, 2) + Math.Pow(img2Color.A, 2)), (byte)255),
Math.Min((byte)Math.Sqrt(Math.Pow(imgColor.R, 2) + Math.Pow(img2Color.R, 2)), (byte)255),
Math.Min((byte)Math.Sqrt(Math.Pow(imgColor.G, 2) + Math.Pow(img2Color.G, 2)), (byte)255),
Math.Min((byte)Math.Sqrt(Math.Pow(imgColor.B, 2) + Math.Pow(img2Color.B, 2)), (byte)255)
);
result.SetPixel(x, y, newColor);
}
}
return result;
}
Convolution is applied over all the available channels. Not only red, green and blue (which is what you want in this case) are processed, but also the alpha channel. This results in an alpha value of zero (100% transparent). Consider the following example:
1 0 -1 255 255 255 2 0 -2 over 255 255 255 1 0 -1 255 255 255
1*255 0*255 -1*255 255 0 -255 2*255 0*255 -2*255 = 510 0 -510 1*255 0*255 -1*255 255 0 -255 2*255 + 510 + 3*0 - 2*255 - 510 = 0 for all pixels
Technically it's all fine, it doesn't detect any edges over the alpha channel. However functionally this is not what you want in this case. If this behavior is not desired, either you can skip processing the alpha channel (if the source allows you to) or reset alpha to 255 afterwards.
I'm going to speculate about the black image that will be shown on screen, because I do not have experience of the used technology. A lot of frameworks first reset the image to a solid color (assuming it's black in this case). This is required so that the previous image will not bleed through if you're dealing with transparent images (or parts of it). Adding the convoluted (transparent) image to this solid color, will result in the same solid color. Therefor the image will be shown all black.
Note: combineSobel uses all channels, but since it was converted to greyscale before, you might want to optimize the creation of colors.