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

三、人物放进背景图片
合并图片函数
private unsafe void MergeImageAt(Mat bg, Mat src, Func<Vec3b, bool> func)
{
Cv2.Resize(bg, bg, src.Size());//以背景人物大小为准
for (int i = 0; i < bg.Rows; i++)
{
for (int j = 0; j < bg.Cols; j++)
{
if (func(src.At<Vec3b>(i, j)))
{
bg.At<Vec3b>(i, j) = src.At<Vec3b>(i, j);
}
}
}
}
续上上一步,加上合并图片的步骤
using (ResourcesTracker t = new ResourcesTracker())
{
Bitmap bitmap = new Bitmap(pictBox_origin.Image);
var mat = BitmapConverter.ToMat(bitmap);
var mat_bg = t.T(Cv2.ImRead("images/bg2.jpg"));
RemoveImageScreen(mat,
p =>
{
int max = Math.Max(p.Item0, Math.Max(p.Item1, p.Item2));
if (max == p.Item1 && p.Item1 > 30)
return true;
return false;
});
MergeImageAt( mat_bg, mat,
p =>
{
if (p == new Vec3b(0, 0, 0))
{
return false;
}
return true;
}
);
pictBox_result.Image = BitmapConverter.ToBitmap(mat_bg);
}
效果如图:

四、操作视频帧图片,实现替换绿幕
和图片的区别,就是需要先逐帧获取 视频/摄像机 的图片,然后按上述操作进行
直接附上完整Demo(已经将两个函数改为指针操作,大家可以先试试原来的At操作,可以明显看到视频是慢速播放)
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<Vec3b, bool> func)
{
Vec3b* start = (Vec3b*)src.DataStart;
Vec3b* end = (Vec3b*)src.DataEnd;
for (Vec3b* p = start; p <= end; p++)
{
if (func(*p))
{
*p = new Vec3b(0, 0, 0);
}
}
}
private static unsafe void MergeImage(Mat bg, Mat src, Func<Vec3b, bool> func)
{
Cv2.Resize(bg, bg, src.Size());
Vec3b* bg_pointer = (Vec3b*)bg.DataStart;
Vec3b* start = (Vec3b*)src.DataStart;
Vec3b* end = (Vec3b*)src.DataEnd;
for (Vec3b* p = start; p <= end; p++, bg_pointer++)
{
*bg_pointer = func(*p) ? *p : *bg_pointer;
}
}
}
}
素材:

效果展示:(这是视频的一张截图)

完成!!!
图片去绿幕的效果还是很粗糙的,后续会持续更新改进方法,希望大家点赞+关注
并欢迎大家留言...
C# OpenCVSharp图像入门_给绿幕图片视频加背景的更多相关文章
- 在Android用vulkan完成蓝绿幕扣像
效果图(1080P处理) 因为摄像头开启自动曝光,画面变动时,亮度变化导致扣像在转动时如上. 源码地址vulkan_extratest 这个demo主要测试二点,一是测试ndk camera集成效果, ...
- AI目标分割能力,无需绿幕即可实现快速视频抠图
绿幕抠图是影视制作过程中常见的技术手段,常用于视频中抠除并替换背景,通过后期加工实现视频剪辑制作的更多可能性.然而,绿幕抠图技术制作成本费时费力,无法应用于日常生活. 华为视频编辑服务近期上线目标分割 ...
- 09_android入门_采用android-async-http开源项目的GET方式或POST方式实现登陆案例
根据08_android入门_android-async-http开源项目介绍及使用方法的介绍,我们通过最常见的登陆案例进行介绍android-async-http开源项目中有关类的使用.希望对你学习 ...
- Spring_MVC_教程_快速入门_深入分析
Spring MVC 教程,快速入门,深入分析 博客分类: SPRING Spring MVC 教程快速入门 资源下载: Spring_MVC_教程_快速入门_深入分析V1.1.pdf Spring ...
- 09_android入门_採用android-async-http开源项目的GET方式或POST方式实现登陆案例
依据08_android入门_android-async-http开源项目介绍及用法的介绍,我们通过最常见的登陆案例进行介绍android-async-http开源项目中有关类的使用.希望对你学习an ...
- 『TensorFlow』第九弹_图像预处理_不爱红妆爱武装
部分代码单独测试: 这里实践了图像大小调整的代码,值得注意的是格式问题: 输入输出图像时一定要使用uint8编码, 但是数据处理过程中TF会自动把编码方式调整为float32,所以输入时没问题,输出时 ...
- 07_android入门_採用HttpClient的POST方式、GET方式分别实现登陆案例
1.简单介绍 HttpClient 是 Apache Jakarta Common 下的子项目,能够用来提供高效的.最新的.功能丰富的支持 HTTP 协议的客户端编程工具包,而且它支持 HTTP 协议 ...
- OpenCvSharp 图像旋转
/// <summary> /// 图像旋转 /// </summary> private Mat MatRotate(Mat src, float angle) { Mat ...
- 【笔记目录2】【jessetalk 】ASP.NET Core快速入门_学习笔记汇总
当前标签: ASP.NET Core快速入门 共2页: 上一页 1 2 任务27:Middleware管道介绍 GASA 2019-02-12 20:07 阅读:15 评论:0 任务26:dotne ...
- Camtasia绿幕素材的视频合成
随着科技和互联网的快速发展,让越来越多的人喜欢上了视频的各项制作,那么怎么让两个视频进行合成并一起播放呢?操作很简单,下面来讲解具体的操作步骤.小编选用的是Camtasia2019版本的视频编辑软件进 ...
随机推荐
- 批x网,登录加密(通过元素绑定的监听事件来找到加密函数)
网站 base64加密 aHR0cHM6Ly93d3cucGlnYWkub3JnLw== 逆向分析 https://blog.csdn.net/a_123_4/article/details/1208 ...
- 2022-10-07:给定员工的 schedule 列表,表示每个员工的工作时间。 每个员工都有一个非重叠的时间段 Intervals 列表,这些时间段已经排好序。 返回表示 所有 员工的 共同,正
2022-10-07:给定员工的 schedule 列表,表示每个员工的工作时间. 每个员工都有一个非重叠的时间段 Intervals 列表,这些时间段已经排好序. 返回表示 所有 员工的 共同,正数 ...
- 2020-10-04:java中GC Root 对象有哪些?
福哥答案2020-10-04:#福大大架构师每日一题# 简单回答:1.局部变量.2.静态引用的对象.3.常量引用的对象.4.JNI引用的对象. 中级回答:1.虚拟机栈(栈帧中的本地变量表)中引用的对象 ...
- 2022-05-19:给定一个数组arr,给定一个正数M, 如果arr[i] + arr[j]可以被M整除,并且i < j,那么(i,j)叫做一个M整除对。 返回arr中M整除对的总数量。 来自微软。
2022-05-19:给定一个数组arr,给定一个正数M, 如果arr[i] + arr[j]可以被M整除,并且i < j,那么(i,j)叫做一个M整除对. 返回arr中M整除对的总数量. 来自 ...
- 2021-04-15:给定一个由字符串组成的数组strs,必须把所有的字符串拼接起来,返回所有可能的拼接结果中,字典序最小的结果。
2021-04-15:给定一个由字符串组成的数组strs,必须把所有的字符串拼接起来,返回所有可能的拼接结果中,字典序最小的结果. 福大大 答案2021-04-15: "b"和&q ...
- vue全家桶进阶之路5:DOM文档对象模型
一.DOM对象 DOM,全称"DocumentObjectModel(文档对象模型)",它是由W3C组织定义的一个标准. 在前端开发时,我们往往需要在页面某个地方添加一个元素或者删 ...
- Python Numpy 切片和索引(高级索引、布尔索引、花式索引)
张量(Tensor).标量(scalar).向量(vector).矩阵(matrix) Python Numpy 切片和索引(高级索引.布尔索引.花式索引) Python NumPy 广播(Broad ...
- 使用vite的创建vue项目
首先也是打开项目文件目录 在标签处快速打上cmd即可打开cmd窗口 然后按照顶部图进行操作即可完成 安装完成的样子如下图 紧接着输入 npm run dev 将Local 的IP复制到浏览器打开,出现 ...
- Mybatis查询
查询 查询的数据为单条实体类 使用实体类进行接受即可,或者使用list,map接口均可.后面两者比较浪费 使用实体类接受 mapper接口: User selectUserById(int useri ...
- AcWing 1023. 买书
小明手里有n元钱全部用来买书,书的价格为10元,20元,50元,100元. 问小明有多少种买书方案?(每种书可购买多本) 输入格式 一个整数 n,代表总共钱数. 输出格式 一个整数,代表选择方案种数. ...