相关文章推荐
鼻子大的苹果  ·  ABB技术确保亚洲最大铁路枢纽客站稳定配电 ...·  10 月前    · 
发财的充值卡  ·  「打生樁」恐怖的日本習俗:每蓋一棟房子都要活 ...·  10 月前    · 
幸福的领结  ·  河内市迎来一年中最大的旅游旺季 ...·  11 月前    · 
乖乖的小熊猫  ·  「盛世N队」李艺彤——历经万险原来是为了仇人 ...·  1 年前    · 
眼睛小的烈马  ·  python django model ...·  1 年前    · 
Code  ›  基于OpenCV-python3实现抠图开发者社区
https://cloud.tencent.com/developer/article/1570404?areaSource=104001.20&traceId=XYRXGBIMXi7qB4_p9uiYu
烦恼的鸵鸟
2 年前
作者头像
py3study
0 篇文章

基于OpenCV-python3实现抠图

前往专栏
腾讯云
开发者社区
文档 意见反馈 控制台
首页
学习
活动
专区
工具
TVP
文章/答案/技术大牛
发布
首页
学习
活动
专区
工具
TVP
返回腾讯云官网
社区首页 > 专栏 > python3 > 基于OpenCV-python3实现抠图

基于OpenCV-python3实现抠图

作者头像
py3study
发布 于 2020-01-10 12:33:46
4.8K 0
发布 于 2020-01-10 12:33:46
举报

简述

在 上一篇博客 进行了证件照更换背景颜色,纯蓝色,红色,白色之间的替换,有人私信我,可以不可以把背景换成其他图片,而不是单纯的颜色填充。这在photoshop里面就是选中一个图层然后复制到另外一张图片上去,用代码实现的话和上篇博文换纯色背景思路完全一样,只是在替换颜色时候有了新变化。

获取目标区域(抠图)

将目标区域和背景分离开。

此方法抠图只适合颜色对比比较明显的图片,允许存在少量颜色干扰

加载&缩放

通过imread函数加载图片,resize函数对图像进行缩放。 (因为找的图片有些大,显示器太小,所以适当缩放)

import cv2
import  numpy as np
img=cv2.imread('zjz.jpg')
img_back=cv2.imread('back.jpg')
#日常缩放
rows,cols,channels = img_back.shape
img_back=cv2.resize(img_back,None,fx=0.7,fy=0.7)
cv2.imshow('img_back',img_back)
rows,cols,channels = img.shape
img=cv2.resize(img,None,fx=0.4,fy=0.4)
cv2.imshow('img',img)
rows,cols,channels = img.shape#rows,cols最后一定要是前景图片的,后面遍历图片需要用到

两张图片如下

这里写图片描述
这里写图片描述

(图片源于网络,已经马赛克处理,如有侵权,私信立即删除)

要实现的效果就是,把人物图像抠出来,放在背景图片上面。

获取背景区域

由于背景纯蓝色,所以找到了这些区域,相反的就是我们想要的。 这里要用到inRange这个函数获取蓝色区域。 首先需要将图片转换为HSV类型。

#转换hsv
hsv=cv2.cvtColor(img,cv2.COLOR_BGR2HSV)

获取mask得到蓝色区域

#获取mask
lower_blue=np.array([78,43,46])
upper_blue=np.array([110,255,255])
mask = cv2.inRange(hsv, lower_blue, upper_blue)
cv2.imshow('Mask', mask)

蓝色区域mask如下图

这里写图片描述
这里写图片描述

黑色区域有明显白点,有少量的颜色干扰,需要进一步优化。

mask优化

通过腐蚀和膨胀操作进行消除个别白点。 我对于腐蚀和膨胀操作的理解是:

腐蚀操作将会腐蚀图像中白色像素,以此来消除小斑点, 而膨胀操作将使剩余的白色像素扩张并重新增长回去。


#腐蚀膨胀
erode=cv2.erode(mask,None,iterations=1)
cv2.imshow('erode',erode)
dilate=cv2.dilate(erode,None,iterations=1)
cv2.imshow('dilate',dilate)

优化后如下图

这里写图片描述
这里写图片描述

黑色区域内白点已经消除,完美分离人物与背景[傲娇]。

替换背景图片

此时已经将图片目标区域抠出来了,只需要再新的背景图上把抠出来的对应点颜色填充上去就好。 我们首先要确定一个坐标点,这个点决定了要把抠出来的图像放到新背景图片的什么位置,即就是抠出图片左上角(0,0)点在新的背景图片中应该在的位置。 注意:

扣出的图片应该小于背景图片,确定位置时候应注意,坐标越界后 会发生异常。注意协调。

#遍历替换
center=[50,50]#在新背景图片中的位置
for i in range(rows):
    for j in range(cols):
        if dilate[i,j]==0:#0代表黑色的点
            img_back[center[0]+i,center[1]+j]=img[i,j]#此处替换颜色,为BGR通道
cv2.imshow('res',img_back)

最终效果

这里写图片描述
这里写图片描述

(图片源于网络,已经马赛克处理,如有侵权,私信立即删除)

总结

基本原理和 上篇博客 所讲相同,重点在于后面的center点的确定(谨防越界),和不同图片间相对应的坐标和颜色的相互复制替换。

完整代码如下:

import cv2
import  numpy as np
img=cv2.imread('zjz.jpg')
img_back=cv2.imread('back.jpg')
#日常缩放
rows,cols,channels = img_back.shape
img_back=cv2.resize(img_back,None,fx=0.7,fy=0.7)
cv2.imshow('img_back',img_back)
rows,cols,channels = img.shape
img=cv2.resize(img,None,fx=0.4,fy=0.4)
cv2.imshow('img',img)
rows,cols,channels = img.shape#rows,cols最后一定要是前景图片的,后面遍历图片需要用到
#转换hsv
hsv=cv2.cvtColor(img,cv2.COLOR_BGR2HSV)
#获取mask
lower_blue=np.array([78,43,46])
upper_blue=np.array([110,255,255])
mask = cv2.inRange(hsv, lower_blue, upper_blue)
cv2.imshow('Mask', mask)
#腐蚀膨胀
erode=cv2.erode(mask,None,iterations=1)
cv2.imshow('erode',erode)
dilate=cv2.dilate(erode,None,iterations=1)
cv2.imshow('dilate',dilate)
#遍历替换
center=[50,50]#在新背景图片中的位置
for i in range(rows):
    for j in range(cols):
 
推荐文章
鼻子大的苹果  ·  ABB技术确保亚洲最大铁路枢纽客站稳定配电 | News center
10 月前
发财的充值卡  ·  「打生樁」恐怖的日本習俗:每蓋一棟房子都要活埋一位少女 | 娛樂星聞
10 月前
幸福的领结  ·  河内市迎来一年中最大的旅游旺季 旅游市场氛围热烈而浓厚 | Vietnam+ (VietnamPlus)
11 月前
乖乖的小熊猫  ·  「盛世N队」李艺彤——历经万险原来是为了仇人相见_百科TA说
1 年前
眼睛小的烈马  ·  python django model 创建用户表_mob649e816a77bf的技术博客_51CTO博客
1 年前
今天看啥   ·   Py中国   ·   codingpro   ·   小百科   ·   link之家   ·   卧龙AI搜索
删除内容请联系邮箱 2879853325@qq.com
Code - 代码工具平台
© 2024 ~ 沪ICP备11025650号