问题描述
所以我使用WriteableBitmapEx在Windows RT的应用程序。我试图实现使用Sobel算子的图像边缘检测。我一直在使用.Convolute()成功申请x和y都检测到的内核的形象,但现在我卡住了添加两个图像之一。
中的问题是,这两个图象的所有象素似乎有透明度值0(因此在ARGB的A)中。我可以没有问题显示在自己的两个图像,但加入他们给了我只是一个黑色的画面。
所以我的问题是:
- 为什么透明度设置为0卷积后的每个像素
- 为什么我还可以显示图像没有它全黑的?
- 为什么黑人当我添加两个图像?
- 是否有合并两个图像更好的办法? BLIT unfortunatley似乎不支持这种像素加入。但真正的ForEach很慢...
有关calrification,这是我到目前为止的代码。我可以显示wbmpY和wbmpX,但finalbmp完全是黑色的。
公共INT [,] sobelY =新INT [3, 3] {{1,2,1},{0,0,0},{-1,-2,-1}};
公众诠释[,] sobelX =新INT [3,3] {{-1,0,1},{-2,0,2},{-1,0,1}};
公共无效修剪(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);
}
公共WriteableBitmap的combineSobel(WriteableBitmap的IMG,WriteableBitmap的IMG2)
{
INT高度= img.PixelHeight;
INT宽度= img.PixelWidth;
WriteableBitmap的结果= img.Clone();
的for(int x = 0; X<宽度; X ++)
{
为(INT Y = 0; Y<高度; Y ++)
{
色imgColor = img.GetPixel(X,Y);
色彩img2Color = img2.GetPixel(X,Y);
色彩newColor = Color.FromArgb(
Math.Min((字节)的Math.sqrt(Math.Pow(imgColor.A,2)+ Math.Pow(img2Color.A,2)),(字节)255),
Math.Min((字节)的Math.sqrt(Math.Pow(imgColor.R,2)+ Math.Pow(img2Color.R,2)),(字节)255),
Math.Min((字节)的Math.sqrt(Math.Pow(imgColor.G,2)+ Math.Pow(img2Color.G,2)),(字节)255),
Math.Min ((字节)的Math.sqrt(Math.Pow(imgColor.B,2)+ Math.Pow(img2Color.B,2)),(字节)255)$ b $二);
result.SetPixel(X,Y,newColor);
}
}
返回结果;
}
卷积被应用在所有可用的频道。不仅具有红,绿,蓝(它是在此情况下,所希望的)进行处理,而且alpha通道。这导致零(100%透明)的α值。请看下面的例子:
1 0 -1 255 255 255
2 0 -2超过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对所有像素
技术上这一切都很好,它不随检测到任何边缘Alpha通道。但是在功能上,这是不是你在这种情况下想要的东西。如果这种行为是不希望的,要么你可以跳过处理alpha通道(如果源让你)或重置阿尔法255之后。
我要推测会在屏幕上显示黑色图像,因为我没有使用的技术经验。很多框架的第一个图像重置为纯色(假设它的黑色在这种情况下)。因此,如果你处理的透明图像(或部分)以前的形象会不会流血通过这是必需的。加入卷积(透明)图像此纯色,将导致在同一个固体颜色。 。为此图像将显示全黑
请注意:combineSobel使用的所有通道,但由于它被转换之前,灰度图,你可能要优化色彩的创造。
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:
- Why is the transparency set to 0 for every pixel after the convolution?
- Why can I still display the Image without it being all black?
- Why is it black when I add two Images?
- Is there a better way of combining two Images? Blit unfortunatley doesn't seem to support this kind of pixel-adding. But ForEach really is slow...
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.
这篇关于Sobel算子和放大器;卷积WriteableBitmapEx的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!