You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何高效检测目标物体颜色?YOLO裁剪后非深度学习快速方案

高效目标颜色检测方案(基于裁剪后的目标区域)

需求背景

已通过YOLO模型得到目标边界框并裁剪出目标区域,需要高效、准确的颜色检测/分类方案,要求速度极快,优先使用纯Python、OpenCV等非深度学习工具。此前尝试过两种方案均不理想:

  1. 训练YOLO检测10类颜色,但双模型运行速度无法满足实时需求;
  2. 将图像缩至1x1像素取色,但精度极差、结果偏差大。

解决方案

一、HSV空间直方图峰值法(极致速度+高鲁棒性)

RGB空间的颜色分布不适合直接统计,转HSV后,H通道(色调)直接对应人眼感知的颜色类别,统计H通道的直方图峰值即可快速得到主色调,再通过S(饱和度)和V(明度)过滤低饱和、过暗/过亮的干扰像素。

import cv2
import numpy as np

def get_dominant_color_hsv(cropped_img):
    # 转HSV颜色空间(OpenCV默认BGR格式)
    hsv = cv2.cvtColor(cropped_img, cv2.COLOR_BGR2HSV)
    
    # 过滤低饱和、过暗/过亮的像素(阈值可根据实际场景调整)
    mask = cv2.inRange(hsv, (0, 30, 30), (179, 255, 255))
    hsv_filtered = hsv[mask > 0]
    
    if len(hsv_filtered) == 0:
        # 无有效像素时取H通道均值
        h_mean = np.mean(hsv[:, :, 0])
        dominant_h = int(h_mean)
    else:
        # 统计H通道直方图,取峰值对应的H值
        hist = cv2.calcHist([hsv_filtered], [0], None, [180], [0, 180])
        dominant_h = np.argmax(hist)
    
    # 映射为你的10类颜色(根据需求调整区间)
    color_map = {
        (0, 10): "红色",
        (10, 25): "橙色",
        (25, 35): "黄色",
        (35, 77): "绿色",
        (77, 90): "青色",
        (90, 127): "蓝色",
        (127, 150): "紫色",
        (150, 160): "粉色",
        (160, 179): "红色",
        (0, 0): "黑色"  # 补充你需要的颜色类别
    }
    
    for (h_min, h_max), color_name in color_map.items():
        if h_min <= dominant_h <= h_max:
            return color_name, dominant_h
    return "未知", dominant_h

# 示例调用(cropped_img为YOLO裁剪后的BGR图像)
# cropped_img = cv2.imread("cropped_target.jpg")
# color_name, h_value = get_dominant_color_hsv(cropped_img)
# print(f"主颜色:{color_name},H值:{h_value}")

二、K-Means聚类法(更高精度)

如果目标区域颜色有轻微渐变或少量杂色,可使用K-Means对像素聚类,取占比最高的簇中心作为主色,速度远快于深度学习,适合对精度要求较高的实时场景。

import cv2
import numpy as np
from sklearn.cluster import KMeans

def get_dominant_color_kmeans(cropped_img, n_clusters=2):
    # 转RGB格式并扁平化像素数组
    rgb_img = cv2.cvtColor(cropped_img, cv2.COLOR_BGR2RGB)
    pixels = rgb_img.reshape(-1, 3)
    
    # 过滤低饱和像素(减少干扰)
    hsv = cv2.cvtColor(cropped_img, cv2.COLOR_BGR2HSV)
    s_mask = hsv[:, :, 1] > 30
    pixels_filtered = pixels[s_mask.flatten()]
    
    if len(pixels_filtered) < 10:
        # 有效像素过少时取全局均值
        mean_color = np.mean(pixels, axis=0).astype(int)
        dominant_color = tuple(mean_color)
    else:
        # K-Means聚类(n_init=10避免局部最优)
        kmeans = KMeans(n_clusters=n_clusters, n_init=10, random_state=42)
        kmeans.fit(pixels_filtered)
        # 取占比最高的簇中心
        counts = np.bincount(kmeans.labels_)
        dominant_color = kmeans.cluster_centers_[np.argmax(counts)].astype(int)
        dominant_color = tuple(dominant_color)
    
    # 映射为你的10类颜色(根据RGB阈值调整)
    r, g, b = dominant_color
    if r > 200 and g < 100 and b < 100:
        return "红色", dominant_color
    elif r > 200 and g > 150 and b < 100:
        return "橙色", dominant_color
    # 补充其他颜色判断逻辑...
    return "未知", dominant_color

# 示例调用
# cropped_img = cv2.imread("cropped_target.jpg")
# color_name, rgb_color = get_dominant_color_kmeans(cropped_img)
# print(f"主颜色:{color_name},RGB值:{rgb_color}")

三、优化你的1x1取色法(简单场景可用)

原方法直接缩至1x1会受边缘噪点、阴影影响,可通过模糊处理或取中心区域均值优化:

from PIL import Image, ImageFilter
import numpy as np

def get_dominant_color_optimized(pil_img):
    img = pil_img.copy().convert("RGB")
    
    # 方法1:先高斯模糊再缩小,过滤噪点
    img_blur = img.filter(ImageFilter.GaussianBlur(radius=2))
    img_blur = img_blur.resize((1, 1), resample=Image.Resampling.BILINEAR)
    dominant_color = img_blur.getpixel((0, 0))
    
    # 方法2:取中心1/3区域的均值,避免边缘干扰
    # w, h = img.size
    # center_w, center_h = w//3, h//3
    # center_region = img.crop((center_w, center_h, w-center_w, h-center_h))
    # pixels = list(center_region.getdata())
    # dominant_color = tuple(np.mean(pixels, axis=0).astype(int))
    
    # 颜色映射逻辑
    r, g, b = dominant_color
    if r > 180 and g < 80 and b < 80:
        return "红色", dominant_color
    # 补充其他颜色判断...
    return "未知", dominant_color

# 示例调用
# image = Image.open("cropped_target.jpg")
# color_name, rgb_color = get_dominant_color_optimized(image)
# print(f"主颜色:{color_name},RGB值:{rgb_color}")

选择建议

  • 极致速度优先:选HSV直方图峰值法,单帧处理耗时在毫秒级,完全满足实时要求;
  • 高精度优先:选K-Means聚类法,注意设置n_clusters=2或3控制计算量,结合HSV过滤可进一步提升效率;
  • 简单均匀场景:用优化后的1x1取色法,仅适合颜色无渐变、无杂色的目标。

内容的提问来源于stack exchange,提问作者angel_30

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 17:35:00