我有两个图像,第一个是白色背景,大小是512x512类型PNG位深度32:从这个图像中我想读取不是白色(云)的像素,并将它们放在另一个图像上。
第二个图像是我想把像素放在上面的图像:该图像尺寸也是512 × 512,但是类型为jpg,且Bith深度为24。
这个类是我用来阅读和设置像素的:
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Weather
{
public class RadarPixels
{
public RadarPixels(Bitmap image1, Bitmap image2)
{
ReadSetPixels(image1, image2);
}
private void ReadSetPixels(Bitmap image1 , Bitmap image2)
{
for(int x = 0; x < image1.Width; x++)
{
for(int y = 0; y < image1.Height; y++)
{
Color pixelColor = image1.GetPixel(x, y);
if (pixelColor != Color.FromArgb(255,255,255,255))
{
image2.SetPixel(x, y, pixelColor);
}
}
}
image2.Save(@"d:\mynewbmp.bmp");
image1.Dispose();
image2.Dispose();
}
}
}
以表格1的形式使用:
public Form1()
{
InitializeComponent();
RadarPixels rp = new RadarPixels(
new Bitmap(Image.FromFile(@"D:\1.png")),
new Bitmap(Image.FromFile(@"D:\2.jpg")));
}
其中1.png是具有白色背景的图像。
图像mynewbmp.bmp的结果是
不知道为什么它有一些白色边框周围的设置像素,如果它复制了所有的像素颜色的权利。
如果我把Color.FromArgb(255,255,255,255)的alpha值从255改为1或100,它会使mynewbmp.bmp和1.png一样,只有当alpha值为255时,它才更接近我想要的。
2条答案
按热度按时间brccelvz1#
正如其他人所说,有些像素不是纯白的,所以它们包含在最终的图像中。jtxkopt设置容差的解决方案很棒,但根据输入图像的质量和边缘的平滑度,容差可能需要不断调整以获得良好的效果。
最后,您的解决方案和Jtxkopt的解决方案都模拟了一个二进制掩码。这意味着您基于一个掩码图像将两个图像合成在一起,而该掩码图像只有2个值,黑色和白色。如果一个像素是黑色绘制图像1,如果一个像素是白色,则绘制image2。只有在您的情况下,您的2个值是白色和非白色。这是理论上的二进制掩码图像,只有黑色和白色像素:
二进制蒙版有非常粗糙的边缘,有时被称为"裁剪"蒙版,因为它就像用sizzors裁剪东西。创建二进制蒙版时,主要问题是试图确定哪些像素变白,哪些像素变黑,问题几乎总是在事物的边缘,jtxkopt的公差解决方案只是帮助做出决定并画出最终的界限。用户Andy建议使用MakeTransparent,但其结果与二进制遮罩类似,因为您为其指定1种颜色来决定哪些应该透明,哪些不应该透明(打开或关闭)。
合成两张图像的另一种方法是使用灰度蒙版。您可以使用许多灰色阴影来描述如何将两张图像混合在一起,而不是使用黑色和白色。如果像素是纯白和纯黑,则可以获得二元蒙版的所有优点,但如果像素是灰色,则可以根据其灰度值将两张图像混合在一起。这会创建更平滑的合成。下面是灰度蒙版:
下面是一个简单的解决方案,它获取每个像素,转换为一个简单的灰色像素,并使用该灰色像素设置image1的Alpha通道(透明度),以便可以将其合成到image2的顶部。
结果是:
这种方法有优点也有缺点,优点是不必调整容差值,而且生成的图像不只是图像1中的像素和图像2中的一些像素,像素是从两幅图像中混合出来的。2缺点是云有点透明,不那么明显。3这可以通过调整灰度掩模的对比度来解决,这样亮的区域更亮,暗的区域更暗。或者,您可以将image1多次合成到image2上以获得"累加"效果。或者,您可以添加另一个变量以减少或增加最终alpha值。
我希望这个替代解决方案是有用的。
更清楚地说,在这个解决方案中,我们在使用alpha通道的值之前反转灰色像素。这是因为alpha通道将0视为不可见,将255视为可见。因此,我们希望通过从255中减去像素,将白色255反转为黑色0。最终结果是反转的灰度遮罩,如下所示:
此时,越接近白色的东西在合成图中越明显。由于此灰度图像中的云有点偏深灰色,它们将与背景图像混合并失去一点活力。我们希望调整此图像,使黑色保持黑色,但灰色变得更亮以恢复活力。
通过一个简单的改变,我们可以忽略所有黑色的0值,因为我们希望它们保持不可见,但增加所有其他值的alpha。
这就像一个二进制蒙版。所有黑色值将保持不可见,所有非黑色值完全可见。但这违背了使用灰度蒙版的目的。但我们可以设置一个"容差"值如下:
这将结合灰度解决方案和"容差"解决方案。例如,如果我们将容差设置为
64
,这意味着任何大于64
的灰度值将100%可见,而任何低于64
的灰度值将不可见或略微可见。这意味着白色边缘(这是原来的问题)不会完全去除,只会与背景柔和地结合。所以这个解决方案只是"软化边缘"。以下是公差为64时的结果:
最终代码为:
tyky79it2#
如注解中所述,白色像素并不完全是白色的。因此,您应该计算到白色的距离,并检查计算出的距离是否大于某个容差值。
要获得所需结果,应调整以下公差值。