| 授 课 班 级 | 20级人工智能1 、2班 | 授 课 日 期 | |
| 教 学 课 题 | 色彩空间类型转换 | ||
| 教学目的及要求 | 了解色彩空间基础,掌握类型转换函数 | ||
| 教 学 重 点 | 色彩类型转换函数 | ||
| 教 学 难 点 | HSV色彩空间、alpha通道 | ||
| 教 学 方 法 | 讲授法、项目化教学法 | ||
| 教 具 | 计算机、Anaconda软件 | ||
| 作 业 | |||
| 教学过程及内容 | 见下 | ||
基础:
RGB图像是一种常见的色彩空间类型,除此之外还有一些其他的色彩空间,比较常见的包括GRAY色彩空间(灰度图像)、XYZ色彩空间、YCrCb色彩空间、HSV色彩空间、HLS色彩空间、CIEL*a*b*色彩空间、CIEL*u*v*色彩空间、Bayer色彩空间。每个色彩空间都有自己擅长的处理问题的领域,因此,为了更方便地处理某个具体问题,就要用到色彩空间类型转换。
色彩空间类型转换就是指,将图像从一个色彩空间转换到另外一个色彩空间。
色彩空间也称为颜色空间、彩色空间、颜色模型、彩色模型、色彩模型等。
4.1GRAY色彩空间
GRAY(灰度图像)通常指8位灰度图,其具有256个灰度级,像素值的范围为【0-255】
Gray=0.299R+0.587G+0.114B
Gray=(R+G+B)/3
4.2类型转换函数
Dst=cv2.cvtColor(src,code)
a=cv2.imread("lenacolor.png",-1)
aa=cv2.imread("lena256.bmp",-1)
b=cv2.cvtColor(a,cv2.COLOR_BGR2GRAY)#BGR图像转灰度图像
c=cv2.cvtColor(a,cv2.COLOR_BGR2RGB)#BGR图像转RGB图像
d=cv2.cvtColor(aa,cv2.COLOR_GRAY2BGR)#灰度值转换成BGR图像
print(d.shape)
cv2.imshow("a",a)
cv2.imshow("BGR2GRAY",b)
cv2.imshow("BGR2RGB",c)
cv2.imshow("GRAY2BGR",d)
cv2.waitKey()
cv2.destroyAllWindows()
通过数组观察转换效果
例4.1将BGR图像转换为灰度图像
Gray=0.299R+0.587G+0.114B
#4.1将BGR图像转换为灰度图像
import cv2
import numpy as np
img=np.random.randint(0,256,size=[2,4,3],dtype=np.uint8)
rst=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
print("img=\n",img)
print("rst=\n",rst)
print("像素点(1,0)直接计算得到的值=",
img[1,0,0]*0.114+img[1,0,1]*0.587+img[1,0,2]*0.299)
print("像素点(1,0)使用公式cv2.cvtColor()转换值=",rst[1,0])
print(img[1,0,0])
print(img[1,0,1])
print(img[1,0,2])
运行结果:
img=
[[[ 56 98 47]
[201 140 198]
[246 255 167]
[108 176 148]]
[[ 76 27 104]
[121 115 129]
[163 7 136]
[249 93 123]]]
rst=
[[ 78 164 228 160]
[ 56 120 63 120]]
像素点(1,0)直接计算得到的值= 55.608999999999995
像素点(1,0)使用公式cv2.cvtColor()转换值= 56
76
27
104
#例4.2将灰度图像转换为BGR图像
import cv2
import numpy as np
img=np.random.randint(0,256,size=[2,4],dtype=np.uint8)
rst=cv2.cvtColor(img,cv2.COLOR_GRAY2BGR)
print("img=\n",img)
print("rst=\n",rst)
运行结果:
img=
[[237 60 217 91]
[113 41 236 166]]
rst=
[[[237 237 237]
[ 60 60 60]
[217 217 217]
[ 91 91 91]]
[[113 113 113]
[ 41 41 41]
[236 236 236]
[166 166 166]]]
上述程序进一步印证了,当图像由GRAY色彩空间转换到RGB/BGR色彩空间时,最终所有通道的值都是相同。
R=Gray
G=Gray
B=Gray
例4.3将图像在BGR和RGB模式之间相互转换
import cv2
import numpy as np
img=np.random.randint(0,256,size=[2,4,3],dtype=np.uint8)
rgb=cv2.cvtColor(img,cv2.COLOR_BGR2RGB)
bgr=cv2.cvtColor(rgb,cv2.COLOR_RGB2BGR)
print("img=\n",img)
print("rgb=\n",rgb)
print("bgr=\n",bgr)运行结果:
img=
[[[ 24 141 13]
[201 62 193]
[146 85 152]
[ 81 237 4]]
[[ 82 131 106]
[ 59 199 42]
[141 195 122]
[189 153 193]]]
rgb=
[[[ 13 141 24]
[193 62 201]
[152 85 146]
[ 4 237 81]]
[[106 131 82]
[ 42 199 59]
[122 195 141]
[193 153 189]]]
bgr=
[[[ 24 141 13]
[201 62 193]
[146 85 152]
[ 81 237 4]]
[[ 82 131 106]
[ 59 199 42]
[141 195 122]
[189 153 193]]]
从程序可以看到,在RGB和BGR模式之间相互转换时,R通道和B通道的位置发生了交换。
图像处理实例
#例4.4 将图像在BGR模式和灰度图像之间相互转换
#RGB<->GRAY
import cv2
lena=cv2.imread("lenacolor.png")
gray=cv2.cvtColor(lena,cv2.COLOR_BGR2GRAY)
rgb=cv2.cvtColor(gray,cv2.COLOR_GRAY2BGR)
#==========打印shape============
print("lena.shape=",lena.shape)
print("gray.shape=",gray.shape)
print("rgb.shape=",rgb.shape)
#==========显示效果============
cv2.imshow("lena",lena)
cv2.imshow("gray",gray)
cv2.imshow("rgb",rgb)
cv2.waitKey()
cv2.destroyAllWindows()
#4.5将图像从BGR模式转换为RGB模式
import cv2
lena=cv2.imread("lenacolor.png")
rgb = cv2.cvtColor(lena, cv2.COLOR_BGR2RGB)
cv2.imshow("lena",lena)
cv2.imshow("rgb",rgb)
cv2.waitKey()
cv2.destroyAllWindows()
4.4HSV色彩空间
HSV色彩空间从心理学和视觉的角度出发,提出人眼的色彩知觉主要包含三要素:
H:色调(Hue,也称为色相)
S:饱和度(Saturation)
V:亮度(Value)
1.色调
在HSV色彩空间中,色调H的取值范围为【0,360】,8位图像内每个像素点所能表示的灰度级有28=256个,所有在8位图像内表示HSV图像时,要把色调的角度值映射到【0,255】范围内,在OpenCV中,可以直接把色调的角度值除以2,得到【0,180】之间的值,以适应8位二进制(256个灰度级)的存储和表示范围。
色调值及对应颜色
色调值(度) | 颜色 |
0 | 红色 |
60 | 黄色 |
120 | 绿色 |
180 | 青色 |
240 | 蓝色 |
300 | 品红色 |
在OPENCV中,将色调值除以2之后,会得到色调值与对应的颜色
色调值(度) | 颜色 |
0 | 红色 |
30 | 黄色 |
60 | 绿色 |
90 | 青色 |
120 | 蓝色 |
150 | 品红色 |
2. 饱和度
饱和度值的范围是【0,1】
灰度颜色所包含的R、G、B的成分是相等的,相当于一种极不饱和的颜色,所以,灰度颜色的饱和度值是0.
作为灰度图像显示时,较亮区域对应的颜色具有较高的饱和度。
如果颜色的饱和度很低,那么它计算所得色调就不靠谱。
3. 亮度V
亮度的范围都是【0,1】,同样,亮度值在OpenCV内也将值映射到【0,255】范围内。
亮度值越大,图像越亮;亮度值越低,图像越暗。当亮度值为0时,图像是纯黑色。
#4.6在OpenCV中,测试RGB色彩空间中不同颜色的值转换到HSV色彩空间后的对应值
import cv2
import numpy as np
#=========测试下OpenCV中蓝色的HSV模式值=============
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)
#=========测试下OpenCV中绿色的HSV模式值=============
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)
#=========测试下OpenCV中红色的HSV模式值=============
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]]]
4.4.3标记指定颜色
1. 通过inRange函数锁定特定值
Cv2.inRange()来判断图像内像素点的像素值是否在指定的范围内,其语法格式为:
Dst=cv2.inRange(src,lowerb,upperb)
说明:
dst表示输出结果,大小和src一致
src表示要检查的数组或图像
lowerb表示范围下界
upperb表示范围上界
返回值dst与src等大小,其值取决于src中对应位置上的值是否处于区间[lowerb,upperb]内:
如果src值处于该指定区间内,则dst中对应位置上的值为255。
如果src值不处于该指定区间内,则dst中对应位置上的值为0。
#4.7使用函数cv2.inRange()将某个图像内的在[100,200]内的值标注出来
import cv2
import numpy as np
img=np.random.randint(0,256,size=[5,5],dtype=np.uint8)
min=100
max=200
mask = cv2.inRange(img, min, max)
print("img=\n",img)
print("mask=\n",mask)
运行结果:
img=
[[143 206 226 68 237]
[ 48 0 216 122 60]
[109 108 47 50 26]
[232 232 0 20 216]
[ 79 233 18 188 246]]
mask=
[[255 0 0 0 0]
[ 0 0 0 255 0]
[255 255 0 0 0]
[ 0 0 0 0 0]
[ 0 0 0 255 0]]
说明:在100-200内的值标记为255,不在100-200范围内的值标记为0.
#4.8正常显示某个图像内的感兴趣区域(ROI),而将其余区域显示为黑色
import cv2
import numpy as np
img=np.ones([5,5],dtype=np.uint8)*9
mask =np.zeros([5,5],dtype=np.uint8)
mask[0:3,0]=1
mask[2:5,2:4]=1
roi=cv2.bitwise_and(img,img, mask= mask)
print("img=\n",img)
print("mask=\n",mask)
print("roi=\n",roi)
显示特定颜色值:
在实际提取颜色时,往往不是提取一个特定的值,而是提取一个颜色区间。例如在OPENCV中的HSV模式内,蓝色在H通道内的值是120,在提取蓝色时,通常将“蓝色值120”附近的一个区间的值作为提取范围,该区间的半径通常为10左右,例如通常提取[120-10,120+10]范围内的值来指定蓝色。
HSV模式中S通道、V通道的值的取值范围一般是【100,255】,这主要是因为,当饱和度和亮度太低时,计算出来的色调不可靠。
根据上述分析,各种颜色的HSV区间值分布在[H-10,100,100]和[H+10,255,255]之间。因此,各种颜色值的范围为:
蓝色:值分布在[110,100,100]和[130,255,255]之间
绿色:值分布在[50,100,100]和[70,255,255]之间
红色:值分布在[0,100,100]和[10,255,255]之间
#4.9分别提取OpenCV的logo图像内的红色、绿色、蓝色。
import cv2
import numpy as np
opencv=cv2.imread("opencv.jpg")
hsv = cv2.cvtColor(opencv, cv2.COLOR_BGR2HSV)
cv2.imshow('opencv',opencv)
#=============指定蓝色值的范围=============
minBlue = np.array([110,50,50])
maxBlue = np.array([130,255,255])
#确定蓝色区域
mask = cv2.inRange(hsv, minBlue, maxBlue)
#通过掩码控制的按位与,锁定蓝色区域
blue = cv2.bitwise_and(opencv,opencv, mask= mask)
cv2.imshow('blue',blue)
#=============指定绿色值的范围=============
minGreen = np.array([50,50,50])
maxGreen = np.array([70,255,255])
#确定绿色区域
mask = cv2.inRange(hsv, minGreen, maxGreen)
#通过掩码控制的按位与,锁定绿色区域
green = cv2.bitwise_and(opencv,opencv, mask= mask)
cv2.imshow('green',green)
#=============指定红色值的范围=============
minRed = np.array([0,50,50])
maxRed = np.array([30,255,255])
#确定红色区域
mask = cv2.inRange(hsv, minRed, maxRed)
#通过掩码控制的按位与,锁定红色区域
red= cv2.bitwise_and(opencv,opencv, mask= mask)
cv2.imshow('red',red)
cv2.waitKey()
cv2.destroyAllWindows()
运行结果:
标记肤色
肤色范围划定为:
色调值在【5,170】之间
饱和度值在【25,166】之间
#4.10 提取一副图像内的肤色部门
import cv2
img=cv2.imread("lesson2.jpg")
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)
mask = hueMask & satMask
roi = cv2.bitwise_and(img,img, mask= mask)
cv2.imshow("img",img)
cv2.imshow("ROI",roi)
cv2.waitKey()
cv2.destroyAllWindows()
运行结果:
实现艺术字效果:
保持H通道和S通道的值不变,而将V通道的值都调整为255,即设置为最亮,观察得到的艺术效果。
#4.11调整HSV色彩空间内V通道的值,观察其处理结果
import cv2
img=cv2.imread("barbara.bmp")
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
h,s,v=cv2.split(hsv)
v[:,:]=255
newHSV=cv2.merge([h,s,v])
art = cv2.cvtColor(newHSV, cv2.COLOR_HSV2BGR)
cv2.imshow("img",img)
cv2.imshow("art",art)
cv2.waitKey()
cv2.destroyAllWindows()
运行结果:
4.5alpha通道
在RGB色彩空间三个通道的基础上,还可以加上一个A通道,也叫alpha通道,表示透明度,这种4个通道的色彩空间被称为RGBA色彩空间,PNG图像是一种典型的4通道图像,alpha通道的赋值范围是【0,1】,或者【0,255】,表示从透明到不透明
#4.12编写一个程序,分析alpha通道的值
import cv2
import numpy as np
img=np.random.randint(0,256,size=[2,3,3],dtype=np.uint8)
bgra = cv2.cvtColor(img, cv2.COLOR_BGR2BGRA)
print("img=\n",img)
print("bgra=\n",bgra)
b,g,r,a=cv2.split(bgra)
print("a=\n",a)
a[:,:]=125
bgra=cv2.merge([b,g,r,a])
print("bgra=\n",bgra)
运行结果:
img=
[[[151 79 170]
[ 60 237 101]
[127 193 248]]
[[ 67 51 190]
[180 41 147]
[ 44 100 41]]]
bgra=
[[[151 79 170 255]
[ 60 237 101 255]
[127 193 248 255]]
[[ 67 51 190 255]
[180 41 147 255]
[ 44 100 41 255]]]
a=
[[255 255 255]
[255 255 255]]
bgra=
[[[151 79 170 125]
[ 60 237 101 125]
[127 193 248 125]]
[[ 67 51 190 125]
[180 41 147 125]
[ 44 100 41 125]]]
#4.13编写一个程序,对图像的alpha通道进行处理
import cv2
img=cv2.imread("lenacolor.png")
bgra = cv2.cvtColor(img, cv2.COLOR_BGR2BGRA)
b,g,r,a=cv2.split(bgra)
a[:,:]=125
bgra125=cv2.merge([b,g,r,a])
a[:,:]=0
bgra0=cv2.merge([b,g,r,a])
cv2.imshow("img",img)
cv2.imshow("bgra",bgra)
cv2.imshow("bgra125",bgra125)
cv2.imshow("bgra0",bgra0)
cv2.waitKey()
cv2.destroyAllWindows()
cv2.imwrite("bgra.png", bgra)
cv2.imwrite("bgra125.png", bgra125)
cv2.imwrite("bgra0.png", bgra0)

