成都网站建设推来客,深圳英文网站设计,设置网站404页面,建设网站有哪些步骤1 概述
生活中经常要用到各种要求的证件照电子版#xff0c;红底#xff0c;蓝底#xff0c;白底等#xff0c;大部分情况我们只有其中一种#xff0c;本文通过opencv实现证件照背景的颜色替换。
1.1 opencv介绍
OpenCV#xff08;Open Source Computer Vision Librar…1 概述
生活中经常要用到各种要求的证件照电子版红底蓝底白底等大部分情况我们只有其中一种本文通过opencv实现证件照背景的颜色替换。
1.1 opencv介绍
OpenCVOpen Source Computer Vision Library是一个开源的计算机视觉和机器学习软件库。它最初由英特尔在1999年开发后来由Willow Garage和Itseez现为部分的Intel维护。OpenCV旨在提供一个易于使用的计算机视觉基础设施帮助人们实现复杂的视觉分析任务。
1.2 RGB介绍
RGB 是我们接触最多的颜色空间由三个通道表示一幅图像分别为红色(R)绿色(G)和蓝色(B)。这三种颜色的不同组合可以形成几乎所有的其他颜色。
RGB 颜色空间是图像处理中最基本、最常用、面向硬件的颜色空间比较容易理解。RGB 颜色空间利用三个颜色分量的线性组合来表示颜色任何颜色都与这三个分量有关而且这三个分量是高度相关的所以连续变换颜色时并不直观想对图像的颜色进行调整需要更改这三个分量才行。
自然环境下获取的图像容易受自然光照、遮挡和阴影等情况的影响即对亮度比较敏感。而 RGB 颜色空间的三个分量都与亮度密切相关即只要亮度改变三个分量都会随之相应地改变而没有一种更直观的方式来表达。
但是人眼对于这三种颜色分量的敏感程度是不一样的在单色中人眼对红色最不敏感蓝色最敏感所以 RGB 颜色空间是一种均匀性较差的颜色空间。如果颜色的相似性直接用欧氏距离来度量其结果与人眼视觉会有较大的偏差。对于某一种颜色我们很难推测出较为精确的三个分量数值来表示。所以RGB 颜色空间适合于显示系统却并不适合于图像处理。
1.3 HSV 颜色空间
基于上述理由在图像处理中使用较多的是 HSV 颜色空间它比 RGB 更接近人们对彩色的感知经验。非常直观地表达颜色的色调、鲜艳程度和明暗程度方便进行颜色的对比。在 HSV 颜色空间下比 BGR 更容易跟踪某种颜色的物体常用于分割指定颜色的物体。
HSV 表达彩色图像的方式由三个部分组成
Hue色调、色相Saturation饱和度、色彩纯净度Value明度
用下面这个圆柱体来表示 HSV 颜色空间圆柱体的横截面可以看做是一个极坐标系 H 用极坐标的极角表示S 用极坐标的极轴长度表示V 用圆柱中轴的高度表示。 Hue 用角度度量取值范围为0360°表示色彩信息即所处的光谱颜色的位置。表示如下 颜色圆环上所有的颜色都是光谱上的颜色从红色开始按逆时针方向旋转Hue0 表示红色Hue120 表示绿色Hue240 表示蓝色等等。在 GRB中 颜色由三个值共同决定比如黄色为即 (255,255,0)在HSV中黄色只由一个值决定Hue60即可。
HSV 圆柱体的半边横截面Hue60 其中水平方向表示饱和度饱和度表示颜色接近光谱色的程度。饱和度越高说明颜色越深越接近光谱色饱和度越低说明颜色越浅越接近白色。饱和度为0表示纯白色。取值范围为0100%值越大颜色越饱和。
竖直方向表示明度决定颜色空间中颜色的明暗程度明度越高表示颜色越明亮范围是 0-100%。明度为0表示纯黑色此时颜色最暗。
可以通俗理解为
在Hue一定的情况下饱和度减小就是往光谱色中添加白色光谱色所占的比例也在减小饱和度减为0表示光谱色所占的比例为零导致整个颜色呈现白色。
明度减小就是往光谱色中添加黑色光谱色所占的比例也在减小明度减为0表示光谱色所占的比例为零导致整个颜色呈现黑色。
HSV 对用户来说是一种比较直观的颜色模型。我们可以很轻松地得到单一颜色即指定颜色角H并让VS1然后通过向其中加入黑色和白色来得到我们需要的颜色。增加黑色可以减小V而S不变同样增加白色可以减小S而V不变。例如要得到深蓝色V0.4 S1 H240度。要得到浅蓝色V1 S0.4 H240度。
HSV 的拉伸对比度增强就是对 S 和 V 两个分量进行归一化(min-max normalize)即可H 保持不变。
RGB颜色空间更加面向于工业而HSV更加面向于用户大多数做图像识别这一块的都会运用HSV颜色空间因为HSV颜色空间表达起来更加直观
1.4 HLS 颜色空间
HLS 和 HSV 比较类似这里一起介绍。HLS 也有三个分量hue色相、saturation饱和度、lightness亮度。
HLS 和 HSV 的区别就是最后一个分量不同HLS 的是 light(亮度)HSV 的是 value(明度)。
HLS 中的 L 分量为亮度亮度为100表示白色亮度为0表示黑色HSV 中的 V 分量为明度明度为100表示光谱色明度为0表示黑色。
下面是 HLS 颜色空间圆柱体 提取白色物体时使用 HLS 更方便因为 HSV 中的Hue里没有白色白色需要由S和V共同决定S0, V100。而在 HLS 中白色仅由亮度L一个分量决定。所以检测白色时使用 HSL 颜色空间更准确。
注意在 OpenCV 中 HLS 三个分量的范围为
H [0,179]L [0,255]S [0,255]
2 使用opencv替换证件照背景颜色
2.1 导入图片并改变图片大小
原始图片 代码实现
img cv2.imread(../data/card_girl01.jpeg)# 缩放
rows, cols, channels img.shape
img cv2.resize(img, None, fx0.5, fy0.5)
rows, cols, channels img.shape
2.2 获取背景区域
首先将读取的图像默认BGR格式转换为HSV格式然后通过inRange函数获取背景的mask。
代码实现
# 转换hsv
hsv cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
lower_blue np.array([78, 43, 46])
upper_blue np.array([110, 255, 255])
mask_img cv2.inRange(hsv, lower_blue, upper_blue)new_image show_multi_imgs(4, [img, cv2.cvtColor(mask_img, cv2.COLOR_GRAY2BGR)], (1, 2))
cv2.namedWindow(imgmask_img, 0)
cv2.imshow(imgmask_img, new_image)
cv2.waitKey(0)
运行代码显示 如图所示蓝色的背景在图中用白色表示白色区域就是要替换的部分但是黑色区域内有白点干扰所以进一步优化。
2.3 腐蚀和膨胀
代码实现
# 腐蚀膨胀
erode_img cv2.erode(mask_img, None, iterations1)new_image show_multi_imgs(4, [img, cv2.cvtColor(erode_img, cv2.COLOR_GRAY2BGR)], (1, 2))
cv2.namedWindow(imgerode_img, 0)
cv2.imshow(imgerode_img, new_image)
cv2.waitKey(0)dilate_img cv2.dilate(erode_img, None, iterations1)
new_image show_multi_imgs(4, [img, cv2.cvtColor(dilate_img, cv2.COLOR_GRAY2BGR)], (1, 2))
cv2.namedWindow(imgdilate_img, 0)
cv2.imshow(imgdilate_img, new_image)
cv2.waitKey(0)
运行代码显示 处理后图像单独白色点消失。
2.4 替换背景色
遍历全部像素点如果该颜色为dilate里面为白色255则说明该点所在背景区域于是在原图img中进行颜色替换。
示例代码
# 遍历替换
final_img img.copy()
for i in range(rows):for j in range(cols):if dilate_img[i, j] 255:# 此处替换颜色为BGR通道final_img[i, j] (0, 0, 255)new_image show_multi_imgs(4, [img, final_img], (1, 2))
cv2.namedWindow(imgfinal_img, 0)
cv2.imshow(imgfinal_img, new_image)
cv2.waitKey(0) 运行代码显示 2.5 完整代码
import cv2
import numpy as np# 一个窗口显示多张图片
def show_multi_imgs(scale, imglist, orderNone, border10, border_color(255, 255, 0))::param scale: float 原图缩放的尺度:param imglist: list 待显示的图像序列:param order: list or tuple 显示顺序 行×列:param border: int 图像间隔距离:param border_color: tuple 间隔区域颜色:return: 返回拼接好的numpy数组if order is None:order [1, len(imglist)]allimgs imglist.copy()ws, hs [], []for i, img in enumerate(allimgs):if np.ndim(img) 2:allimgs[i] cv2.cvtColor(img, cv2.COLOR_GRAY2BGR)allimgs[i] cv2.resize(img, dsize(0, 0), fxscale, fyscale)ws.append(allimgs[i].shape[1])hs.append(allimgs[i].shape[0])w max(ws)h max(hs)# 将待显示图片拼接起来sub int(order[0] * order[1] - len(imglist))# 判断输入的显示格式与待显示图像数量的大小关系if sub 0:for s in range(sub):allimgs.append(np.zeros_like(allimgs[0]))elif sub 0:allimgs allimgs[:sub]imgblank np.zeros(((hborder) * order[0], (wborder) * order[1], 3)) border_colorimgblank imgblank.astype(np.uint8)for i in range(order[0]):for j in range(order[1]):imgblank[(i * h i*border):((i 1) * hi*border), (j * w j*border):((j 1) * w j*border), :] allimgs[i * order[1] j]return imgblankimg cv2.imread(../data/card_girl01.jpeg)# 缩放
rows, cols, channels img.shape
img cv2.resize(img, None, fx0.5, fy0.5)
rows, cols, channels img.shape# 转换hsv
hsv cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
lower_blue np.array([78, 43, 46])
upper_blue np.array([110, 255, 255])
mask_img cv2.inRange(hsv, lower_blue, upper_blue)new_image show_multi_imgs(4, [img, cv2.cvtColor(mask_img, cv2.COLOR_GRAY2BGR)], (1, 2))
cv2.namedWindow(imgmask_img, 0)
cv2.imshow(imgmask_img, new_image)
cv2.waitKey(0)# 腐蚀膨胀
erode_img cv2.erode(mask_img, None, iterations1)new_image show_multi_imgs(4, [img, cv2.cvtColor(erode_img, cv2.COLOR_GRAY2BGR)], (1, 2))
cv2.namedWindow(imgerode_img, 0)
cv2.imshow(imgerode_img, new_image)
cv2.waitKey(0)dilate_img cv2.dilate(erode_img, None, iterations1)
new_image show_multi_imgs(4, [img, cv2.cvtColor(dilate_img, cv2.COLOR_GRAY2BGR)], (1, 2))
cv2.namedWindow(imgdilate_img, 0)
cv2.imshow(imgdilate_img, new_image)
cv2.waitKey(0)# 遍历替换
final_img img.copy()
for i in range(rows):for j in range(cols):if dilate_img[i, j] 255:# 此处替换颜色为BGR通道final_img[i, j] (0, 0, 255)new_image show_multi_imgs(4, [img, final_img], (1, 2))
cv2.namedWindow(imgfinal_img, 0)
cv2.imshow(imgfinal_img, new_image)
cv2.waitKey(0)