C# OpenCvSharp 抠证件照的人物图像,并生成透明背景

依赖:
在这里插入图片描述
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);
        }

    }
}

}

  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值