You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用C#代码实现灰度图为透明度蒙版的图像叠加?附OpenCV示例

图像蒙版叠加的C#实现方案(WPF原生/EmguCV/OpenCV优化)

一、WPF原生C#实现(无需第三方库)

如果不想依赖第三方库,直接用WPF自带的System.Windows.Media.Imaging命名空间即可完成纯C#代码实现,核心是将灰度蒙版的像素值转为目标图像的Alpha通道:

using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.IO;

public static void WpfImageOverlay(string backgroundPath, string maskPath, string outputPath)
{
    // 读取背景图
    BitmapImage background = new BitmapImage();
    background.BeginInit();
    background.UriSource = new Uri(backgroundPath);
    background.CacheOption = BitmapCacheOption.OnLoad;
    background.EndInit();

    // 读取灰度蒙版图
    BitmapImage mask = new BitmapImage();
    mask.BeginInit();
    mask.UriSource = new Uri(maskPath);
    mask.CacheOption = BitmapCacheOption.OnLoad;
    mask.EndInit();

    // 创建可写位图用于像素级处理
    WriteableBitmap resultBitmap = new WriteableBitmap(
        background.PixelWidth, background.PixelHeight, 
        background.DpiX, background.DpiY, 
        PixelFormats.Pbgra32, null);

    // 锁定内存,准备写入数据
    resultBitmap.Lock();

    int stride = resultBitmap.PixelWidth * 4;
    byte[] backgroundData = new byte[stride * resultBitmap.PixelHeight];
    // 复制背景图像素数据
    background.CopyPixels(backgroundData, stride, 0);

    // 读取灰度蒙版数据(单通道)
    byte[] maskData = new byte[resultBitmap.PixelWidth * resultBitmap.PixelHeight];
    mask.CopyPixels(maskData, resultBitmap.PixelWidth, 0);

    // 将灰度值映射为Alpha通道:0全透明,255完全不透明
    for (int y = 0; y < resultBitmap.PixelHeight; y++)
    {
        for (int x = 0; x < resultBitmap.PixelWidth; x++)
        {
            int pixelIndex = y * stride + x * 4;
            backgroundData[pixelIndex + 3] = maskData[y * resultBitmap.PixelWidth + x];
        }
    }

    // 写入处理后的像素数据并解锁
    resultBitmap.WritePixels(new Int32Rect(0, 0, resultBitmap.PixelWidth, resultBitmap.PixelHeight), backgroundData, stride, 0);
    resultBitmap.Unlock();

    // 保存为JPG文件
    using (FileStream fs = new FileStream(outputPath, FileMode.Create))
    {
        JpegBitmapEncoder encoder = new JpegBitmapEncoder();
        encoder.Frames.Add(BitmapFrame.Create(resultBitmap));
        encoder.QualityLevel = 90;
        encoder.Save(fs);
    }
}

二、EmguCV实现(解决安装问题+简洁代码)

针对你安装EmguCV失败的问题,先明确正确的安装步骤:

  • 通过NuGet安装Emgu.CV和对应平台的运行时包(比如Windows平台选Emgu.CV.runtime.windows)
  • 确保项目的.NET版本与包兼容,且平台目标设置为x64/x86(避免Any CPU导致的依赖加载失败)

安装完成后,用EmguCV实现蒙版叠加的代码会比原生OpenCV更简洁:

using Emgu.CV;
using Emgu.CV.CvEnum;

public static void EmguCvImageOverlay(string backgroundPath, string maskPath, string outputPath)
{
    // 读取背景图(彩色)和灰度蒙版
    Mat background = CvInvoke.Imread(backgroundPath, ImreadModes.Color);
    Mat mask = CvInvoke.Imread(maskPath, ImreadModes.Grayscale);

    // 将灰度蒙版转为Alpha通道,与背景图合并为RGBA格式
    Mat rgbaResult = new Mat();
    CvInvoke.Merge(new[] { background, mask }, rgbaResult);

    // 保存结果
    CvInvoke.Imwrite(outputPath, rgbaResult);
}

如果需要将前景图通过蒙版叠加到背景,可改用CvInvoke.AddWeighted实现混合:

public static void EmguCvForegroundOverlay(string backgroundPath, string foregroundPath, string maskPath, string outputPath)
{
    Mat background = CvInvoke.Imread(backgroundPath, ImreadModes.Color);
    Mat foreground = CvInvoke.Imread(foregroundPath, ImreadModes.Color);
    Mat mask = CvInvoke.Imread(maskPath, ImreadModes.Grayscale);

    // 归一化蒙版值为0-1范围,用于混合权重
    Mat normalizedMask = new Mat();
    mask.ConvertTo(normalizedMask, DepthType.Cv32F, 1.0 / 255.0);

    Mat result = new Mat();
    // 前景图按蒙版权重混合到背景
    CvInvoke.AddWeighted(foreground, normalizedMask.GetValue<float>(0,0), background, 1 - normalizedMask.GetValue<float>(0,0), 0, result);

    CvInvoke.Imwrite(outputPath, result);
}

三、现有OpenCV代码的优化建议

你当前的OpenCV代码可以简化,无需多次位运算,直接将灰度蒙版作为Alpha通道合并即可:

public static void OptimizedOpenCvOverlay(string background_file, string mask_file, string output_file)
{
    Mat background = Cv2.ImRead(background_file, ImreadModes.Color);
    Mat mask = Cv2.ImRead(mask_file, ImreadModes.Grayscale);

    // 合并背景图与灰度蒙版为RGBA图像
    Mat rgbaResult = new Mat();
    Cv2.Merge(new[] { background, mask }, rgbaResult);

    Cv2.ImWrite(output_file, rgbaResult);
}

如果你的蒙版是带Alpha通道的PNG文件,直接用AddWeighted实现透明叠加会更直观。

内容的提问来源于stack exchange,提问作者net-on

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 23:45:37