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

文章目录

  • 前言
  • 色度抠图技术(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 npdef 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 npdef 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.xdnf.cn/news/148603.html

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

相关文章

win7系统安装高于13.14.0版本的node及遇到问题

背景 原项目是在win10系统上,使用的是node16.10.0版本,使用的vite开发,现在需要去客户现场进行开发,提供的电脑是win7系统,因为win7系统支持的最高版本node是13.14.0,所以我们需要降低node版本&#xff0c…

深化战略合作|义翘神州与百奥几何扩大合作:生成式AI深度赋能蛋白研发

近日,重组蛋白领军企业义翘神州与前沿数字生物企业百奥几何达成战略合作,将蛋白表达湿实验平台与生成式AI蛋白设计和改造有机结合。在前期项目成功合作的基础上,双方决定进一步深化合作,合力开拓高附加值市场需求。 当前&#xf…

opencv实战项目二十五:复杂背景下的直线提取

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、简介二,算法实现:2.1 中值滤波去噪2.2滤波图像取反并提取直线2.3 二值图细化2.4 对细化后的直线进行霍夫变换 前言 在当今计算机视…

超越想象的声音修复——iZotope RX 11,重塑音频处理的未来

iZotope RX 11是一款功能强大的音频修复和增强软件,专为音频后期制作、音乐制作和内容创作而设计。以下是其主要功能和用途的详细概述: iZotope RX 11 苹果Mac软件下载 iZotope RX 11 Windows软件下载 主要功能 智能降噪与修复: RX 11配备了…

ARM相关概念

ARM课程大纲 ARM相关的基本概念 机器码 计算机能够识别由1和0组成的编码格式 汇编:将汇编文件转换为二进制文件(.bin/.elf) 汇编指令 是一条具备特殊功能的指令 编译:生成汇编文件 int a 10; ------> mov r0 #10 …

Qt/C++ 了解NTFS文件系统,解析0x80 $Data属性,获取Run Lists数据列表

系列文章目录 整个专栏系列是根据GitHub开源项目NTFS-File-Search获取分区所有文件/目录列表的思路。 具体的如下: Qt/C 了解NTFS文件系统,了解MFT(Master File Table)主文件表(一) 介绍NTFS文件系统,对比通过MFT(Master File Tab…

springboot中小学数字化教学资源管理平台

基于springbootvue实现的中小学数字化教学资源管理平台 (源码L文ppt)4-078 第4章 系统设计 4.1 功能模块设计 系统整体模块分为管理员、教师和学生三大用户角色,整体功能设计图如下所示: 图4-1 系统整体功能图 4.2 数据库设计 4.2.1 E-R模…

工业交换机故障快速排查的方法有哪些

在现代工业自动化的环境中,工业交换机作为网络连接的重要设备,其稳定性和可靠性至关重要。然而,实际使用过程中难免会遇到各种故障,这对生产线和系统的正常运作造成了影响。为了有效应对这些问题,下面将介绍一些工业交…

CSRF高级防御绕过

1)回顾low级别做过csrf页面的密码重置,重复之前的操作,我们发现级别调整中级之后,报错如下 2)检查源码 进入dvwa源码,查找到checktoken: 3)在dvwa-csrf页面上,抓包 http…

前端开发者有福啦,循序渐进Vue.js 3.x前端开发实践已上线

目录 写在前面 推荐图书 推荐理由 写在最后 写在前面 好书推荐!前端开发者的福利来喽,《循序渐进Vue.js 3.x前端开发实践》,你值得拥有。 推荐图书 《循序渐进Vue.js 3.x前端开发实践》 推荐理由 《循序渐进Vue.js 3.x前端开发实践》…

介绍GPT-o1:一系列解决困难问题( science, coding, and math )的推理模型

openai o1介绍 一、官方技术报告要点剖析实验1 benchmark分析实验2:和phd比赛技术细节:Chain of Thought的使用人类偏好评估Human preference evaluationsatety技术细节:隐藏思维链为监控模型提供了机会:)openai的几点conclusion 二、官方介绍剖析 Intro…

【C语言进阶】第四节:自定义类型详解

1、结构体 1.1 结构体变量的定义和初始化 struct Point//类型声明 {int x;int y; }p1;//声明类型的同时定义变量p1struct Point p2;//定义结构体变量p2//初始化:定义变量的同时赋初值。 struct Point p3 { x, y };struct Node {int data;struct Point p;struct N…

端侧 AI 的新突破:面壁智能 MiniCPM 3.0

在人工智能领域,每一次技术的革新都可能引发一场小小的革命。 ChatGPT-3.5 曾经凭借其惊人的表现赢得了大众的关注,但如今,随着国内AI公司面壁智能推出的新端侧基座模型,人们开始重新审视端侧AI的潜力和未来。 这款名为MiniCPM …

Dockerfile全面指南:从基础到进阶,掌握容器化构建的核心工具

目录 Dockerfile全面指南:从基础到进阶,掌握容器化构建的核心工具 引言 一、什么是 Dockerfile 二、Dockerfile 的基本结构 三、Dockerfile 的常见配置项 1、多阶段构建 (Multi-stage Builds) 2、缓存优化 3、合并 RUN 命令 四、Dockerfile 使用…

C盘太臃肿了用这招一键给C盘瘦身 快速释放C盘空间

C盘太臃肿了用这招一键给C盘瘦身 快速释放C盘空间。我们的电脑不知不觉的就爆满了,这个主要的原因就是各种垃圾文件堆积,时间用得越久,垃圾堆积得越多,这样我们的C盘空间就被蚕食了,空间越来越小,变得越来越…

干货分享:为什么stable diffusion训练用ddpm, 采样用ddim呢?

前言 回忆一下DDPM,实质上它的推导过程应是如下的: 其中, 是单纯的高斯分布的推导,相当于一个序列过程的归纳法推导。 在DDPM中采用的是[贝叶斯公式]。 而过程则是用对进行一个估测,也就是用前向过程反过来对进行一个…

sql语法学习:关键点和详细解释

学习SQL语法是掌握数据库操作的基础。以下是SQL语法的一些关键点和详细解释: 1. SQL基础 SQL(Structured Query Language)是一种用于管理和操作关系型数据库的标准语言。它主要包括以下几个部分: 数据定义语言(DDL&…

探索Mem0:AI的智能记忆层

文章目录 探索Mem0:AI的智能记忆层背景介绍Mem0是什么?如何安装Mem0?简单使用方法应用场景常见问题及解决方案总结 ![ 探索Mem0:AI的智能记忆层 背景介绍 在人工智能的世界里,记忆是个性化体验的关键。想象一下&…

结构设计模式 -装饰器设计模式 - JAVA

装饰器设计模式 前言 这是我在这个网站整理的笔记,有错误的地方请指出,关注我,接下来还会持续更新。 作者:神的孩子都在歌唱 一. 介绍 百度百科:装饰模式指的是在不必改变原类文件和使用继承的情况下,动态地扩展一个对…

只需5分钟!掌握学术写作的核心逻辑!

人工智能的广泛应用中,ChatGPT 已被证明是一种极具潜力的语言模型,其功能涵盖多个领域,显示出强大的适应性。在 GPT-4 架构的推动下,ChatGPT 正在彻底改变我们与文本驱动的人工智能的交互模式。 在学术界,学术写作至关…