滑稽研究所


java opencv不给背景上色 opencv换背景_缩放

opencv更换证件照背景

哈喽,大家好呀,我是滑稽君。亲爱的朋友们,还在为证件照背景颜色不符合要求发愁?P图嫌麻烦,抠图又手抖?看了这篇文章之后你再也不用担心这个问题了。

那么本期我们就利用opencv来更换证件照的背景颜色。



java opencv不给背景上色 opencv换背景_opencv 二值化_02

视频讲解:

我们拿到如下素材:

java opencv不给背景上色 opencv换背景_缩放_03

我们证件照常用的底色有白底,红底和蓝底。我们的素材为蓝底。现在我们想要红色的背景应该怎么办呢?我们需要进行如下处理。

1.把图像的BGR格式转化为HSV格式。

2.通过inRange函数把图像变为二值图。

3.腐蚀优化边缘细节,膨胀处理主体噪点。

4.遍历像素,在原图替换背景颜色。

思路明确,上代码:

import cv2import  numpy as npimg=cv2.imread('Resources/tom.jpg')#缩放print(img.shape)rows,cols,channels = img.shapeimg=cv2.resize(img,None,fx=0.5,fy=0.5)rows,cols,channels = img.shapecv2.imshow('img',img)b,g,r = img[5,4]print(b,g,r)#转换hsvhsv=cv2.cvtColor(img,cv2.COLOR_BGR2HSV)lower_blue=np.array([78,43,46])upper_blue=np.array([124,255,255])mask = cv2.inRange(hsv, lower_blue, upper_blue)cv2.imshow('Mask', mask)print(mask.shape)#腐蚀膨胀erode=cv2.erode(mask,None,iterations=1)cv2.imshow('erode',erode)dilate=cv2.dilate(erode,None,iterations=1)#遍历时为单通道,获取位置之后在三通道的原图上替换像素。#遍历替换for i in range(rows):    for j in range(cols):        if dilate[i,j]==255:            img[i,j]=(0,0,255)#此处替换颜色,为BGR通道cv2.imshow('res',img)cv2.imshow('dilate',dilate)cv2.waitKey(0)

我们需要注意resize()函数的用法。OpenCV函数resize有2种不同的模式用于调整图像大小。可以在第二个参数中指定固定的输出大小。可以使用用于计算输出大小的fx和fy参数来指定每个维度的缩放因子。即在当前轴体上缩放多少倍。

如果同时使用这两种方法,后面的fx和fy参数将被忽略。这意味着如果我们想要使用缩放方法,我们必须用None代替输出大小参数。None则表示我们不想使用此参数。

注意初始的原图是3通道,二值化之后是单通道,4通道情况下是额外增添了应该透明度,这里我们用不上。

为了识别背景的位置,我们把图像进行了二值化,此时为单通道,此时我们可以很方便的识别出背景的位置。并在原图(3通道)上相同的位置替换像素。我们二值化之后各像素的位置是不变的。这一点我们在代码注释里也给出了。

运行结果:

经过优化之后的二值图:

java opencv不给背景上色 opencv换背景_opencv resize_04

替换成红色背景:

java opencv不给背景上色 opencv换背景_opencv 二值化_05

实际上我们可以通过设置BGR的值替换我们想要的任何颜色。

可能有人想要换成其他背景图,而非单纯的换颜色,可以通过mask和add操作达到想要的效果。如果大家感兴趣的话以后可以单出一期。

通过print(img.shape)来实时检测图片的尺寸及通道数。