opencv-python学习(五):色彩空间转换

一:调用转换函数实现图像色彩空间转换

代码如下:

# 引入包
import cv2 as cv
import numpy as np

def color_space_demo(image):
    gray = cv.cvtColor(image, cv.COLOR_RGB2GRAY) #RGB 转换为 gray -- RGB转灰度图
    cv.namedWindow("gray", cv.WINDOW_NORMAL)
    cv.imshow("gray", gray)
    hsv = cv.cvtColor(image, cv.COLOR_RGB2HSV) #RGB 转换为 hsv
    cv.namedWindow("hsv", cv.WINDOW_NORMAL)
    cv.imshow("hsv", hsv)
    yuv = cv.cvtColor(image, cv.COLOR_RGB2YUV) #RGB 转换为 yuv
    cv.namedWindow("yuv", cv.WINDOW_NORMAL)
    cv.imshow("yuv", yuv)

src = cv.imread("./static/image/blur.jpg")
cv.namedWindow("oldImage", cv.WINDOW_NORMAL) # 可以改变窗口大小
cv.imshow("oldImage", src)
color_space_demo(src)
cv.waitKey(0)
cv.destroyAllWindows()```

代码解释:
1、cv.cvtColor()
cv.cvtColor()用于将图像从一个颜色空间转换到另一个颜色空间的转换(目前常见的颜色空间均支持),并且在转换的过程中能够保证数据的类型不变,即转换后的图像的数据类型和位深与源图像一致。

调用形式如下:

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

src:它是要更改其色彩空间的图像。
code:它是色彩空间转换代码。
dst:它是与src图像大小和深度相同的输出图像。它是一个可选参数。
dstCn:它是目标图像中的频道数。如果参数为0,则通道数自动从src和代码得出。它是一个可选参数。
返回值:它返回一个图像。

2、颜色空间
RGB颜色空间

1、计算机色彩显示器和彩色电视机显示色彩的原理一样,都是采用R、G、B相加混色的原理,通过发射出三种不同强度的电子束,使屏幕内侧覆盖的红、绿、蓝磷光材料发光而产生色彩。这种色彩的表示方法称为RGB色彩空间表示。

2、在RGB颜色空间中,任意色光F都可以用R、G、B三色不同分量的相加混合而成:F=r[R]+r[G]+r[B]。RGB色彩空间还可以用一个三维的立方体来描述。当三基色分量都为0(最弱)时混合为黑色光;当三基色都为k(最大,值由存储空间决定)时混合为白色光。

3、RGB色彩空间采用物理三基色表示,因而物理意义很清楚,适合彩色显象管工作。然而这一体制并不适应人的视觉特点。因而,产生了其它不同的色彩空间表示法。

4、RGB 适合于显示系统,却并不适合于图像处理
因为在自然环境下获取的图像容易受自然光照、遮挡和阴影等情况的影响,即对亮度比较敏感,而 RGB 颜色空间的三个分量都与亮度密切相关,即只要亮度改变,三个分量都会随之相应地改变。另外,RGB 颜色空间是一种均匀性较差的颜色空间,人眼对于这三种颜色分量的敏感程度是不一样的,在单色中,人眼对红色最不敏感,蓝色最敏感,如果颜色的相似性直接用欧氏距离来度量,其结果与人眼视觉会有较大的偏差。对于某一种颜色,我们很难推测出较为精确的三个分量数值来表示。

YUV颜色空间

YUV(亦称YCrCb)是被欧洲电视系统所采用的一种颜色编码方法。

主要用在视频、图形处理流水线中。相对于 RGB 颜色空间,设计 YUV 的目的就是为了编码、传输的方便,减少带宽占用和信息出错。

人眼的视觉特点是对亮度更铭感,对位置、色彩相对来说不铭感。在视频编码系统中为了降低带宽,可以保存更多的亮度信息(luma),保存较少的色差信息(chroma)。相对于RGB,也可以节省很大的空间。
其中“Y”表示明亮度(Luminance或Luma),也就是灰阶值;而“U”和“V” 表示的则是色度(Chrominance或Chroma),作用是描述影像色彩及饱和度,用于指定像素的颜色。

HSV颜色空间

HSV 颜色空间比RGB更适用于图像处理

HSV是一种将RGB色彩空间中的点在倒圆锥体中的表示方法。HSV即色相(Hue)、饱和度(Saturation)、明度(Value),又称HSB(B即Brightness)。

色相是色彩的基本属性,就是平常说的颜色的名称,如红色、黄色等。饱和度(S)是指色彩的纯度,越高色彩越纯,低则逐渐变灰,取0-100%的数值。明度(V),取0-max(计算机中HSV取值范围和存储的长度有关)。HSV颜色空间可以用一个圆锥空间模型来描述。圆锥的顶点处,V=0,H和S无定义,代表黑色。圆锥的顶面中心处V=max,S=0,H无定义,代表白色。

RGB颜色空间中,三种颜色分量的取值与所生成的颜色之间的联系并不直观。而HSV颜色空间,更类似于人类感觉颜色的方式,封装了关于颜色的信息:“这是什么颜色?深浅如何?明暗如何?”
HSV能够直观地表达颜色的色调、鲜艳程度和明暗程度,方便进行颜色的对比,它比 BGR 更容易跟踪某种颜色的物体,常用于分割指定颜色的物体。

HSV色彩空间说明:
H:0-180 S: 0-255 V: 0-255

运行结果:
opencv-python学习(五):色彩空间转换_第1张图片

——————————————————————————————————————————————————————————

二:色彩空间转换,利用inrange函数过滤视频中的颜色,实现跟踪某一颜色

代码如下:

# 引入包
import cv2 as cv
import numpy as np

def nextrace_object_demo():
    capture = cv.VideoCapture("./static/video/test1.mp4") # 导入视频
    while True:
        ret, frame = capture.read()
        if ret == False:
            break
        hsv = cv.cvtColor(frame, cv.COLOR_RGB2HSV)
        # 设置白色的范围,跟踪视频中的白色
        lower_hsv = np.array([0, 0, 221]) # 设置过滤颜色的低值
        upper_hsv = np.array([180, 30, 255]) # 设置过滤颜色的高值
        mask = cv.inRange(hsv, lower_hsv, upper_hsv) # 调节图像的颜色信息(H)、饱和度(S)、亮度(V)区间,选择白色区间
        cv.imshow("video", frame)
        cv.imshow("mask", mask)
        if cv.waitKey(50) & 0xFF == ord('q'):
            break

nextrace_object_demo()
cv.waitKey(0)
cv.destroyAllWindows()

代码解释:
cv.VideoCapture():视频读取

cv.VideoCapture()既支持视频文件的读取,也支持从摄像机中视频的读取。cv.VideoCapture对象的创建方式有以下两种:
第一种方式是从文件(.MPG或.AVI格式)中读取视频,对象创建以后,OpenCV将会打开文件并做好准备读取它,如果打开成功,我们将可以开始读取视频的帧,并且cv.VideoCapture()的成员函数isOpened()将会返回true(建议在打开视频或摄像头时都使用该成员函数判断是否打开成功)。

第二种方式是从摄像机中读取视频,这种情况下,我们会给出一个标识符,用于表示我们想要访问的摄像机,及其与操作系统的握手方式。对于摄像机而言,这个标志符就是一个标志数字——如果只有1个摄像机,那么就是0,如果系统中有多个摄像机,那么只要将其向上增加即可。标识符另外一部分是摄像机域(camera domain),用于表示摄像机的类型。

ret, frame = capture.read()
读取摄像头,它能返回两个参数,第一个参数是bool型的ret,其值为true或false,代表有没有读取到图片;第二个参数是frame,是当前截取一帧图片

cv.inRange()函数的作用是:可以提取你想要的颜色,并把该颜色的区域设置为白色,其余的设置为黑色。
其实原理是这样的:在RGB三通道图像中,该函数会让你输入一个低值数组和高值数组,然后这个函数会扫描图片的每个像素,每个像素的值,即这个数组的每个值,如果相对应的,都在两个你输入的数组的,相对应的位置的数值内,那么这个数值会被设置为白色。否则只要有一个不在这个范围内,那么就会设置为黑色。

可以通过下表对应颜色的数值过滤其他颜色
HSV颜色对应RGB的分量范围:
opencv-python学习(五):色彩空间转换_第2张图片

运行结果:
opencv-python学习(五):色彩空间转换_第3张图片

————————————————————————————————————————————————————————

三:通道分离、合并,修改某一通道

代码如下:

# 引入包
import cv2 as cv
import numpy as np

src = cv.imread("./static/image/blur.jpg")
cv.namedWindow("oldImage", cv.WINDOW_NORMAL)
cv.imshow("oldImage", src)

# 通道分离,输出三个单通道图片
b, g, r = cv.split(src)# 将彩色图像分割成3个通道
cv.namedWindow("blue", cv.WINDOW_NORMAL)
cv.imshow("blue", b)

cv.namedWindow("green", cv.WINDOW_NORMAL)
cv.imshow("green", g)

cv.namedWindow("red", cv.WINDOW_NORMAL)
cv.imshow("red", r)

# 通道合并
src = cv.merge([b, g, r])
cv.namedWindow("merge", cv.WINDOW_NORMAL)
cv.imshow("merge", src)

# 修改某个通道的值
src[:, :, 0] = 100 # 取三维矩阵中第三维的所有数据
cv.namedWindow("single", cv.WINDOW_NORMAL)
cv.imshow("single", src)

# 而在cv2.split()分离出的图像基础上,扩展另外两个通道,但另外两个通道值为0, 就可以得到下面这样的图像。
src = cv.imread("./static/image/blur.jpg")
b, g, r = cv.split(src) # 将彩色图像分割成3个通道
zeros = np.zeros(src.shape[:2], "uint8") # uint8: 无符号整数(0到255)
cv.namedWindow("Blue", cv.WINDOW_NORMAL)
cv.imshow("Blue", cv.merge([b, zeros, zeros]))

cv.namedWindow("Green", cv.WINDOW_NORMAL)
cv.imshow("Green", cv.merge([zeros, g, zeros]))

cv.namedWindow("Red", cv.WINDOW_NORMAL)
cv.imshow("Red", cv.merge([zeros, zeros, r]))

# img.shape[:2]取彩色图片的长、宽
# img.shape[:3]取彩色图片的长、宽、通道
# img.shape[0]图像的垂直尺寸(高度)
# img.shape[1]图像的水平尺寸(宽度)
# img.shape[2]图像的通道数
# 注:矩阵中,[0]表示行数,[1]表示列数

cv.waitKey(0)
cv.destroyAllWindows()

代码解释:

split() 将彩色图像分割成3个通道,分离出来的顺序是逆序的

我们都知道常规的彩色图片一般都是三个通道RGB,Red=红色、Green=绿色、Blue=蓝色(有些图片还有第四个通道A,Alpha=透明度)

对于一张图片有几个通道,只需要通过img.shape进行查看就行了,比如我们读取一张图片,然后打印它的shape值

发现该图片高度为800px,宽度为600px,一共有三个channel
img (800, 600, 3)

现在试着将三个通道拆开,并将三个图像分别展示出来
但是很奇怪,为什么三张图片都变成了灰度图片了呢?

其实从之前的认识中我们已经知道了,一个通道的图片都是灰度图片,三个通道的图片才是彩色图片,现在我们将一张三个通道的图片拆成了三张单个通道的图片,在展示的时候自然就都变成了灰度图片。

打印一下这三张图片的shape值看一下,确实都是单通道的

channels[0] (800, 600)
channels[1] (800, 600)
channels[2] (800, 600)

merge()通道合并

看来光分离三个通道是没有办法单独查看纯色的图片的,那么我们就需要将这三个单通道的图片补全成三通道的图片

这里可以将自身以外的通道都填充为0,可以使用numpy.zeros方法来初始化全为0的图片,然后将分离出的单通道去覆盖响应的通道

补充 zeros = np.zeros(src.shape[:2], “uint8”) 中的src.shape[:2]
uint8: 无符号整数(0到255)
src.shape[:2]取彩色图片的长、宽
src.shape[:3]取彩色图片的长、宽、通道
src.shape[0]图像的垂直尺寸(高度)
src.shape[1]图像的水平尺寸(宽度)
src.shape[2]图像的通道数
注:矩阵中,[0]表示行数,[1]表示列数

运行结果:

opencv-python学习(五):色彩空间转换_第4张图片

你可能感兴趣的:(opencv,python,python,opencv)