我习惯用tensorflow,所以这里读取图片采用的tensorflow,但是,使用OpenCV同样可以,处理图片使用的OpenCV
目标
我这里用的汽车图片,我们目标是将汽车抠出来,然后替换背景,第二章的黑白图,是图片分割结果的mask图片(图片需要下载和代码放同一个位置,注意修改图片名称:tt.jpg 和 tt_mask.gif)
tt.jpg
tt_mask.gif
思路
抠图思路
- 将图片读取后,mask图片需要处理为二进制图片
- 使用OpenCV的bitwise_and,对原图和mask二进制进行抠图
替换背景思路
- 新建一个背景图
- mask二进制文件需要反转一下(图片中的0变为1,1变为0)
- 利用反转后的mask文件,扣掉背景图中汽车所在的位置
- 将3步得到的背景图 和 前面扣除来的汽车进行相加就行了
- 为了看起来更自然,可以使用高斯模糊进行处理一下
代码
抠图
需要的包
import cv2
import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt
1. 读取图片
- 我这里用的tensorf读取的图片,你也可以使用OpenCV读取图片,整体思路是一样
# 原图
path = "tt.jpg"
img = tf.io.read_file(path)
img = tf.image.decode_jpeg(img, channels=3)
# mask
path_mask = "tt_mask.gif"
img_mask = tf.io.read_file(path_mask)
img_mask = tf.image.decode_jpeg(img_mask, channels=3)
2. 由于是tensorflow读取的图片,为方便OpenCV处理,需要转换为numpy格式
img = img.numpy()
img_mask = img_mask.numpy()
3. mask图片为了方便后面计算,我直接转换为二进制文件
img_mask = cv2.threshold(img_mask, 1, 255, cv2.THRESH_BINARY)[1]
4.(关键代码)下面我就开始利用mask抠图了
- sub_img:就是抠图的效果
sub_img = cv2.bitwise_and(img,img_mask)
plt.imshow(sub_img)
效果如下:
替换背景
制作背景图(纯绿色)
background = np.zeros_like(img)
background[:,:,:] = (12, 198, 150)
plt.imshow(background)
对背景图进行抠图
background = cv2.bitwise_and(background, cv2.bitwise_not(img_mask))
plt.imshow(background)
用扣完的背景图,和扣完的汽车图进行相加
new_img = cv2.add(background, sub_img)
plt.imshow(new_img)
高斯模糊一下,看起来更自然
new_img_blur = cv2.GaussianBlur(new_img, (9,9), 5)
plt.imshow(new_img_blur)
总结
好吧,其实很简单,但是这个抠图问题,影响了我半天,主要是我OpenCV不熟练,再次记录一下,也方便其他菜鸟,有任何疑问,都可留言,我看见后第一时间回复大家