玩转图像处理:Python与OpenCV实现高效绿幕背景替换

news2024/9/29 5:02:47

文章目录

  • 前言
  • 色度抠图技术(Chroma Keying)
    • 基本原理
  • 数据准备
  • 代码实现
  • 性能分析
  • 代码优化
  • 优化后的速度

前言

现阶段绿幕抠图有很多种方式,比如色度抠图(Chroma Keying)、亮度抠图(Luma Keying)、色差抠图(Color Difference Keying),甚至还有绿幕抠图的模型。不同方式的绿幕抠图效果和效率各有差异,在使用时应该根据的自己的业务需求进行选择。

本文主要介绍色度抠图技术
文末有完整代码以及优化后的代码

色度抠图技术(Chroma Keying)

基本原理

色度抠图技术的工作原理基于颜色空间的差异。它通常将输入的图像从RGB(红、绿、蓝)色彩空间转换到更适合于颜色分离的色彩空间,如HSV(色调、饱和度、亮度)或YUV(亮度、色度U、色度V)。然后,系统分析图像中的每个像素,并将其与预设的“键控颜色”(通常是绿色或蓝色)进行比较。通过计算像素和预设颜色的距离或者相似度来分割前景和后景。(后续的代码实践里面会讲解)

数据准备

准备的绿幕图片前景中不能出现和绿幕背景相同的颜色,不然会被当作背景替换掉。
拍摄绿幕图片时,尽量避免绿幕反光导致人物边缘出现绿光的现象。
背景的颜色均匀且无杂物

代码实现

原图
在这里插入图片描述

图片色彩空间转换,前景和后景的分离(掩码图片)

import cv2
import time
import numpy as np
image_path="图片路径"
# 加载图片
image = cv2.imread(image_path)  # image的数据类型是numpy.ndarray,其实就是将每一像素点转换成了[b,g,r]
# 转换到HSV颜色空间
hsv_image = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)   # 后续需要根据这个进行分离
# 如果抠图不理想,可以调整一下色彩的范围
lower_green = np.array([35, 43, 46])    # hsv 绿色最小值
upper_green = np.array([77, 255, 255])  # hsv 绿色最大值

# 根据给定的颜色范围创建掩码图片
mask = cv2.inRange(hsv_image, lower_green, upper_green)  
# 显示掩码图片,缩放展示cv2.resize(mask.copy(), (image.shape[1] // 2, image.shape[0] // 2))
cv2.imshow('mask', mask)

掩码图片
白色的部分就是绿幕的部分,黑色的部分就是其他的颜色
在这里插入图片描述

掩码反转背景替换

# 反转掩码,因为我们最后需要的是黑色的部分,所以需要将黑色和白色进行交换
mask_inv = cv2.bitwise_not(mask)  
# 使用掩码提取前景
fg = cv2.bitwise_and(image, image, mask=mask_inv)

在这里插入图片描述
背景替换

background_path = '背景图片路径'
background = cv2.imread(background_path)
# 调整背景大小以匹配前景
bg = cv2.resize(background, (image.shape[1], image.shape[0]))
result = bg.copy()  # 复制一份,也可以不复制,直接在原图上进行修改
# 利用numpy的向量加速,其实就是将前景所对应的像素点替换到背景所对应的像素点上
result[mask_inv == 255] = fg[mask_inv == 255]
cv2.imshow('Green Screen Keying', result)

在这里插入图片描述

第一版代码

import cv2
import time
import numpy as np

def green_screen_keying(image_path, background_path):
    # 读取图像
    image = cv2.imread(image_path)
    background = cv2.imread(background_path)
    t1 = time.time()
    # 转换到HSV颜色空间
    hsv_image = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
    print(type(hsv_image))
    lower_green = np.array([35, 43, 46])
    upper_green = np.array([77, 255, 255])
    mask = cv2.inRange(hsv_image, lower_green, upper_green)
    cv2.imshow('mask', cv2.resize(mask.copy(), (image.shape[1] // 2, image.shape[0] // 2)))
    cv2.imwrite("mask.jpg", mask)
    # 反转掩码
    mask_inv = cv2.bitwise_not(mask)
    # 使用掩码提取前景
    fg = cv2.bitwise_and(image, image, mask=mask_inv)
    # 调整背景大小以匹配前景
    cv2.imwrite("fg.jpg", fg)
    bg = cv2.resize(background, (image.shape[1], image.shape[0]))
    result = bg.copy()
    # print(mask_inv)  # 掩膜只有黑色和白色
    # 利用numpy的向量加速
    result[mask_inv == 255] = fg[mask_inv == 255]
    # 显示结果
    t2 = time.time()
    print(t2 - t1)
    cv2.imshow('Green Screen Keying', cv2.resize(result.copy(), (image.shape[1] // 3, image.shape[0] // 3)))
    cv2.imwrite("result.jpg", result)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

# 使用示例
green_screen_keying('../img/girl.png', '../img/7869190.jpg')

性能分析

电脑配置
系统:window 10
CPU:AMD Ryzen 5 4600H with Radeon Graphics 3.00 GHz
内存:32G,DDR4 3200MHz
电脑配置比较旧,新款的电脑测出的速度应该要更快。

将上面的代码一些无关的显示和存储操作删除以后,经过多次的测试发现替换一张图片1080x1920的图片大概需要0.078s,其中result[mask_inv == 255] = fg[mask_inv == 255]这一步占了0.055s,占耗时的70%,是一个拖慢效率主主要的步骤。

result[mask_inv == 255] = fg[mask_inv == 255]实际上这个操作已经避免了循环遍历,利用了numpy本身的特性,效率已经算是够快了(numpy中可能还有更快的方式,欢迎大佬来指点),但是如果我们处理的是一个视频流或直播,需要一种更加高效的方式处理视频流,来提高效率或者保证视频帧的稳定产生。

代码优化

废话不多说直接上代码

import time
import cv2
import numpy as np

def green_screen_keying(image_path, background_path):
    image = cv2.imread(image_path)
    background = cv2.imread(background_path)
    t1 = time.time()
    bg = cv2.resize(background, (image.shape[1], image.shape[0]))
    hsv_image = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
    lower_green = np.array([36, 25, 25])
    upper_green = np.array([70, 255, 255])
    
    # 创建掩码
    mask = cv2.inRange(hsv_image, lower_green, upper_green)
    # 反转掩码
    mask_inv = cv2.bitwise_not(mask)
    # 使用掩码提取前景,只保留非绿色的部分
    fg = cv2.bitwise_and(image, image, mask=mask_inv)
    # 使用掩码提取背景,只保留原图片中绿色部分
    background_masked = cv2.bitwise_and(bg, bg, mask=mask)
    # 将两个图片进行或操作分别保留前景和背景中存在的部分,
    result = cv2.bitwise_or(fg, background_masked)
    t2 = time.time()
    print(t2-t1)

green_screen_keying('../img/girl.png', '../img/7869190.jpg')```

前面关于图片掩码的处理都是一样的,主要的区别就是后面前景图片和后景图片融合的部分。
主要改变就是下面的部分,我们利用掩码和反转掩码分别在前景图片和后景图片中取出需要保留的部分,然后在利用opencvbitwise_or将两个图片进行融合。其实就是或操,图片中被舍弃的部分是“黑色”,两张图片中取非“黑色”部分

# 使用掩码提取前景,只保留非绿色的部分
fg = cv2.bitwise_and(image, image, mask=mask_inv)
# 使用掩码提取背景,只保留原图片中绿色部分
background_masked = cv2.bitwise_and(bg, bg, mask=mask) # 
# 将两个图片进行或操作,分别保留前景和背景中存在的部分,
result = cv2.bitwise_or(fg, background_masked)

优化后的速度

一张1080x1920的图片替换绿幕所花费的时间是0.013s,处理一张图片的耗时大概是原来的16.7%,速度是原来的6倍,优化的效果算是比较理想的。

关于背景替换后出现边缘锯齿状的情况,有几个解决方向

  • 一个是在拍摄绿幕的时候避免主体内容收到绿光的污染
  • 提高原始素材的分辨率,更大的素材像素点就更多,即使出现锯齿状,缩放图片以后也在一定程度上缓解。
  • 优化算法,使用opencv一些’膨胀’、’腐蚀‘的形态学操作,还可以使用一些 ’高斯模糊‘,’边缘检测‘等方式

各位看官看官还有更优的方式,欢迎指点。如果对你有所帮助,希望您能点个赞支持一下。

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2175860.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

探索Python网络世界的利器:Requests-HTML库

文章目录 探索Python网络世界的利器:Requests-HTML库背景:为何选择Requests-HTML?什么是Requests-HTML?如何安装Requests-HTML?5个简单库函数的使用方法3个场景下库的使用示例常见Bug及解决方案总结 探索Python网络世界…

Acwing 质数

1.试除法判定质数 首先回顾一下什么是质数? 对所有大于1的自然数,如果这个数的约数只包含1和它本身,则这个数被称为质数或者素数 试除法:对于一个数n,从2枚举到n-1,若有数能够整除n,则说明除…

C# 泛型使用案例_C# 泛型使用整理

一、系统自带常用的泛型 1.字典&#xff0c;集合 //字典 Dictionary<string, int> dic new Dictionary<string, int>(); //泛型集合 List<int> list new List<int>(); 2.泛型委托&#xff0c;输入参数&#xff0c;输出参数 //泛型 委托---输出参…

nuclei配合burpsuite快速生成POC

nuclei配合burpsuite快速生成POC 简介 Nuclei是一款基于YAML语法模板的开发的定制化快速漏洞扫描器。它使用Go语言开发&#xff0c;具有很强的可配置性、可扩展性和易用性 官网&#xff1a;https://nuclei.projectdiscovery.io Nuclei项目地址&#xff1a;https://github.com/…

生物信息常用编辑器:轻量/强大/可定制/跨平台支持的编辑器之神 - vim

Emacs 被誉为神的编辑器&#xff0c;而 vim 是编辑器之神。本人曾经是 Emacs 的粉丝&#xff0c;不过后来不知不觉&#xff0c;已经是 vim 的重度用户&#xff0c;而 Emacs 却很长时间没用了。 如果你开始在生物信息学中编写代码或处理大量文本数据&#xff0c;选择一个合适的文…

【C语言刷力扣】2079.给植物浇水

题目&#xff1a; 解题思路&#xff1a; 面对每一株植物有两种情况 水够 or 水不够&#xff1a; 水够&#xff1a; result 加1即向前走一步水不够&#xff1a; 走回河边再走回来并向前走一步&#xff0c;走到下一植物 result 2 * i 1 int wateringPlants(int* plants, int…

Cluster Explanation via Polyhedral Descriptions

通过多面体描述进行聚类解释 本文关注聚类描述问题&#xff0c;即在给定数据集及其聚类划分的情况下&#xff0c;解释这些聚类的任务。我们提出了一种新的聚类解释方法&#xff0c;通过在每个聚类周围构建一个多面体&#xff0c;同时最小化最终多面体的复杂性或用于描述的特征…

2024-9-28 QT登录框基础练习

1.头文件 #ifndef LOGINWINDOW_H #define LOGINWINDOW_H#include <QWidget> #include <QPushButton> #include <QLineEdit> #include <QVBoxLayout>class LoginWindow : public QWidget {Q_OBJECTpublic:// 构造函数LoginWindow(QWidget *parent nul…

卸载WSL(Ubuntu),卸载linux

禁用 WSL 功能 打开 Windows 功能&#xff1a; 按下 Windows R 打开运行对话框&#xff0c;输入 optionalfeatures&#xff0c;然后按回车。 禁用 WSL&#xff1a; 在弹出的 Windows 功能窗口中&#xff0c;找到 适用于 Linux 的 Windows 子系统&#xff08;Windows Subsystem…

2024年咸宁中级职称水平测试合格公示

工程系列水测合格549人 农业系列水测合格18人 新闻系列水测合格37人 档案系列水测合格16人 看来每年评工程类职称 人员还是占大多数 关于咸宁初级、中级职称评审更多需要了解的可以留言

.NET 开源的功能强大的人脸识别 API

给大家推荐一款.NET 开源提供了强大的人脸识别 API&#xff0c;工具不仅易于集成&#xff0c;还具备高效处理能力。 本文将介绍一款如何利用这些API&#xff0c;为我们的项目添加智能识别的亮点 GitHub 上拥有 1.2k 星标的 C# 面部识别 API 项目&#xff1a;FaceRecognitionD…

传知代码-基于图神经网络的知识追踪方法(论文复现)

代码以及视频讲解 本文所涉及所有资源均在传知代码平台可获取 1.论文概述 论文链接提出了一种基于图神经网络的知识追踪方法&#xff0c;称为基于图的知识追踪&#xff08;GKT&#xff09;。将知识结构构建为图&#xff0c;其中节点对应于概念&#xff0c;边对应于它们之间的…

Jupyter Notebook 更换主题

1、安装 Jupyter 主题 pip install jupyterthemes 2、更新 Jupyter 主题 &#xff08;可选&#xff09; pip install --upgrade jupyterthemes 3、查看可用的 Jupyter 主题 jt -l 4、更换 Jupyter 主题 选择你喜欢的主题后&#xff0c;可以使用以下命令来应用它。更换主题后…

个人健康管理小程序(源码+参考文档+定制)

博主介绍&#xff1a; ✌我是阿龙&#xff0c;一名专注于Java技术领域的程序员&#xff0c;全网拥有10W粉丝。作为CSDN特邀作者、博客专家、新星计划导师&#xff0c;我在计算机毕业设计开发方面积累了丰富的经验。同时&#xff0c;我也是掘金、华为云、阿里云、InfoQ等平台…

Python 潮流周刊#71:PyPI 应该摆脱掉它的赞助依赖

△△请给“Python猫”加星标 &#xff0c;以免错过文章推送 本周刊由 Python猫 出品&#xff0c;精心筛选国内外的 250 信息源&#xff0c;为你挑选最值得分享的文章、教程、开源项目、软件工具、播客和视频、热门话题等内容。愿景&#xff1a;帮助所有读者精进 Python 技术&am…

如何安装和设置 Go 版本的 fabric AI 工作流框架?

痛点 今年 6 月份&#xff0c;我给你介绍了 fabric 这款 AI 工作流工具。 它包裹了大量的优秀提示词&#xff0c;可以处理各种你日常工作、学习和科研中的事务性工作。包括但不限于&#xff1a; 从视频当中提取要点撰写博客给研究评分…… 不少读者看过之后&#xff0c;大呼有用…

代码随想录Day 59|图论Part09,dijkstra(堆优化版)精讲、Bellman_ford算法精讲

提示&#xff1a;DDU&#xff0c;供自己复习使用。欢迎大家前来讨论~ 文章目录 图论part09dijkstra&#xff08;堆优化版&#xff09;精讲图的存储邻接矩阵邻接表 Bellman_ford 算法精讲模拟过程代码总结 图论part09 dijkstra&#xff08;堆优化版&#xff09;精讲 图的存储…

Windows安装启动apache httpd 2.4 web服务器

Windows安装启动apache httpd 2.4 web服务器 apache httpd主要用来处理静态网页内容以及如php。 &#xff08;1&#xff09;在 Apache VS17 binaries and modules download 下载apache&#xff1a; &#xff08;2&#xff09;下载解压到一个目录&#xff0c;如果目录是这样的…