1 颜色识别

图片颜色识别主要通过掩膜对原图像进行与运算来找到要识别的颜色。

1.1 RGB颜色空间

在图像处理中,最常见的就是RGB颜色空间。RGB颜色空间是我们接触最多的颜色空间,是一种用于表示和显示彩色图像的一种颜色模型。RGB代表红色(Red)、绿色(Green)和蓝色(Blue),这三种颜色通过不同强度的光的组合来创建其他颜色。

2 HSV颜色空间

HSV颜色空间(HSV颜色模型,也成为HSL)是一种与RGB颜色模型并列的颜色空间表示法。

HSV颜色空间使用色调或色相(Hue)、饱和度(Saturation)和亮度或明度(Value)三个参数来表示颜色,色调 H 表示颜色的种类,如红色、绿色、蓝色等;饱和度 S 表示颜色的纯度或强度,如红色越纯,饱和度就越高;亮度 V 表示颜色的明暗程度,如黑色比白色亮度低。

由于HSV的颜色是连续的,比RGB更适合进行颜色范围划分,常见的颜色经过试验得到的范围如下:

代码运行步骤:图片输入→HSV空间转换→制作掩膜→与运算→图片输出

掩膜(Mask)是一种在图像处理中常见的操作(类似于PS中的蒙版),它可以选择性地遮挡图像的某个部分,从而实现特定任务的目标。掩膜通常是一个二值化图像,并且与原图相同大小,其中目标区域被设置为255(白色),而其他区域设置为0(黑色),目标区域可以根据HSV的参数修改,通过掩膜可以使用白色区域操作原图中的同位置像素。

与运算在图像处理中,与运算被用来对像素进行操作,可以将两个图像中的所有对应像素值进行与运算操作。

原图名称:demo.jpg

import cv2
import numpy as np

if __name__ == '__main__':
    # 1.图片输入
    path = 'demo.jpg'  # 图像文件路径
    image_np = cv2.imread(path)  # 读取图像为NumPy数组(BGR格式)

    # 2.HSV空间转换
    hsv_image_np = cv2.cvtColor(image_np, cv2.COLOR_BGR2HSV)  # BGR转HSV
    # print(hsv_image_np.shap) # 打印HSV图像的维度(高度, 宽度, 通道数)
    # print(hsv_image_np)           # (注释)打印HSV像素值数组

    # 3. 制作掩膜
    # 定义红色范围1
    red_low = np.array([0, 43, 46])  # 红色下限(Hmin, Smin, Vmin)
    red_high = np.array([10, 255, 255])  # 红色上限(Hmax, Smax, Vmax)

    mask1 = cv2.inRange(  # 创建二值掩膜
        hsv_image_np,  # 基于哪个图像, 输入HSV图像
        red_low,  # 颜色下限
        red_high  # 颜色上限
    )
    # print(mask1.shape)
    # print(mask1)

    # 定义红色范围2
    red_low = np.array([156, 43, 46])  # 红色第二范围下限(深红色)
    red_high = np.array([180, 255, 255])  # 第二范围上限
    # 制作掩膜
    mask2 = cv2.inRange(  # 创建第二个掩膜
        hsv_image_np,
        red_low,
        red_high
    )
    # 合并掩膜
    mask_image_np = cv2.bitwise_or(mask1, mask2)  # 创建第二个掩膜
    # print(mask_image_np.shape)
    # print(mask_image_np)

    # 原图和掩膜进行 与操作
    color_image_np = cv2.bitwise_and(  # 按位与操作
        image_np,  # 原始图像
        image_np,  # 再次使用原始图像
        mask=mask_image_np  # 应用合并后的掩膜
    )  # 掩膜
    # print(color_image_np.shape) # 输出结果图像维度
    # print(color_image_np)# 输出结果像素数组

    # 图片输出
    cv2.imshow('mask1:', mask1)  # 显示第一个红色掩膜
    cv2.imshow('mask2:', mask2)  # 显示第二个红色掩膜
    cv2.imshow('mask_image_np', mask_image_np)  # 显示合并掩膜
    cv2.imshow('color_image_np', color_image_np)  # 显示提取的红色区域
    cv2.waitKey(0)  # 等待按键(0表示无限等待)

运行后结果:

mask1.png 

mask2.png

合并后的掩膜:

color_red_np.png:

3 颜色替换

在图像中识别某一种(多种)颜色,那么就可以对这些颜色进行单独操作,比如替换成其他的颜色,原理就是在得到掩膜后,对掩膜中白色区域的原图进行一个像素值的修改。

代码运行步骤:图片输入→HSV空间转换→制作掩膜→开运算→颜色替换→图片输出

在形态学变换章节中学习了腐蚀和膨胀的工作原理,开运算就是先对图像进行腐蚀操作,再进行膨胀操作,开运算的效果是可以去除二值化图中的小噪点,并分离相连的物体。

由于掩膜与原图的大小相同,并且像素的一一对应的,可以得到掩膜中的白色区域坐标,把掩膜中所有白色区域的坐标带入到原图中,就可以得到原图中所有红色区域的坐标。拿到原图红色的坐标后,可以进行任何红色像素值的操作,例如修改颜色。

图片名称:image.jpg

import cv2
import numpy as np

if __name__ == '__main__':
    # 1.图片输入
    path = 'image.jpg'
    image_np = cv2.imread(path)  # 读取图片到NumPy数组(BGR格式)

    # 2.HSV空间转换
    hsv_image_np = cv2.cvtColor(image_np, cv2.COLOR_BGR2HSV)  # 将图片从BGR颜色空间转换为HSV颜色空间
    # print(hsv_image_np) # 打印HSV图像的维度(高度, 宽度, 通道数)

    # 3. 制作掩膜
    # 定义红色范围1(HSV格式:0°-10°)
    red_low = np.array([0, 43, 46])
    red_high = np.array([10, 255, 255])

    # 制作掩膜1
    mask1 = cv2.inRange(
        hsv_image_np,  # 基于哪个图像就输入哪个图像(HSV图像)
        red_low,  # 颜色下限
        red_high  # 颜色上限
    )  # 创建二值掩膜:在红色范围内的像素为255(白色),其余为0(黑色)
    # print(mask1.shape)  # 打印掩膜维度(单通道)
    # print(mask1)        # 打印掩膜数据(二维数组)

    # 定义红色范围2(HSV格式:156°-180°)
    red_low = np.array([156, 43, 46])
    red_high = np.array([180, 255, 255])
    # 制作掩膜
    mask2 = cv2.inRange(
        hsv_image_np,
        red_low,  # 颜色下限
        red_high  # 颜色上限
    )

    # 合并掩膜
    mask_image_np = cv2.bitwise_or(mask1, mask2)  # 将两个掩膜合并(逻辑OR操作)
    # print(mask_image_np.shape)  # 打印合并后掩膜维度
    # print(mask_image_np)  # 打印合并掩膜数据

    # 4.图片矫正. 开运算(去噪)
    # 创建一个5x5矩形核
    kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))

    # 执行开运算
    open_image_np = cv2.morphologyEx(
        src=mask_image_np,  # 输入掩膜
        op=cv2.MORPH_OPEN,  # 开运算类型(先腐蚀后膨胀)
        kernel=kernel  # 使用的结构核
    )  # 去除小噪点,平滑物体边界

    # 颜色替换
    for i in range(open_image_np.shape[0]):  # 遍历高度方向
        for j in range(open_image_np.shape[1]):  # 遍历宽度方向
            # 如果当前遍历的像素点是掩膜的白色
            if open_image_np[i, j] == 255:  # 当开运算掩膜中为白色区域时
                # 给原图进行颜色替换为蓝色
                image_np[i, j] = (255, 0, 0)  # 将原图对应像素改为蓝色(BGR格式)

    # 6. 图片输出
    cv2.imshow('mask_image_np', mask_image_np)  # 显示原始掩膜
    cv2.imshow('open_image_np', open_image_np)  # 显示开运算后的掩膜
    cv2.imshow('image_np', image_np)  # 显示处理后的原图(红色变蓝)
    cv2.waitKey(0)  # 等待任意按键关闭窗口
    cv2.imwrite('blue.png', image_np)

原始掩膜:mask_image_np.png

开运算后的掩膜:open_image_np.png

最终结果:blue.png

更多推荐