OpenCV实战:图像颜色识别与提取、掩膜制作

前言

        在计算机视觉和图像处理领域,颜色识别是一项基础而重要的技术。无论是交通标志识别、工业分拣还是美颜滤镜开发,都离不开对特定颜色的处理。本文将带你全面掌握使用OpenCV进行颜色识别的关键技术,包含完整的代码实现和原理讲解。

一、颜色空间基础

1.1 RGB颜色空间

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

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

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

RGB(红绿蓝)是最常见的颜色模型,采用加色法原理:

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

1.2 颜色加法

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

import cv2
import numpy as np

x = np.uint([80])
y = np.uint([200])
print(cv2.add(x,y)) #[[255]]

print(x+y) #[[24]]
运算类型计算过程预期输出
cv2.add(x,y)80+200=280→饱和截断到255[[255]]
x + y80+200=280→模256得24[[24]]
import cv2
import numpy as np
# 导入两张图片
img1 = cv2.imread("./src/pig.png")
img2 = cv2.imread("./src/lawn.png")
img3 = img1 + img2
cv2.imshow("img3windows",img3)
cv2.waitKey(0)
# 分别使用opencv(顶点255)、numpy(256取模)相加
print(cv2.add(img1,img2)
print(img1+img2)

注意:OpenCV中图像以BGR顺序存储,与常规RGB顺序不同,这也是上面红色的像素值是(0,0,255)而不是(255,0,0)的原因。

颜色加权加法

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

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("./lawn.png")
# 2 图像混合
image3 = cv2.addWeighted(image1,0.7,image2,0.3,0)
cv2.imshow("image3",image3)
cv2.waitKey(0)

1.2 HSV颜色空间

HSV(色调Hue:表示颜色的种类 如红色、绿色、蓝色等 、饱和度Saturation:表示颜色的纯度或强度 如红色越纯,饱和度就越高 、明度Value:表示颜色的明暗程度,如黑色比白色亮度低 )更接近人类对颜色的感知:

分量范围描述
H0-180色调(OpenCV中为0-180)
S0-255饱和度
V0-255

明度

二、颜色识别关键技术

2.1 创建颜色掩膜

def color_mask(image, lower, upper):
    """创建颜色掩膜"""
    hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
    mask = cv2.inRange(hsv, lower, upper)
    return mask

2.2 常用颜色HSV范围

三、完整颜色识别流程

3.1 基础实现

def detect_color(image, color='red'):
    """检测特定颜色区域"""
    # 颜色范围定义
    color_ranges = {
        'red': ([0,43,46], [10,255,255]),
        'green': ([35,43,46], [77,255,255]),
        'blue': ([100,43,46], [124,255,255])
    }
    
    lower, upper = color_ranges.get(color, ([0,0,0], [179,255,255]))
    lower = np.array(lower)
    upper = np.array(upper)
    
    # 转换HSV并创建掩膜
    hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
    mask = cv2.inRange(hsv, lower, upper)
    
    # 应用掩膜
    result = cv2.bitwise_and(image, image, mask=mask)
    
    return mask, result

3.2 进阶优化

形态学处理:消除噪点

kernel = np.ones((5,5), np.uint8)
mask = cv2.morphologyEx(mask, cv2.MORPH_OPEN, kernel)
mask = cv2.morphologyEx(mask, cv2.MORPH_CLOSE, kernel)

轮廓检测:标记颜色区域

contours, _ = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
for cnt in contours:
    if cv2.contourArea(cnt) > 500:  # 过滤小区域
        x,y,w,h = cv2.boundingRect(cnt)
        cv2.rectangle(image, (x,y), (x+w,y+h), (0,255,0), 2)

四、实战案例:交通灯识别

def traffic_light_detection(image):
    # 检测红色
    red_mask, _ = detect_color(image, 'red')
    # 检测绿色
    green_mask, _ = detect_color(image, 'green')
    
    # 判断哪个颜色更显著
    red_pixels = cv2.countNonZero(red_mask)
    green_pixels = cv2.countNonZero(green_mask)
    
    if red_pixels > green_pixels and red_pixels > 1000:
        return "红灯"
    elif green_pixels > red_pixels and green_pixels > 1000:
        return "绿灯"
    else:
        return "无信号"

五、常见问题解答

Q1:为什么颜色识别不准确?
A:可能原因:

  1. 光照条件变化 - 尝试自适应阈值或调整V通道范围

  2. 反光/阴影 - 使用形态学处理消除噪点

  3. HSV范围不合适 - 使用动态调整工具确定准确范围

Q2:如何提高识别速度?
A:

  1. 缩小处理图像尺寸

  2. 限定ROI区域

  3. 使用GPU加速(cv2.UMat)

结语

        掌握颜色识别技术是计算机视觉开发的重要基础。本文从原理到实践详细讲解了OpenCV颜色处理的全流程,建议读者动手实践各个示例,并根据实际需求进行调整优化。欢迎在评论区交流遇到的问题和心得!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值