图像颜色识别

1. RGB颜色空间

在图像处理中,最常见的就是RGB颜色空间。RGB颜色空间是我们接触最多的颜色空间,是一种用于表示和显示彩色图像的一种颜色模型。RGB代表红色(Red)、绿色(Green)和蓝色(Blue),这三种颜色通过不同强度的光的组合来创建其他颜色,广泛应用于我们的生活中,比如电视、电脑显示屏以及上面实验中所介绍的RGB彩色图。

RGB颜色模型基于笛卡尔坐标系,如下图所示,RGB原色值位于3个角上,二次色青色、红色和黄色位于另外三个角上,黑色位于原点处,白色位于离原点最远的角上。因为黑色在RGB三通道中表现为(0,0,0),所以映射到这里就是原点;而白色是(255,255,255),所以映射到这里就是三个坐标为最大值的点。

在这里插入图片描述

RGB颜色空间可以产生大约1600万种颜色,几乎包括了世界上的所有颜色,也就是说可以使用RGB颜色空间来生成任意一种颜色。

注意:在OpenCV中,颜色是以BGR的方式进行存储的,而不是RGB,这也是上面红色的像素值是(0,0,255)而不是(255,0,0)的原因。

你可以使用OpenCV的cv.add()函数把两幅图像相加,或者可以简单地通过numpy操作添加两个图像,如res = img1 + img2。两个图像应该具有相同的大小和类型。

OpenCV加法和Numpy加法之间存在差异。OpenCV的加法是饱和操作,而Numpy添加是模运算

#OpenCV加法与numpy加法的区别:
x=np.uint8([255])
y=np.uint8([10])
print(cv2.add(x,y)) #255+10=265>=255,因此结果就为255
[[255]]
print(x+y)          #255+10=265%256=9
[9]

import cv2
import numpy as np
#cv2.add()图像加法:
img1=np.array([[10,20,30],
               [255,249,254]],dtype=np.uint8)
img2=np.array([[10,20,30],
               [255,249,254]],dtype=np.uint8)
img3=cv2.add(img1,img2,)#加法过后超出255,会保留255
print(img3)

#打印结果:
[[ 20  40  60]
 [255 255 255]]
import numpy as np
x=np.array([[10,20,30],
             [255,249,254]],dtype=np.uint8)
x2=x+20
print(x2) #uint8的范围为0~256,相加超出范围后取余

#打印结果:
[[30 40 50]
 [19 13 18]]

3. 颜色加权加法

这其实也是加法,但是不同的是两幅图像的权重不同,这就会给人一种混合或者透明的感觉。图像混合的计算公式如下:

g(x) = (1−α)f0(x) + αf1(x)

通过修改 α 的值(0 → 1),可以实现非常炫酷的混合。

现在我们把两幅图混合在一起。第一幅图的权重是0.7,第二幅图的权重是0.3。函数cv2.addWeighted()可以按下面的公式对图片进行混合操作。

dst = α⋅img1 + β⋅img2 + γ

这里γ取为零。

# 加权加法
import cv2
import numpy as np
# 1 读取图像
image1 = cv2.imread("./pig.png")
image2 = cv2.imread("./cao.png")
# 2 图像混合
image3 = cv2.addWeighted(image1,0.7,image2,0.3,0)
cv2.imshow("image3",image3)
cv2.waitKey(0)

4. HSV颜色空间

HSV颜色空间指的是HSV颜色模型,这是一种与RGB颜色模型并列的颜色空间表示法。RGB颜色模型使用红、绿、蓝三原色的强度来表示颜色,是一种加色法模型,即颜色的混合是添加三原色的强度。而HSV颜色空间使用色调(Hue)、饱和度(Saturation)和亮度(Value)三个参数来表示颜色,色调H表示颜色的种类,如红色、绿色、蓝色等;饱和度表示颜色的纯度或强度,如红色越纯,饱和度就越高;亮度表示颜色的明暗程度,如黑色比白色亮度低。

HSV颜色模型是一种六角锥体模型,如下图所示:

在这里插入图片描述

色调H:

使用角度度量,取值范围为0°~360°,从红色开始按逆时针方向计算,红色为0°,绿色为120°,蓝色为240°。它们的补色是:黄色为60°,青色为180°,紫色为300°。通过改变H的值,可以选择不同的颜色

饱和度S:

饱和度S表示颜色接近光谱色的程度。一种颜色可以看成是某种光谱色与白色混合的结果。其中光谱色所占的比例越大,颜色接近光谱色的程度就越高,颜色的饱和度就越高。饱和度越高,颜色就越深而艳,光谱色的白光成分为0,饱和度达到最高。通常取值范围为0%~100%,其中0%表示灰色或无色,100%表示纯色,通过调整饱和度的值,可以使颜色变得更加鲜艳或者更加灰暗。

明度V:

明度表示颜色明亮的程度,对于光源色,明度值与发光体的光亮度有关;对于物体色,此值和物体的透射比或反射比有关。通常取值范围为0%(黑)到100%(白),通过调整明度的值,可以使颜色变得更亮或者更暗。

一般对颜色空间的图像进行有效处理都是在HSV空间进行的,然后对于基本色中对应的HSV分量需要给定一个严格的范围,下面是通过实验计算的模糊范围(准确的范围在网上都没有给出)。

H: 0— 180

S: 0— 255

V: 0— 255

此处把部分红色归为紫色范围:

在这里插入图片描述

为什么有了RGB颜色空间我们还是需要转换成HSV颜色空间来进行图像处理呢?

  • 符合人类对颜色的感知方式:人类对颜色的感知是基于色调、饱和度和亮度三个维度的,而HSV颜色空间恰好就是通过这三个维度来描述颜色的。因此,使用HSV空间处理图像可以更直观地调整颜色和进行色彩平衡等操作,更符合人类的感知习惯。
  • 颜色调整更加直观:在HSV颜色空间中,色调、饱和度和亮度的调整都是直观的,而在RGB颜色空间中调整颜色不那么直观。例如,在RGB空间中要调整红色系的颜色,需要同时调整R、G、B三个通道的数值,而在HSV空间中只需要调整色调和饱和度即可。
  • 降维处理有利于计算:在图像处理中,降维处理可以减少计算的复杂性和计算量。HSV颜色空间相对于RGB颜色空间,减少了两个维度(红、绿、蓝),这有利于进行一些计算和处理任务,比如色彩分割、匹配等。

因此,在进行图片颜色识别时,我们会将RGB图像转换到HSV颜色空间,然后根据颜色区间来识别目标颜色。

5. 制作掩膜

掩膜(Mask)是一种在图像处理中常见的操作,它用于选择性地遮挡图像的某些部分,以实现特定任务的目标。掩膜通常是一个二值化图像,并且与原图像的大小相同,其中目标区域被设置为1(或白色),而其他区域被设置为0(或黑色),并且目标区域可以根据HSV的颜色范围进行修改,如下图就是制作红色掩膜的过程:

在这里插入图片描述

通过这个掩膜,我们就可以对掩膜中的白色区域所对应的原图中的区域进行处理与操作。

import cv2
import numpy as np
if __name__ == "__main__":
    path = "./demo.png"
    image_np = cv2.imread(path)
    hsv_image_np = cv2.cvtColor(image_np, cv2.COLOR_BGR2HSV)  # 转为HSV空间
    color_low = np.array([26, 43, 46])#HSV空间黄色最小值
    color_high = np.array([34, 255, 255])#HSV空间黄色最大值
    #cv2.inRange用于进行多通道图像(尤其是彩色图像)的阈值操作。它将图像中的每个像素值与指定的颜色范围进行比较,并根据比较结果生成一个二值图像(通常称为掩模或标记图像),其中白色像素代表原图中对应位置的像素颜色在设定范围内,而黑色像素则表示不在该范围内。
    mask_image_np = cv2.inRange(hsv_image_np, color_low, color_high)  # 创建掩膜
    cv2.imshow("origin_image_np", image_np)
    cv2.imshow("mask_image_np", mask_image_np)
    cv2.waitKey(0)

4. 与运算

我们在高中时学过逻辑运算中的“与”运算,其规则是当两个命题都是真时,其结果才为真。而在图像处理中,“与”运算被用来对图像的像素值进行操作。具体来说,就是将两个图像中所有的对应像素值一一进行“与”运算,从而得到新的图像。从上面的图片我们可以看出,掩膜中有很多地方是黑色的,其像素值为0,那么在与原图像进行“与”运算的时候,得到的新图像的对应位置也是黑色的,如下图所示:

在这里插入图片描述

通过掩膜与原图的与运算,我们就可以提取出图像中被掩膜覆盖的区域(扣图)。

import cv2
import numpy as np

if __name__ == "__main__":
    path = "./demo.png"
    image_np = cv2.imread(path)
    hsv_image_np = cv2.cvtColor(image_np, cv2.COLOR_BGR2HSV)  # 转为HSV空间

    color_low = np.array([26, 43, 46])#黄色的最小值
    color_high = np.array([34, 255, 255])#黄色的最大值
     
    mask_image_np = cv2.inRange(hsv_image_np, color_low, color_high)  # 创建掩膜
   

    
    # 输出图像中的每个像素值将是输入的两个图像对应像素值进行位与操作的结果。但当提供了第三个参数 mask存在时,该掩模图像会决定哪些位置上的像素进行实际的位与计算。掩模图像通常是一个单通道图像,其中非零(例如白色或高值)像素表示在位与操作中要保留的位置。
    # 注意 参数一image_np和参数二image_np  的每一位像素进行按位与操作 由于是同一张图片  因此相同像素按位与后还是当前像素
    #200和200按位与后还是200:
    #   11001000
    # & 11001000
    # --------------
    # = 11001000 (二进制)  
    color_image_np = cv2.bitwise_and(image_np, image_np, mask=mask_image_np)  # 获得颜色识别后的图像
    cv2.imshow("origin_image_np", image_np)
    cv2.imshow("mask_image_np", mask_image_np)
    cv2.imshow("color_image_np", color_image_np)
    cv2.waitKey(0)

Logo

火山引擎开发者社区是火山引擎打造的AI技术生态平台,聚焦Agent与大模型开发,提供豆包系列模型(图像/视频/视觉)、智能分析与会话工具,并配套评测集、动手实验室及行业案例库。社区通过技术沙龙、挑战赛等活动促进开发者成长,新用户可领50万Tokens权益,助力构建智能应用。

更多推荐