相关文章推荐
坚韧的大葱  ·  十分钟上手 Next.js - 知乎·  1 年前    · 
有腹肌的啄木鸟  ·  Outlook 365 - Insert ...·  1 年前    · 
风流的火柴  ·  Python ValueError: No ...·  1 年前    · 

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

本系列是 Python 小白的课题作业《基于OpenCV 的图像分割和抠图》。
需要说明的是,本系列并不能算是 OpenCV 的抠图项目教程,只是以此为主题的课题报告。其中包括了一个较为完整的 PyQt 项目。

欢迎关注 『Python 小白的项目实战 @ youcans』 原创作品
Python 小白的课题报告—OpenCV 抠图项目实战(1)目录摘要
Python 小白的课题报告—OpenCV 抠图项目实战(2)抠图绪论
Python 小白的课题报告—OpenCV 抠图项目实战(3)抠图综述
Python 小白的课题报告—OpenCV 抠图项目实战(4)固定阈值抠图
Python 小白的课题报告—OpenCV 抠图项目实战(5)自适应阈值抠图
Python 小白的课题报告—OpenCV 抠图项目实战(6)色彩范围抠图
Python 小白的课题报告—OpenCV 抠图项目实战(7)边缘检测
Python 小白的课题报告—OpenCV 抠图项目实战(8)图像轮廓
Python 小白的课题报告—OpenCV 抠图项目实战(9)评价指标
Python 小白的课题报告—OpenCV 抠图项目实战(10)PyQt5 使用
Python 小白的课题报告—OpenCV 抠图项目实战(11)算法实验平台
Python 小白的课题报告—OpenCV 抠图项目实战(12)源程序代码

第三章 阈值抠图

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
# 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

Crated:2022-01-05

欢迎关注『Python 小白的项目实战 @ youcans』 原创作品
Python 小白的课题报告—OpenCV 抠图项目实战(1)目录摘要
Python 小白的课题报告—OpenCV 抠图项目实战(2)抠图绪论
Python 小白的课题报告—OpenCV 抠图项目实战(3)抠图综述
Python 小白的课题报告—OpenCV 抠图项目实战(4)固定阈值抠图
Python 小白的课题报告—OpenCV 抠图项目实战(5)自适应阈值抠图
Python 小白的课题报告—OpenCV 抠图项目实战(6)色彩范围抠图
Python 小白的课题报告—OpenCV 抠图项目实战(7)边缘检测
Python 小白的课题报告—OpenCV 抠图项目实战(8)图像轮廓
Python 小白的课题报告—OpenCV 抠图项目实战(9)评价指标
Python 小白的课题报告—OpenCV 抠图项目实战(10)PyQt5 使用
Python 小白的课题报告—OpenCV 抠图项目实战(11)算法实验平台
Python 小白的课题报告—OpenCV 抠图项目实战(12)源程序代码

通常,即使对于确定颜色背景的蓝屏抠图,背景图像的所有像素的颜色也并非完全相同,而是处于相近的色彩范围内。因此,对背景色彩范围进行阈值处理,比阈值处理更为合理。RGB 通道不能很好地反映出物体具体的颜色信息,而 HSV 空间可以非常直观的表达色彩的明暗、色调及鲜艳程度。因此,通常使用 HSV 色彩空间进行某种颜色的识别和不同颜色的对比。
HSV 模型在对指定颜色分割时非常有效。用 H 和 S 分量表示颜色距离,颜色距离指代表两种颜色之间的数值差异。对于不同的彩色区域,混合 H 与 S 变量,划定阈值,就可以进行简单的分割。 函数 inRange () 可以实现按颜色区域 [lowerb,upperb] 对像进行二值分割 。 ............
皮肤检测与 皮肤检测的方法很多,这里写的是最简单的方法,感兴趣的同学可以自己加上椭圆检测,膨胀腐蚀等,使得检测与更加精确。github上许多人脸识别的算法,可以多学习那些。 HSV颜色空间 hsv涉及心理学的颜色知识,比rgb检测具有更好的分类效果 python 代码 def get_skin_hsv(img) hsv_img = cv2.cvtColor(img, cv2.COLOR_...
Java OpenCV是针对Java开发的一个开源计算机视觉库。它提供了许多处理像和视频的功能,包括是指从原始像中提取出感兴趣的对象或者将对象从背景中分离出来。在Java OpenCV中,可以使用GrabCut算法实现像的操作。 首先,我们需要加载原始像并创建一个和原始像一样大小的掩码像。然后,需要通过绘制一个矩形来指定要的对象的初始位置。接下来,可以使用GrabCut算法对像进行迭代处理,将对象和背景逐渐分离。 在每次迭代中,我们需要指定一个矩形来更新掩码像,标记哪些像素属于前景、背景或者未知区域。然后,根据模型的训练结果,可以通过对像素进行分类来更新掩码像。最终,可以通过将不属于前景的像素设置为背景来得到最终的结果。 在Java OpenCV中,可以使用Mat类来表示像和掩码像,使用Imgcodecs类加载和保存像,使用Imgproc类实现像处理操作,使用Rect类表示矩形区域。可以通过调用Imgproc.grabCut()方法来执行GrabCut算法。 总之,使用Java OpenCV可以实现像的操作,具体步骤包括加载原始像、创建掩码像、指定初始位置、迭代更新掩码像,并最终得到结果。通过这些步骤,可以实现在Java环境中方便地进行的应用开发。