依赖:
using OpenCvSharp;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Imaging;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WinFormsApp1
{
public partial class Form1 : Form
{
public Form1()
{
int threshold = 255 - 20;
InitializeComponent();
Bitmap dstBitmap = null;
using (Image image = Image.FromFile(@"test2.bmp"))
{
using (Bitmap bitmap = new Bitmap(image))
{
using (Mat src = OpenCvSharp.Extensions.BitmapConverter.ToMat(bitmap))//bitmap转 mat
{
using (Mat matMask = new Mat(src.Rows, src.Cols, MatType.CV_8UC4))
{
//去除白色背景,得到人物的遮罩图
RenderMask(src, matMask, threshold);
//接下来使用上步骤的图做为遮罩对原始帧图像进行背景透明处理
using (Mat dst = new Mat(src.Rows, src.Cols, MatType.CV_8UC4))
{
MergeMask(src, dst, matMask);
dstBitmap = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(dst); // mat 转 bitmap
}
}
}
}
}
panel2.BackgroundImage = dstBitmap;
}
/// <summary>
/// 生成遮罩层
/// </summary>
/// <param name="src"></param>
/// <param name="matMask"></param>
/// <param name="threshold"></param>
private unsafe void RenderMask(Mat src, Mat matMask, int threshold)
{
int rows = src.Rows;
int cols = src.Cols;
for (int x = 0; x < rows; x++)
{
Vec4b* srcRow = (Vec4b*)src.Ptr(x);
Vec4b* maskRow = (Vec4b*)matMask.Ptr(x);
for (int y = 0; y < cols; y++)
{
var pData = srcRow + y;
var maskPData = maskRow + y;
byte blue = pData->Item0;
byte green = pData->Item1;
byte red = pData->Item2;
byte alpha = pData->Item3;
//阀值判断
if (blue <= threshold || green <= threshold || red <= threshold)
{
//把没超过阀值的转换成白色
maskPData->Item0 = 255;
maskPData->Item1 = 255;
maskPData->Item2 = 255;
maskPData->Item3 = 255;
}
else
{
//把超过阀值的转换成黑色
maskPData->Item0 = 0;
maskPData->Item1 = 0;
maskPData->Item2 = 0;
maskPData->Item3 = 0;
}
}
}
}
/// <summary>
/// 合并遮罩
/// </summary>
/// <param name="src">原始帧图像</param>
/// <param name="dst">合并结果</param>
/// <param name="alpha">透明遮罩</param>
public static void MergeMask(Mat src, Mat dst, Mat alpha)
{
using (ResourcesTracker t = new ResourcesTracker())
{
//split is used for splitting the channels separately
var srcBgr = t.T(Cv2.Split(src));
var alphaBgr = t.T(Cv2.Split(alpha));
var bgra = new[] { srcBgr[0], srcBgr[1], srcBgr[2], alphaBgr[3] };
Cv2.Merge(bgra, dst);
}
}
}
}