0
点赞
收藏
分享

微信扫一扫

【课题总结报告】OpenCV 抠图项目实战(6)

Python 小白的课题报告—OpenCV 抠图项目实战(6)

欢迎关注『Python 小白的项目实战 @ youcans』 原创作品
Python 小白的课题报告—OpenCV 抠图项目实战(1)
Python 小白的课题报告—OpenCV 抠图项目实战(2)
Python 小白的课题报告—OpenCV 抠图项目实战(3)
Python 小白的课题报告—OpenCV 抠图项目实战(4)
Python 小白的课题报告—OpenCV 抠图项目实战(5)
Python 小白的课题报告—OpenCV 抠图项目实战(6)


第三章 阈值抠图

3.3 色彩范围抠图

通常,即使对于确定颜色背景的蓝屏抠图,背景图像的所有像素的颜色也并非完全相同,而是处于相近的色彩范围内。因此,对背景色彩范围进行阈值处理,比阈值处理更为合理。

3.3.1 HSV颜色空间的基本概念

RGB 通道不能很好地反映出物体具体的颜色信息,而 HSV 空间可以非常直观的表达色彩的明暗、色调及鲜艳程度。例如,红色在 HSV 空间中 H 维度的范围为 0~10 和 160~180,而在 RGB 中很难简单明确地给出红色范围的表达式。因此,通常使用 HSV 色彩空间进行某种颜色的识别和不同颜色的对比。

HSV 分别指色相(Hue)、饱和度(Saturation)、明度(Value),又称 HSB(B 指 Brightness)。

  • 色相是色彩的基本属性,就是颜色的名称,如红色、黄色等。
  • 饱和度(S)是指色彩的纯度,饱和度越高色彩越纯,饱和度低则逐渐变灰,取值 0-100%。
  • 明度(V),取值为 0~max(计算机存储长度)。

HSV 颜色空间可以用一个圆锥空间模型来描述。圆锥的顶点处 V=0,H 和 S 无定义,代表黑色;圆锥的顶面中心处V=max,S=0,H 无定义,代表白色。

当 S=1, V=1 时,H 所代表的任何颜色被称为纯色;当 S=0 时,饱和度为 0,颜色最浅,最浅被描述为灰色,灰色的亮度由 V 决定,此时 H 无意义;当 V=0 时,颜色最暗,最暗被描述为黑色,此时 H 和 S 均无意义,无论如何取值均为黑色。

在这里插入图片描述

图3.5 HSV颜色空间

HSV 是一种将 RGB 色彩空间中的点在倒圆锥体中的表示方法,HSV 可以与 RGB 相互转化。
HSV 模型是针对用户观感的一种颜色模型,侧重于色彩表示,什么颜色、深浅如何、明暗如何。
HSV 模型在对指定颜色分割时非常有效。用 H 和 S 分量表示颜色距离,颜色距离指代表两种颜色之间的数值差异。对于不同的彩色区域,混合 H 与 S 变量,划定阈值,即可进行简单的分割。
OpenCV 提供了函数 cv.cvtColor()实现图像的颜色空间转换。

函数说明:

cv. cvtColor(src, code[, dst[, dstCn]]) → dst

函数cvtColor()将图像从一种颜色空间转换为另一种颜色空间。

参数说明:

  • src:输入图像
  • dst:输出图像
  • code:色彩空间转换代码
    • cv2.COLOR_BGR2RGB:BGR -> RGB
    • cv2.COLOR_RGB2BGR:RGB -> BGR
    • cv2.COLOR_BGR2GRAY:BGR -> Gray
    • cv2.COLOR_GRAY2BGR:Gray -> BGR
    • cv2.COLOR_BGR2HSV:BGR -> HSV
    • cv2.COLOR_HSV2BGR:HSV -> BGR

3.3.2 划分颜色区域

函数inRange()可以实现按颜色区域[lowerb,upperb]对图像进行二值分割。

函数inRange()检查数组元素是否在设定区间内,通常用于在HSV空间检查设定的颜色区域范围。如果图像的某个像素值在 [lowerb,upperb] 之间,则输出图像的相应位置置 255;否则置0。

因此,cv.inrange 函数可以实现按颜色区域 [lowerb,upperb] 对图像进行二值分割。对于单通道图像,如果灰度图像的某个像素的灰度值在指定的高低阈值范围内,则输出图像中该像素值为255,否则为 0。

对于两通道或多通道图像,如果原始图像的某个像素的各个通道的像素值都在指定的阈值范围内,则输出图像中该像素值为255,否则为 0。

函数说明:

cv.inRange(src, lowerb, upperb[, dst]) → dst

参数说明:

  • src:输入图像,可以是灰度图像,也可以是多通道的彩色图像
  • lowerb:标量(src为单通道)或数组(src为多通道),下边界阈值
  • upperb:标量(src为单通道)或数组(src为多通道),上边界阈值
  • dst:输出图像,单通道的二值图像,大小与 src 相同,深度为 CV_8U

注意事项:

  1. 输入图像可以是灰度图像,也可以是多通道的彩色图像,但通常是 HSV 空间的彩色图像。
  2. 不论输入图像是单通道还是多通道图像,输出图像都是单通道灰度图像(二值图像),相当于输入图像的黑白遮罩 mask。
  3. 输入图像是单通道的灰度图像时,lower, upper 都是标量;输入图像是多通道的彩色图像时,lower, upper 都是数组,数组长度与通道数相同。
  4. 典型颜色的上下边界阈值 lower, upper 可以参考颜色阈值表。

使用色彩范围进行图像分割的基本程序如下:

# MattingRangeThresh.py
# Copyright 2021 youcans, XUPTy
# Crated:2021-12-10

# 1. 读取原始图像
imgOri = cv2.imread("../images/lady983Green.jpg")  # 读取原始图像
height, width, channels = imgOri.shape

# 2. 从原始图像提取绿色通道
imgGray = cv2.cvtColor(imgOri, cv2.COLOR_BGR2GRAY)  # 彩色图像转换为灰度图像
imgGreen = imgOri[:,:,1] 
print(imgOri.shape, imgGray.shape, imgGreen.shape)

# 3. 转换到 HSV 空间,对背景颜色范围进行阈值处理,生成遮罩 Mask、逆遮罩 MaskInv
# 使用 cv.nrange 函数在 HSV 空间检查设定的颜色区域范围,转换为二值图像,生成遮罩
# cv.inRange(src, lowerb, upperb[, dst]    ) -> dst
# inRange(frame,Scalar(low_b,low_g,low_r), Scalar(high_b,high_g,high_r))
 hsv = cv2.cvtColor(imgOri, cv2.COLOR_BGR2HSV)  # 将图片转换到 HSV 色彩空间
lowerColor = np.array([35, 43, 46])  # (下限: 绿色33/43/46,红色156/43/46,蓝色100/43/46)
 upperColor = np.array([77, 255, 255])  # (上限: 绿色77/255/255,红色180/255/255,蓝色124/255/255)
 binary = cv2.inRange(hsv, lowerColor, upperColor)  
binaryInv = cv2.bitwise_not(binary)

# 4. 用遮罩进行抠图和更换背景
# 生成抠图图像 (前景保留,背景黑色)
 imgMatte = cv2.bitwise_and(imgOri, imgOri, mask=binaryInv)  # 生成抠图前景,标准抠图以外的逆遮罩区域输出黑色
 imgReplace = imgOri.copy()
imgReplace[binaryInv==0] = [0,0,255]

plt.figure(figsize=(12,8))
 plt.subplot(231), plt.imshow(cv2.cvtColor(imgOri, cv2.COLOR_BGR2RGB)), plt.title("Origin image"), plt.axis('off')
 plt.subplot(232), plt.imshow(imgGray, cmap='gray'), plt.title("Gray image"), plt.axis('off')
 plt.subplot(233), plt.imshow(imgGreen, cmap='gray'), plt.title("Green channel level"), plt.axis('off')
 # plt.subplot(234), plt.imshow(binary, cmap='gray'), plt.title("binary mask"), plt.axis('off')
 plt.subplot(234), plt.imshow(binaryInv, cmap='gray'), plt.title("inv-binary mask"), plt.axis('off')
 plt.subplot(235), plt.imshow(cv2.cvtColor(imgMatte, cv2.COLOR_BGR2RGB)), plt.title("Matting Image"), plt.axis('off')
 plt.subplot(236), plt.imshow(cv2.cvtColor(imgReplace, cv2.COLOR_BGR2RGB)), plt.title("BgColor changed"), plt.axis('off')
 plt.tight_layout()

使用自适应阈值方法对单色背景图像抠图的结果如图3.6所示。
对于确定颜色背景的蓝屏抠图,基于色彩范围的阈值抠图取得了非常满意的效果,对人像的头发丝都可以进行很好的分割,其性能优于固定阈值和自适应阈值方法。

在这里插入图片描述
图3.6 色彩范围抠图法

【本节完】


版权声明:

欢迎关注『Python 小白的项目实战 @ youcans』 原创作品

原创作品,转载必须标注原文链接:https://blog.csdn.net/youcans/article/details/122296231

Copyright 2022 youcans, XUPT

Crated:2022-01-05


欢迎关注『Python 小白的项目实战 @ youcans』 原创作品
Python 小白的课题报告—OpenCV 抠图项目实战(1)
Python 小白的课题报告—OpenCV 抠图项目实战(2)
Python 小白的课题报告—OpenCV 抠图项目实战(3)
Python 小白的课题报告—OpenCV 抠图项目实战(4)
Python 小白的课题报告—OpenCV 抠图项目实战(5)
Python 小白的课题报告—OpenCV 抠图项目实战(6)

举报

相关推荐

0 条评论