介绍

绿幕抠图指将图片中的绿色扣去,并将该处的 alpha 分量设为 0,并将另外一张图片作为背景,以实现背景替换的功能,常用于电影和电视的制作场景。

最终效果

原始图片

绿幕抠图后效果

代码

这一块的代码改动,主要在像素着色器 shader。

ps shader

本文只是实现了最简单的绿幕抠图,对于这种比较完美的图片,抠图效果较好,对于其他图片还有较大的优化空间。

Texture2D tex : register(t0);
SamplerState samplerLinear : register(s0);struct VSOut
{float4 pos : SV_Position;float2 tex : TEXCOORD1;
};float4 MyPs(VSOut pIn) : SV_Target
{float4 sampleColor = tex.Sample(samplerLinear, pIn.tex);float dis = distance(float3(sampleColor.xyz), float3(0.0, 1.0, 0.0));return float4(sampleColor.xyz, step(0.4, dis));
}

原理

本文使用的绿幕抠图的原理比较简单,就是比较该点的 rgb 颜色和绿色之间的差距d,并设置一个阈值a,但差距小于阈值 a,则认为其他绿色,将其透明分量设为 0。

step

step(x,y) 当 x ≤y时,返回1,否则为 0。

具体代码

void Graphics::DrawPicture()
{InitEffect();/************************************* 输入装配阶段 **************************************/ //创建顶点缓存struct SimpleVertex{DirectX::XMFLOAT3 pos;DirectX::XMFLOAT2 tex;};SimpleVertex vertices[] ={{DirectX::XMFLOAT3(-0.5f, -0.5f, 0.5f), XMFLOAT2(0.0f, 1.0f)},{DirectX::XMFLOAT3(-0.5f,  0.5f, 0.5f),  XMFLOAT2(0.0f, 0.0f)},{DirectX::XMFLOAT3(0.5f,  0.5f, 0.5f),    XMFLOAT2(1.0f, 0.0f)},{DirectX::XMFLOAT3(0.5f, -0.5f, 0.5f),    XMFLOAT2(1.0f, 1.0f)},};D3D11_BUFFER_DESC verticsDesc = {};verticsDesc.ByteWidth = sizeof(vertices) * 5; // 字节数// 将 usage 设为 D3D11_USAGE_IMMUTABLE  D3D11_USAGE_DEFAULT 可行verticsDesc.Usage = D3D11_USAGE_IMMUTABLE; // 资源的使用,gpu和cpu 的读写权限 verticsDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; // 标识如何将资源绑定到 pipeline verticsDesc.CPUAccessFlags = 0; // CPU 的读写权限verticsDesc.MiscFlags = 0;verticsDesc.StructureByteStride = 0;D3D11_SUBRESOURCE_DATA resourceData = {};resourceData.pSysMem = vertices;resourceData.SysMemPitch = 0;resourceData.SysMemSlicePitch = 0;ID3D11Buffer* verticesBuffer = NULL;m_pDevice->CreateBuffer(&verticsDesc, &resourceData, &verticesBuffer);UINT strider = sizeof(SimpleVertex);UINT offset = 0;m_pContext->IASetVertexBuffers(0,               // start slot1,             // buffer 数量  (start slot ~ start slot + buffer number&verticesBuffer,// 顶点缓存&strider,     // 每组数据的字节数&offset);        // 偏移量DirectX::XMUINT3 index[] = {{0, 1, 2},{0, 2, 3}};D3D11_BUFFER_DESC indexDesc = {};indexDesc.ByteWidth = sizeof(index) * 2; // 字节数// 将 usage 设为 D3D11_USAGE_IMMUTABLE  D3D11_USAGE_DEFAULT 可行indexDesc.Usage = D3D11_USAGE_IMMUTABLE; // 资源的使用,gpu和cpu 的读写权限 indexDesc.BindFlags = D3D11_BIND_INDEX_BUFFER; // 标识如何将资源绑定到 pipeline indexDesc.CPUAccessFlags = 0; // CPU 的读写权限indexDesc.MiscFlags = 0;indexDesc.StructureByteStride = 0;resourceData.pSysMem = index;resourceData.SysMemPitch = 0;resourceData.SysMemSlicePitch = 0;ID3D11Buffer* indexBuffer = NULL;m_pDevice->CreateBuffer(&indexDesc, &resourceData, &indexBuffer);// 设置所引缓存m_pContext->IASetIndexBuffer(indexBuffer, DXGI_FORMAT_R32_UINT, 0);// 输入布局m_pContext->IASetInputLayout(m_inputLayout);// 图元拓扑结构m_pContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);/************************************* 顶点着色器阶段 **************************************/m_pContext->VSSetShader(m_pVertexShader, nullptr, 0);/************************************* 像素着色器阶段 **************************************/m_pContext->PSSetShader(m_pPixelShader, nullptr, 0);ID3D11Resource* inputResource = NULL;ID3D11ShaderResourceView* shaderResourceView = NULL;std::wstring path = L"res\\image\\tiger.png";CreateWICTextureFromFile(m_pDevice,path.c_str(),&inputResource,&shaderResourceView);m_pContext->PSSetShaderResources(0, 1, &shaderResourceView);ID3D11SamplerState* sampler;D3D11_SAMPLER_DESC sampleDesc = {};sampleDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;sampleDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; // 平铺整数个sampleDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP;sampleDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP;sampleDesc.ComparisonFunc = D3D11_COMPARISON_NEVER;sampleDesc.MinLOD = 0;sampleDesc.MaxLOD = D3D11_FLOAT32_MAX;m_pDevice->CreateSamplerState(&sampleDesc, &sampler);m_pContext->PSSetSamplers(0, 1, &sampler);/************************************* 输出阶段 **************************************/// 设置渲染目标m_pContext->OMSetRenderTargets(1, &m_pRenderTargetView, NULL);ID3D11BlendState* blendState;D3D11_BLEND_DESC blendDesc = {};blendDesc.AlphaToCoverageEnable = FALSE;blendDesc.IndependentBlendEnable = FALSE;blendDesc.RenderTarget->BlendEnable = TRUE; // 是否开启混合blendDesc.RenderTarget->SrcBlend = D3D11_BLEND_SRC_ALPHA; // 将源图的 alpha 作为 src rgb 的混合因子blendDesc.RenderTarget->DestBlend = D3D11_BLEND_INV_SRC_ALPHA; // 将源图的 1-alpha 作为 dst rgb 的混合因子blendDesc.RenderTarget->BlendOp = D3D11_BLEND_OP_ADD; // 进行相加操作blendDesc.RenderTarget->SrcBlendAlpha = D3D11_BLEND_ONE; // blendDesc.RenderTarget->DestBlendAlpha = D3D11_BLEND_ONE;blendDesc.RenderTarget->BlendOpAlpha = D3D11_BLEND_OP_ADD;blendDesc.RenderTarget->RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL; // 可以写入的位置m_pDevice->CreateBlendState(&blendDesc, &blendState);const FLOAT BlendFactor[4] = {1.0f, 1.0f, 1.0f, 1.0f};m_pContext->OMSetBlendState(blendState, BlendFactor, 0xffffffff);// 设置视口D3D11_VIEWPORT viewPort = {};viewPort.TopLeftX = 0;viewPort.TopLeftY = 0;viewPort.Width = 800;viewPort.Height = 600;viewPort.MinDepth = 0.0f;viewPort.MaxDepth = 1.0f;m_pContext->RSSetViewports(1, &viewPort);// 开始绘制m_pContext->DrawIndexed(6, 0, 0);
}

参考文献

https://blog.csdn.net/grace_yi/article/details/109081046

Direct3D 11 总结 —— 8 实现简单的绿幕抠图效果相关推荐

  1. Direct3D 11 总结 —— 9 通过键盘调整绿幕抠图阈值

    介绍 本文主要介绍如何通过键盘设置绿幕抠图的阈值,通过设置不同的阈值,看最终的结果. 最终结果 阈值为 0.9 阈值为 0.2 阈值为 0.5 知识点 获取键盘输入 当键盘按下后,会给窗口的回调函数, ...

  2. Android OpenGL ES(八) - 简单实现绿幕抠图

    image.png 实现绿幕抠图,其实想法很简单. 这里简单粗暴的使用着色器替换. OES Filter 直接实现在相机预览上的Shader #extension GL_OES_EGL_image_e ...

  3. 绿幕抠图在手机上使用认识.

    简单介绍 疑问1: 绿幕技术在手机APP上合适吗? 毕竟带着绿布在户外不现实. 是的, 太不现实了, 我们之前不做也是这样想的, 用户量不大, 使用场景不大. 没有谁愿意在户外先支好绿布,然后再拍视频 ...

  4. 绿幕抠图自己的认识.

    疑问1: 绿幕技术在手机APP上合适吗? 毕竟带着绿布在户外不现实. 是的, 太不现实了, 我们之前不做也是这样想的, 用户量不大, 使用场景不大. 没有谁愿意在户外先支好绿布,然后再拍视频. 也是我 ...

  5. 通过OpenCV对视频进行绿幕抠图

    通过OpenCV对视频进行绿幕抠图 效果 代码 1.打开视频素材 2.保存视频路径及格式设置 3.读取一帧视频 4.寻找绿幕背景 5.融合 6.代码执行效果 效果 今天跟大家分享的是最近比较受大家喜欢 ...

  6. 抖音直播画中画、绿幕抠图直播,如此简单

    抖音直播目前较火,但只单存的播放视频,很容易限流,无法加热... 目前较火的直播方式,无非就是画中画+绿幕直播了.可能会环节以上问题. 什么是画中画,就是两个媒体源叠加在一起 如下图: 如何把摄像头只 ...

  7. 编程去除背景绿幕抠图,基于.NET+OpenCVSharp

    摘要:本文介绍了一种使用OpenCVSharp对摄像头中的绿幕视频进行实时"抠人像.替换背景"的方式,对于项目中的算法进行了分析.本文中给出了简化OpenCVSharp中Mat.M ...

  8. Unity3D视频绿幕抠图的实现及优化

    Unity3D视频绿幕抠图的实现及优化 展开 本文是通过Shader处理绿幕的方式来实现Unity中视频(VideoPlayer)的绿幕抠图.因为项目原因,不追究细节(能用就好能用就好)orz可是我连 ...

  9. 绿幕抠图SDK技术对比

    复杂度 现实环境的影响:绿色不是一个固定的像素值, 它会随光线亮暗,绿布的颜色, 相机的成像质量,反光,色溢等各种因素影响,所以不能用简单的判断一个像素值,就认为是绿或不绿:也不是一个平滑过度的值,比 ...

最新文章

  1. Delphi 2010 secondsBetween Bug
  2. linux shell 数组遍历方式(非原创)
  3. poj2002 poj3432 正方形个数 (hash,二分)
  4. python xlutils.copy_使用python的xlrd,xlwt和xlutils.copy保留样式
  5. PHP 基本数据类型
  6. 什么是 SAP Spartacus 里的 module augmentation
  7. 火狐查cookie_Firefox 65默认会阻止跟踪Cookie
  8. 随笔-机器如何学习我们的知识?
  9. 什么人适合学习Java编程?编程好学吗?
  10. python3语法都相同吗_python3.4学习笔记(一) 基本语法 python3不向下兼容,有些语法跟python2.x不一样...
  11. 未来计算机硬件的发展有可能使用的技术,未来计算机硬件的发展有可能使用的技术是______。...
  12. drools 7.x 加载指定的决策表
  13. 实验linux下的编程,实验四 Linux下的C语言编程;
  14. Ubuntu终端常用的快捷键,光标移动到开始位置
  15. JMeter录制的两种方法
  16. 虚幻四中怎么保持导入模型坐标_「虚幻引擎5」为何让开发者们拍手叫好?它到底厉害在哪?...
  17. 保研夏令营/预推免联系老师邮件模板
  18. WGCNA:(加权共表达网络分析)
  19. vtd和vt的区别_vtvi和v的区别是什么?
  20. 深度linux12.12安装,深度Linux 12.12 Alpha发布

热门文章

  1. concurrent_network
  2. jsp幼儿园管理系统ssh框架
  3. 听说你不会玩直播技术?
  4. 秀场衰落之后,谁来主导直播的下半场?
  5. 女人不成熟的10大表现
  6. 下载android版本到手机通讯录,和通讯录下载-和通讯录 安卓版v6.0.4-PC6安卓网
  7. win7 x64环境下载、安装、配置jdk-7u7
  8. 兰卡斯特大学计算机专业世界排名,2019上海软科世界一流学科排名计算机科学与工程专业排名兰卡斯特大学排名第101-150...
  9. 技术前沿与经典文章18:历史上54位伟大物理学家、科学家的专属LOGO(四)
  10. processing创意图形代码_代码之上,诗意之中 | Processing编程造个梦