翼度科技»论坛 编程开发 .net 查看内容

C# OpenCVSharp图像入门_给绿幕图片视频加背景

6

主题

6

帖子

18

积分

新手上路

Rank: 1

积分
18
  OpenCV的全称是Open Source Computer Vision Library,是一个跨平台的计算机视觉库。OpenCV是由英特尔公司发起并参与开发,以BSD许可证授权发行,可以在商业和研究领域中免费使用。OpenCV可用于开发实时的图像处理计算机视觉以及模式识别程序。该程序库也可以使用英特尔公司的IPP进行加速处理。
  OpenCVSharp是一个.Net平台使用的OpenCV封装库。现在网上关于openCV的教程基本都是c++和python,如果是C#方向,可以跟着这两个语言的步骤自己写demo。
  开始我们今天的课程。
一、分析
  这个功能只要是给绿幕人物加上背景,比如:在直播的时候,因为私密或者其他原因,不想透露出背景
  设想只需要购买一块绿幕,然后上网挑选一张自己喜欢的背景照片,就可以拥有一个好看的背景。
  如何替换视频背景呢?我们一步一步入门!!
  1)绿幕相片扣出人物
  2)人物放进背景图片
  3)操作视频帧图片,实现替换绿幕。
  需要安装的nuget包,注意查看依赖项选版本
  1. OpenCvSharp4
  2. OpenCvSharp4.runtime.win
复制代码
二、绿幕相片扣出人物
  只展示核心代码
  1)识别绿幕函数(一般操作图片是使用指针的,为了更好理解,我们这里先At执行,后面会讲使用指针改进)
  1.         //删除绿幕
  2.         private unsafe void RemoveImageScreen(Mat src, Func<Vec3b, bool> func)
  3.         {
  4.             for (int i = 0; i < src.Rows; i++)
  5.             {
  6.                 for (int j = 0; j < src.Cols; j++)
  7.                 {
  8.                     if (func(src.At<Vec3b>(i, j)))
  9.                     {
  10.                         src.At<Vec3b>(i, j) = new Vec3b(0, 0, 0);
  11.                     }
  12.                 }
  13.             }
  14.         }
复制代码
  2)选择图片并清除绿幕
  1.             using (ResourcesTracker t = new ResourcesTracker())
  2.             {
  3.                 Bitmap bitmap = new Bitmap(pictBox_origin.Image);
  4.                 var mat = BitmapConverter.ToMat(bitmap);
  5.                 RemoveImageScreen(mat,
  6.                     p =>
  7.                     {
  8.                         int max = Math.Max(p.Item0, Math.Max(p.Item1, p.Item2));
  9.                         if (max == p.Item1 && p.Item1 > 30) //BGR,当G最大时且大于30时,可以根据实际调节这个阈值
  10.                             return true;
  11.                         return false;
  12.                     });
  13.                 pictBox_result.Image = BitmapConverter.ToBitmap(mat_bg);<br>        }
复制代码
  效果展示:(我是跟着杨神的思路写的这个程序,素材就直接用杨神了,这篇是入门级别,可以看完我这篇再去观摩杨神的)
  杨中科(就是下图这个帅哥):https://www.bilibili.com/read/cv8850462?spm_id_from=333.999.0.0
  

 三、人物放进背景图片
  合并图片函数
  1.         private unsafe void MergeImageAt(Mat bg, Mat src, Func<Vec3b, bool> func)
  2.         {
  3.             Cv2.Resize(bg, bg, src.Size());//以背景人物大小为准
  4.             for (int i = 0; i < bg.Rows; i++)
  5.             {
  6.                 for (int j = 0; j < bg.Cols; j++)
  7.                 {
  8.                     if (func(src.At<Vec3b>(i, j)))
  9.                     {
  10.                         bg.At<Vec3b>(i, j) = src.At<Vec3b>(i, j);
  11.                     }
  12.                 }
  13.             }
  14.         }
复制代码
  续上上一步,加上合并图片的步骤
  1.             using (ResourcesTracker t = new ResourcesTracker())
  2.             {
  3.                 Bitmap bitmap = new Bitmap(pictBox_origin.Image);
  4.                 var mat = BitmapConverter.ToMat(bitmap);
  5.                 var mat_bg = t.T(Cv2.ImRead("images/bg2.jpg"));
  6.                 RemoveImageScreen(mat,
  7.                     p =>
  8.                     {
  9.                         int max = Math.Max(p.Item0, Math.Max(p.Item1, p.Item2));
  10.                         if (max == p.Item1 && p.Item1 > 30)
  11.                             return true;
  12.                         return false;
  13.                     });
  14.                 MergeImageAt( mat_bg, mat,
  15.                     p =>
  16.                     {
  17.                         if (p == new Vec3b(0, 0, 0))
  18.                         {
  19.                             return false;
  20.                         }
  21.                         return true;
  22.                     }
  23.                     );
  24.                 pictBox_result.Image = BitmapConverter.ToBitmap(mat_bg);
  25.             }
复制代码
  效果如图:
  

 四、操作视频帧图片,实现替换绿幕
  和图片的区别,就是需要先逐帧获取 视频/摄像机 的图片,然后按上述操作进行
  直接附上完整Demo(已经将两个函数改为指针操作,大家可以先试试原来的At操作,可以明显看到视频是慢速播放)
[code]using OpenCvSharp;using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;namespace MyOpenCV{    public static class RemoveGreenScreen    {        public static unsafe void Start()        {            //VideoCapture videoCapture = new VideoCapture(1, VideoCaptureAPIs.DSHOW);//摄像头            VideoCapture videoCapture = new VideoCapture(@"images/绿幕视频.mp4");            using (videoCapture)            using (Mat frameMat = new Mat())            using (Mat mat_bg = Cv2.ImRead("images/bg.png"))            {                if (videoCapture.CaptureType == CaptureType.Camera)//如果是摄像头                {                    videoCapture.FrameWidth = 800;                    videoCapture.FrameHeight = 600;                    videoCapture.FourCC = "MJPG";                }                while (true)                {                    if (!videoCapture.Read(frameMat))                    {                        //如果是视频文件,从头部开始播放                        if (videoCapture.CaptureType == CaptureType.File)                        {                            videoCapture.PosFrames = 0;                        }                        continue;                    }                    RemoveImageScreen(frameMat,                        p =>                        {                            int max = Math.Max(p.Item0, Math.Max(p.Item1, p.Item2));                            if (max == p.Item1 && p.Item1 > 30)                                return true;                            return false;                        });                    var bg_clone = mat_bg.Clone();                    MergeImage(bg_clone, frameMat,                        p =>                        {                            if (p == new Vec3b(0, 0, 0))                            {                                return false;                            }                            return true;                        });                    Cv2.ImShow("press any key to quit", bg_clone);                    if (Cv2.WaitKey(1) > 0)                    {                        break;                    }                }            }            Cv2.DestroyAllWindows();        }        private static unsafe void RemoveImageScreen(Mat src, Func func)        {            Vec3b* start = (Vec3b*)src.DataStart;            Vec3b* end = (Vec3b*)src.DataEnd;            for (Vec3b* p = start; p

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x

举报 回复 使用道具