首页 > 解决方案 > C# - 使图像的黑色像素透明

问题描述

我有一个大问题。

我有一个代码来比较 2 个图像像素。它在第二个图像像素内寻找第一个图像像素。

 private bool FindBitmap12(Bitmap bmpNeedle, Bitmap bmpHaystack, out Point location)
    {
        if (bmpNeedle == null || bmpHaystack == null)
        {
            location = new Point();
            return false;
        }
        for (int outerX = 0; outerX < bmpHaystack.Width - bmpNeedle.Width; outerX++)
        {
            for (int outerY = 0; outerY < bmpHaystack.Height - bmpNeedle.Height; outerY++)
            {
                for (int innerX = 0; innerX < bmpNeedle.Width; innerX++)
                {
                    for (int innerY = 0; innerY < bmpNeedle.Height; innerY++)
                    {
                        Color cNeedle = bmpNeedle.GetPixel(innerX, innerY);
                        Color cHaystack = bmpHaystack.GetPixel(innerX + outerX, innerY + outerY);
                        if (cNeedle.R != cHaystack.R || cNeedle.G != cHaystack.G || cNeedle.B != cHaystack.B)
                        {
                            goto notFound;
                        }
                    }
                }
                location = new Point(outerX, outerY);
                return true;
            notFound:
                continue;
            }
        }
        location = Point.Empty;
        return false;
    }

上面的代码完美运行。

问题是现在我需要比较一张上面有黑色像素的图片和一张没有黑色像素的图片。所以发生的情况是上面的代码返回图片不同。

所以我想:嘿,让这个黑色像素透明!

我做了这个代码:

Rectangle mouseNewRect = new Rectangle(new Point(x - 125, y - 125), new Size(250, 250));
Bitmap myBitmap2 = new Bitmap(mouseNewRect.Width, mouseNewRect.Height);
Bitmap myBitmap3 = new Bitmap("Images\\xd1.png");
myBitmap3.MakeTransparent(Color.Black);
Graphics g = Graphics.FromImage(myBitmap2);
g.CopyFromScreen(mouseNewRect.Left, mouseNewRect.Top, 0, 0, myBitmap2.Size, CopyPixelOperation.SourceCopy);

myBitmap2 == 大图;

myBitmap3 == 具有黑色像素的图片,将在 myBitmap2 中进行比较。

所以你们看到了,我把myBitmap3的黑色像素设置为透明的,所以当myBitmap3和myBitmap2比较时,结果应该是:嘿,我们在myBitmap2里面找到了myBitmap3的像素!

我不知道为什么,但即使使黑色像素透明,结果:

bool sucess2 = FindBitmap12(myBitmap3, myBitmap2, out location);

== 假的。所以我让黑色像素透明,但不知何故,成功2 ==假。

我尝试删除https://pixlr.com上的黑色像素,在这个黑色像素中留下一个“空白”空间,也是 sucess2 == false 的结果。

Some1 知道如何删除 myBitmap3 的黑色像素吗?

谢谢。

编辑:在这部分:

Color cNeedle = bmpNeedle.GetPixel(innerX, innerY);
Color cHaystack = bmpHaystack.GetPixel(innerX + outerX, innerY + outerY);
if (cNeedle.R != cHaystack.R || cNeedle.G != cHaystack.G || cNeedle.B != cHaystack.B)
                        {
                            goto notFound;
                        }

也许我可以做一个“如果”,如果找到一个黑色像素,忽略它并继续搜索,因为这个黑色像素不存在?

标签: c#imagepixel

解决方案


在不深入API的情况下,我假设 MakeTransparent 方法不会改变像素的 RGB 值。它只是在调色板和信息中的某处设置,不应在屏幕上绘制此特定颜色。这就是为什么当您比较 RGB 值时它们仍然相同的原因。

我没有测试或验证我的答案,但这是我对图像工作一段时间的假设。

如果我是对的,最简单的方法可能是仅比较调色板中未标记为透明颜色的像素。

更新

似乎没有检查系统调色板的简单方法。请参阅https://docs.microsoft.com/en-us/windows/desktop/gdi/system-palette

相反:您可以尝试比较像素的 alpha 分量吗?如果您已将像素的 alpha 值(通过 pixlr/gimp/photoshop)设置为透明,则它的值应为 0。因此您的代码将是:

Color cNeedle = bmpNeedle.GetPixel(innerX, innerY);
Color cHaystack = bmpHaystack.GetPixel(innerX + outerX, innerY + outerY);

bool isDifferentRGB = cNeedle.R != cHaystack.R || cNeedle.G != cHaystack.G || cNeedle.B != cHaystack.B;
bool isTransparent = cNeedle.A == 0;

if (isDifferentRGB && !isTransparent)
{
     goto notFound;
}

推荐阅读