文章目录
- 1 OpenCV的色彩空间
- 1.1 RGB和BGR
- 1.2 HSV, HSL和YUV
- 1.2.1 HSV(HSB)
- 1.2.2 HSL
- 1.2.3 YUV
- 1.3 色彩空间的转换
- 2 OpenCV的重要数据结构--Mat
- 2.1 Mat介绍
- 2.2 Mat拷贝
- 2.3 访问图像(Mat)的属性
- 2.4 通道的分离与合并
1 OpenCV的色彩空间
1.1 RGB和BGR
最常见的色彩空间就是RGB, 人眼也是基于RGB的色彩空间去分辨颜色的.
OpenCV默认使用的是BGR. BGR和RGB色彩空间的区别在于图片在色彩通道上的排列顺序不同.
显示图片的时候需要注意适配图片的色彩空间和显示环境的色彩空间.比如传入的图片是BGR色彩空间, 显示环境是RBG空间, 就会出现颜色混乱的情况.
RGBA中的A指的是透明度通道!
1.2 HSV, HSL和YUV
1.2.1 HSV(HSB)
- OpenCV用的最多的色彩空间是HSV.
- Hue: 色相, 即色彩, 如红色, 蓝色. 用角度度量,取值范围为0°~360°,从红色开始按逆时针方向计算,红色为0°,绿色为120°,蓝色为240°
- Saturation: 饱和度, 表示颜色接近光谱色的程度。一种颜色,可以看成是某种光谱色与白色混合的结果。其中光谱色所占的比例愈大,颜色接近光谱色的程度就愈高,颜色的饱和度也就愈高。饱和度高,颜色则深而艳。光谱色的白光成分为0,饱和度达到最高。通常取值范围为0%~100%,值越大,颜色越饱和。
- Value(Brightness): 明度. 明度表示颜色明亮的程度,对于光源色,明度值与发光体的光亮度有关;对于物体色,此值和物体的透射比或反射比有关。通常取值范围为0%(黑)到100%(白)。
为什么要使用HSV?
方便OpenCV做图像处理.比如根据hue的值就可以判断背景颜色.
1.2.2 HSL
HSL和HSV差不多.
- Hue: 色相
- Saturation: 饱和度
- Lightness: 亮度
HSL在顶部是纯白的, 不管是什么颜色.
HSV和HSL的区别:
HSB和HSL在字面上的意思是一样的: - H指的是色相(Hue),就是颜色名称,例如“红色”、“蓝色”;
- S指的是饱和度(Saturation),即颜色的纯度;
- L(Lightness)和B(Brightness)是明度,颜色的明亮程度.
在原理和表现上,HSL和HSB中的H(色相)完全一致,但二者的S(饱和度)不一样,L和B(明度)也不一样:
- HSB中的S控制纯色中混入白色的量,值越大,白色越少,颜色越纯;
- HSB中的B控制纯色中混入黑色的量,值越大,黑色越少,明度越高;
- HSL中的S和黑白没有关系,饱和度不控制颜色中混入黑白的多寡;
- HSL中的L控制纯色中的混入的黑白两种颜色。
用生活的例子来解释HSL和HSV中的S:
(1)HSL中的S:可以理解成稀释
10ml纯红色液体,饱和度为100%。加入1L纯净水,颜色就没那么红了,那么饱和度也下降了。
(2)HSV中的S:可以理解成混合
10ml纯红色液体,饱和度为100%。加入白色的液体混合在一起后,饱和度下降了。
1.2.3 YUV
YUV,是一种颜色编码方法。常使用在各个视频处理组件中。 YUV在对照片或视频编码时,考虑到人类的感知能力,允许降低色度的带宽。
“Y”表示明亮度(Luminance或Luma),也就是灰阶值,“U”和“V”表示的则是色度(Chrominance或Chroma),作用是描述影像色彩及饱和度,用于指定像素的颜色。
Y’UV的发明是由于彩色电视与黑白电视的过渡时期。
Y’UV最大的优点在于只需占用极少的带宽。
- 4:4:4表示完全取样。
- 4:2:2表示2:1的水平取样,垂直完全采样。
- 4:2:0表示2:1的水平取样,垂直2:1采样。
- 4:1:1表示4:1的水平取样,垂直完全采样。
1.3 色彩空间的转换
- cv2.cvtColor(src, code[, dst[, dstCn]]) 将输入图像从一个颜色空间转换为另一个颜色空间,颜色转换的关键API
- src: 输入图像
- code: 颜色空间转换代码(A指的是透明度)
- cv2.COLOR_BGR2RGBA,
- cv2.COLOR_BGR2BGRA,
- cv2.COLOR_BGR2GRAY,
- cv2.COLOR_BGR2HSV,
- cv2.COLOR_BGR2YUV
- dst: 输出与src相同大小和深度的图像
- dstCn: 目标图像的通道数,如果参数为0,则通道的数量自动从src和code派生
将trackbar与颜色空间转换结合实现对应的颜色转换代码:
# 关键API cv2.cvtColor
import cv2
def callback(value):
pass
cv2.namedWindow('color', cv2.WINDOW_NORMAL)
cv2.resizeWindow('color', 640, 480)
# 读取照片, OpenCV读进来的图片默认是BGR的色彩空间.
img = cv2.imread('./cat.jpeg')
# 定义颜色空间转化列表
color_spaces = [
# 所有颜色空间的转化都是COLOR开头
cv2.COLOR_BGR2RGBA, cv2.COLOR_BGR2BGRA,
cv2.COLOR_BGR2GRAY, cv2.COLOR_BGR2HSV,
cv2.COLOR_BGR2YUV
]
# 设置trackbar
cv2.createTrackbar('trackbar', 'color', 0, 4, callback)
while True:
# 获取trarckbar的值
index =cv2.getTrackbarPos('trackbar', 'color')
# 进行颜色空间转换
cvt_img = cv2.cvtColor(img, color_spaces[index])
cv2.imshow('color', cvt_img)
key = cv2.waitKey(10)
if key == ord('q'):
break
cv2.destroyAllWindows()
2 OpenCV的重要数据结构–Mat
2.1 Mat介绍
Mat是OpenCV在C++语言中用来表示图像数据的一种数据结构,C++中是用mat来保存图片.在python中转化为numpy的ndarray.
- Mat由header和data组成, header中记录了图片的维数, 大小, 数据类型等数据.
2.2 Mat拷贝
- Mat共享数据
在python中Mat数据对应numpy的ndarray, 使用numpy提供的深浅拷贝方法即可实现Mat的拷贝.
numpy的深浅拷贝的区别:
浅拷贝view( ):B复制A,A改变,B不改变
深拷贝copy( ):B复制A,A改变,B改变
# 因为python中图片数据已经包装成ndarray了, 所以对mat的深浅拷贝,其实就是对ndarray深浅拷贝.
import cv2
import numpy as np
cv2.namedWindow('img',cv2.WINDOW_NORMAL)
# cv2.resizeWindow('img',560,720)
img = cv2.imread('./cat.jpeg')
# 浅拷贝.
img2 = img.view()
# 深拷贝
img3 = img.copy()
# 对原始图片某个区域进行变红操作,看看img2和img3的变化
img[10:100, 10: 100] = [0, 0, 255]
# 竖着排
# cv2.imshow('img', np.vstack((img, img2, img3)))
# 横着排
cv2.imshow('img', np.hstack((img, img2, img3)))
cv2.waitKey(0)
cv2.destroyAllWindows()
2.3 访问图像(Mat)的属性
OpenCV中的Mat在python中已经转化为ndarray, 通过ndarray的属性即可访问Mat图像的属性
- shape( ):宽度、长度和通道数
- size( ):高度 * 长度 * 通道数
- dtype( ):位深
import cv2
import numpy as np
img = cv2.imread('cat.jpeg')
#shape属性中包括了三个信息
#高度,长度 和 通道数
print(img.shape)
#图像占用多大空间
#高度 * 长度 * 通道数
print(img.size)
#图像中每个元素的位深
print(img.dtype)
2.4 通道的分离与合并
- cv2.split(m[, mv]) 分割图像的通道
- m:传入的mat,即图片
- mv:输出的mat,不填
- merge(mv[, dst]) 融合多个通道
- mv:通道,用( )括起来要融合的通道
- dst:输出的图像mat,不填
# 图像的分割与融合
import cv2
import numpy as np
# 行,宽,通道数:BGR的通道数为3,全黑图片
img = np.zeros((200, 200, 3), np.uint8)
# 分割通道
b, g, r = cv2.split(img)
# 分别展示b,g,r
# cv2.imshow('b',b)
# cv2.imshow('g',g)
# cv2.imshow('r',r)
# print('b:', b)
# 修改一些颜色
b[10:100, 10:100] = 255
g[10:100, 10: 100] = 255
# 合并通道
img2 = cv2.merge((b, g, r))
# b,g全黑的图片里指定区域变白色
cv2.imshow('img', np.hstack((b, g)))
# img2的的颜色组成b,g指定区域为255,r为0
cv2.imshow('img2', np.hstack((img, img2)))
cv2.waitKey(0)
cv2.destroyAllWindows()