使用Python,OpenCV确定对象的颜色

1. 如何利用Python、OpenCV计算轮廓的中心
2. Python,OpenCV应用轮廓逼近算法,检测对象的形状,如三角形,正方形,矩形,五边形,圆。

这一节学习应用 L * a * b * 颜色空间确定对象的颜色,与其颜色的通道计算最小的欧几里得距离,得到其颜色最接近预定义的颜色。

这个方法有其缺陷,会把颜色饱和度不够的(非红、绿、蓝)的颜色也标记为红或绿或蓝。(取决于预定义的颜色空间的准确度)。

检测颜色过程:

  1. 预定义颜色空间(颜色:BRG的值)
  2. 循环遍历颜色并将其转换为 L * a * b 空间的值
  3. 寻找轮廓,为轮廓构建一个蒙版,计算蒙版区域的平均 L * a * b 值
  4. 遍历已转换后的 L * a * b 空间list,分别与蒙版计算欧几里得距离,得到最小的距离值,以及其对应的颜色。则认为该颜色就是最接近的颜色——轮廓的颜色
# 用来标记带有颜色文本标签的图像区域
# 创建一个Python类,该类可用于用关联的颜色标记图像中的形状。

# 导入必要的包
from scipy.spatial import distance as dist
from collections import OrderedDict
import numpy as np
import cv2


class ColorLabeler:
    def __init__(self):
        # 初始化颜色字典 包括颜色名称和RGB元组值
        colors = OrderedDict({
            "red": (255, 0, 0),
            "green": (0, 255, 0),
            "blue": (0, 0, 255)})

        # 为L*a*b*图像分配内存 并且初始化颜色名称list
        self.lab = np.zeros((len(colors), 1, 3), dtype="uint8")
        self.colorNames = []

        # 循环遍历颜色字典
        for (i, (name, rgb)) in enumerate(colors.items()):
            # 更新L*a*b数组 及 颜色list
            self.lab[i] = rgb
            self.colorNames.append(name)

        # 转换 RGB颜色空间 为 L*a*b* 数组
        self.lab = cv2.cvtColor(self.lab, cv2.COLOR_RGB2LAB)

    # image:待检测的图像, c:轮廓
    def label(self, image, c):
        # 为轮廓构建一个蒙版,计算蒙版区域的 L*a*b的平均值
        mask = np.zeros(image.shape[:2], dtype="uint8")
        cv2.drawContours(mask, [c], -1, 255, -1)
        mask = cv2.erode(mask, None, iterations=2)
        mean = cv2.mean(image, mask=mask)[:3]

        # 初始化到目前为止找到的最小距离
        minDist = (np.inf, None)
        # 遍历L*a*b 数组颜色
        for (i, row) in enumerate(self.lab):
            # 计算每个已知颜色与平均颜色之间的欧几里得距离
            d = dist.euclidean(row[0], mean)

            # 如果距离比当前距离小,更新保留的距离变量值
            if d < minDist[0]:
                minDist = (d, i)

        # 返回最小欧几里得距离值的颜色
        return self.colorNames[minDist[1]]

在这里插入图片描述

1. 实现

  1. 加载图像、缩放、高斯平滑高频噪音、灰度图、BGR空间转 L * a * b空间, 阈值化(背景黑色,前景轮廓白色)、寻找轮廓
  2. 遍历轮廓,寻找轮廓中心,检测颜色
  3. 从中心位置,绘制颜色标签文本

2. 优化

颜色是可以识别,但是有些瑕疵,颜色不饱满的检测有误,橘色的被检测成红色,黄色的检测呈绿色;优化办法用 rangeDetector或者cv2.inRange()

(1)预先定义要检测的颜色的上下限范围(可以是Lab,HSV等颜色空间);
(2)运用cv2.inRange得到匹配颜色上下限范围的蒙版图;
(3)运用cv2.bitwise_and获得按位与结果图;

在这里插入图片描述

# python detect_color.py --image pokens.png

# 导入必要的包
import numpy as np
import argparse
import cv2

# 构建命令行参数
ap = argparse.ArgumentParser()
ap.add_argument("-i", "--image", help="path to the image")
args = vars(ap.parse_args())
# 加载图片
image = cv2.imread(args["image"])

# 定义颜色边界list 分别为红、蓝、黄、灰
# numpy以 BGR颜色空间以下限:[17, 15, 100],上限: [50, 56, 200]表示 红色
boundaries = [
    ([17, 15, 100], [50, 56, 200]),
    ([86, 31, 4], [220, 88, 50]),
    ([25, 146, 190], [62, 174, 250]),
    ([103, 86, 65], [145, 133, 128])
]

# 现在我们有了边界列表,我们可以使用cv2.inRange 功能执行实际的颜色检测。
# 遍历边界列表
for (lower, upper) in boundaries:
    # 从边界列表构建 Numpy数组 由于这些像素值在[0,256]范围内,因此我们可以使用无符号8位整数数据类型。
    lower = np.array(lower, dtype="uint8")
    upper = np.array(upper, dtype="uint8")

    # 找到固定边界中范围所匹配的颜色,并应用mask
    mask = cv2.inRange(image, lower, upper)
    output = cv2.bitwise_and(image, image, mask=mask)

    # 展示图像
    cv2.imshow("images", np.hstack([image, output]))
    cv2.waitKey(0)

参考:
https://www.pyimagesearch.com/2014/08/04/opencv-python-color-detection/

https://www.pyimagesearch.com/2016/02/15/determining-object-color-with-opencv/

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序媛一枚~

您的鼓励是我创作的最大动力。

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值