HSV提供了更加直观的方式来感知颜色。在前面的色彩空间中,已经简要介绍过HSV色彩空间。本节将详细介绍HSV色彩空间,讲述获取指定颜色、标定指定颜色、标记肤色等知识点。

基础知识

所谓HSV,就是H (Hue,色调) 、S (Saturation,饱和度) 、V (亮度,Value) 。

色调H

在HSV色彩空间里,HSV中的H取值范围为[0,360],在OpenCV中,直接将色调角度除以2,得到[0,180]之间的值,以适应8位二进制(256个灰度级)的存储和表示范围。

饱和度S

灰度颜色中。RGB都是相等的,饱和度为0。饱和度的范围应该为[0,1],为了适应8位图的256个像素级,需要将其映射为[0,255]。

亮度V

亮度的范围为[0,1],亮度值OpenCV将值映射为[0,255]。

亮度值越大,图像越亮。当亮度为0时,为纯黑色。

获取指定颜色

在OpenCV中,测试RGB色彩空间中的值转换到HSV色彩空间后的值。

为了方便理解,这里分别对红绿蓝单项色进行显示。

import cv2
import numpy as np
# ------------------------------蓝色
imgBlue = np.zeros([1, 1, 3], dtype=np.uint8)
imgBlue[0, 0, 0] = 255
Blue = imgBlue
BlueHSV = cv2.cvtColor(Blue, cv2.COLOR_BGR2HSV)
print("Blue=\n", Blue)
print("BlueHSV=\n", BlueHSV)

# ------------------------------绿色
imgGreen = np.zeros([1, 1, 3], dtype=np.uint8)
imgGreen[0, 0, 1] = 255
Green = imgGreen
GreenHSV = cv2.cvtColor(Green, cv2.COLOR_BGR2HSV)
print("Green=\n", Green)
print("GreenHSV=\n", GreenHSV)

# ------------------------------红色
imgRED = np.zeros([1, 1, 3], dtype=np.uint8)
imgRED[0, 0, 2] = 255
RED = imgRED
REDHSV = cv2.cvtColor(RED, cv2.COLOR_BGR2HSV)
print("RED=\n", RED)
print("REDHSV=\n", REDHSV)

结果

Blue=
[[[255 0 0]]]
BlueHSV=
[[[120 255 255]]]
Green=
[[[ 0 255 0]]]
GreenHSV=
[[[ 60 255 255]]]
RED=
[[[ 0 0 255]]]
REDHSV=
[[[ 0 255 255]]]

标记指定颜色

颜色的差异主要体现在H通道的不同,通过对H通道值进行筛选,便能够筛选出特定的颜色。

通过inRange函数锁定特定值

OpenCV中,通过cv2.inRange()来判断图像内像素点是否在范围内。

dst = cv2.inRange( src, lowerb, upperb)

  • dst 表示输出结果
  • src表示要检查的数组或者图像
  • lowerb表示范围下界
  • upperb表示范围上界
  • src在指定区域,那么dst对应位置值为255
  • src在指定区域,那么dst对应位置值为0

说实话,这和matlab里的一些字符串函数是一样的。这里用一个二维数组来演示。

import cv2
import numpy as np
img = np.random.randint(0, 256, size=[5, 5], dtype=np.uint8)
min = 100
max = 200
msk = cv2.inRange(img, min, max)
print("img = \n", img)
print("msk = \n", msk)

结果:

img =
[[130 117 115 172 183]
[216 104 122 165 118]
[175 5 249 250 187]
[154 15 129 219 19]
[135 28 106 255 21]]
msk =
[[255 255 255 255 255]
[ 0 255 255 255 255]
[255 0 0 0 255]
[255 0 255 0 0]
[255 0 255 0 0]]

显示特定颜色值

例 :分别提取OpenCV的logo里的红绿蓝颜色。

需要注意的是,在提取颜色的时候,往往不能提取特定的值,而是提取一个范围,区域一般为10~15这样

H通道表示颜色,S通道和V通道的取值范围一般为[100,255],当饱和度或亮度太低时,计算的色调可能就不是很可靠。根据上述分析,各颜色的范围:

  • 蓝色:[110,100,100] 到 [130, 255, 255]
  • 绿色:[50,100,100] 到 [70, 255, 255]
  • 红色:[0,100,100] 到 [10, 255, 255]

色调值及对应的颜色及映射后色调及对应颜色

import cv2
import numpy as np
opencv = cv2.imread('OPENCVLOGO.jpg')
hsv = cv2.cvtColor(opencv, cv2.COLOR_BGR2HSV)
cv2.imshow('OPENCV', opencv)

# --------指定蓝色区域-------
minBlue = np.array([110, 50, 50])
maxBlue = np.array([130, 255, 255])
maskBlue = cv2.inRange(hsv, minBlue, maxBlue)
# 通过掩码按位与操作,锁定蓝色区域
blue = cv2.bitwise_and(opencv, opencv, mask=maskBlue)
cv2.imshow('blue', blue)

# --------指定绿色区域-------
minGreen = np.array([50, 50, 50])
maxGreen = np.array([70, 255, 255])
maskGreen = cv2.inRange(hsv, minGreen, maxGreen)
# 通过掩码按位与操作,锁定绿色区域
Green = cv2.bitwise_and(opencv, opencv, mask=maskGreen)
cv2.imshow('Green', Green)

# --------指定红色区域-------
minRed = np.array([0, 50, 50])
maxRed = np.array([10, 255, 255])
maskRed = cv2.inRange(hsv, minRed, maxRed)
# 通过掩码按位与操作,锁定红色区域
Red = cv2.bitwise_and(opencv, opencv, mask=maskRed)
cv2.imshow('Red', Red)
cv2.waitKey()

运行结果

标记肤色

在标定颜色的基础上,可以将标注范围进一步推广到特定的对象上,可以估算肤色在HSV的范围,然后在HSV空间内筛选出肤色范围内的值,即可将肤色部分提取出来。

在素材里,我找了一个大美女的图片,背景已经经过了我的抠图处理,选择背景为纯白色,主要是为了简化程序,因为这里只是做个演示。

  • 假定色调值在[5,170]之间
  • 饱和度值在[25,166]之间
import cv2
img = cv2.imread('C:/Users/Administrator/Desktop/Blog/Opencv/mn.png')
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
h, s, v = cv2.split(hsv)
minHue = 5
maxHue = 170
hueMask = cv2.inRange(h, minHue, maxHue)
minSat = 25
maxSat = 166
satMask = cv2.inRange(s, minSat, maxSat)
msk = hueMask & satMask
roi = cv2.bitwise_and(img, img, mask=msk)
cv2.imshow('img', img)
cv2.imshow('ROI', roi)
cv2.waitKey()

程序运行结果

思考:右图为什么不该黑的地方黑了呢?

调整图片亮度

将一幅图像的H通道和S通道的值保持不变,而将其V通道的值都调整为255,即设置为最亮,观察得到的效果。

import cv2
img = cv2.imread('boy.png')
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
h, s, v = cv2.split(hsv)
print(v)
v[:, :] = 255
newHSV = cv2.merge([h, s, v])
mynew = cv2.cvtColor(newHSV, cv2.COLOR_HSV2BGR)
cv2.imshow('img', img)
cv2.imshow('ART', mynew)
cv2.waitKey()

程序运行结果图

素材

OpenCV的LOGO

大美女(图片来源于百度图片,如有侵权,请联系博主)

小男孩(图片来源于百度图片,如有侵权,请联系博主)


博主个人公众号
版权声明 ▶ 本网站名称:陶小桃Blog
▶ 本文链接:https://www.52txr.cn/2021/OpenCV13.html
▶ 本网站的文章部分内容可能来源于网络,仅供大家学习与参考,如有侵权,请联系站长进行核实删除。
▶ 转载本站文章需要遵守:商业转载请联系站长,非商业转载请注明出处!!

最后修改:2022 年 05 月 24 日
如果觉得我的文章对你有用,请随意赞赏