对于一张非纯色的图片,如果想要识别其颜色,可能没法直接识别。本文提供了一种利用颜色直方图来识别主要颜色的方法。
本文采用的方法适用于对象主体颜色占总区域面积比例较大的情况,不适合哪些颜色较为分散、杂乱的情况。
基本步骤步骤如下:
图像crop, 降低周围背景的影响;统计H、S、V三个分量的直方图;分别取H、S、V的主要成分,判断落在哪种颜色区间内;本文主要参考的颜色区间见表:
黑灰白红橙黄绿青蓝紫hmin000015611263578100125hmax180180180101802534;7799124155smin00043434343434343smax2554330255255255255255255255vmin04622146464646464646vmax46220255255255255255255255255颜色识别分类器代码如下:
import cv2
import numpy as np
class ColorClassify(object):
def __init__(self, debug=True):
self.debug = debug
self.hsv_color = {
"Black": [(0, 180), (0, 255), (0, 46)],
"Gray": [(0, 180), (0, 43), (46, 150)],
"White": [(0, 180), (0, 30), (151, 255)],
"Red": [[(0, 10), (156, 180)], (43, 255), (46, 255)],
"Orange": [(11, 25), (43, 255), (46, 255)],
"Yellow": [(26, 34), (43, 255), (46, 255)],
"Green": [(35, 77), (43, 255), (46, 255)],
"CyanBlue": [(78, 99), (43, 255), (46, 255)],
"Blue": [(100, 124), (43, 255), (46, 255)],
"Purple": [(125, 155), (43, 255), (46, 255)],
}
def get_hsv_hist(self, img_hsv):
h, s, v = img_hsv[:, :, 0], img_hsv[:, :, 1], img_hsv[:, :, 2]
h_bins = [0, 11, 26, 35, 78, 100, 125, 156, 180]
h_hist = np.histogram(h, h_bins)
s_bins = [0, 30, 43, 255]
s_hist = np.histogram(s, s_bins)
v_bins = [0, 46, 151, 255]
v_hist = np.histogram(v, v_bins)
return [h_hist, s_hist, v_hist]
def get_hsv_info(self, h_hist, s_hist, v_hist):
infos = {
"h": {
"hist": h_hist,
"argsort": None,
"sort_normal": None,
"arg_values": [],
},
"s": {
"hist": s_hist,
"argsort": None,
"sort_normal": None,
"arg_values": [],
},
"v": {
"hist": v_hist,
"argsort": None,
"sort_normal": None,
"arg_values": [],
}
}
for k in infos:
hist = infos[k]['hist']
argsort = np.argsort(hist[0])[::-1][:2]
infos[k]['argsort'] = argsort
infos[k]['sort_normal'] = hist[0][argsort] / (sum(hist[0]) * 3)
for idx in argsort:
value_mean = round(np.mean([hist[1][idx], hist[1][idx + 1]]))
infos[k]['arg_values'].append(value_mean)
return infos
def get_hsv_main_info(self, h_hist, s_hist, v_hist):
h_main_idx = np.argmax(h_hist[0])
h_main = [h_hist[1][h_main_idx], h_hist[1][h_main_idx + 1]]
s_weights = np.array([1, 1, 1])
s_array = s_hist[0] * s_weights
s_main_idx = np.argmax(s_array)
s_main = [s_hist[1][s_main_idx], s_hist[1][s_main_idx + 1]]
v_weights = np.array([1, 1, 1])
v_array = v_hist[0] * v_weights
v_main_idx = np.argmax(v_array)
v_main = [v_hist[1][v_main_idx], v_hist[1][v_main_idx + 1]]
if self.debug:
print("h_hist: {}ns_hist: {}nv_hist: {}".format(h_hist, s_hist, v_hist))
print("h_main: {}, s_main: {}, v_main: {}".format(h_main, s_main, v_main))
return np.mean(h_main), np.mean(s_main), np.mean(v_main)
def hsv2color(self, infos):
h_info = infos['h']
s_info = infos['s']
v_info = infos['v']
result = {}
for snh, avh in zip(h_info['sort_normal'], h_info['arg_values']):
for sns, avs in zip(s_info['sort_normal'], s_info['arg_values']):
for snv, avv in zip(v_info['sort_normal'], v_info['arg_values']):
cls = self.hsv2color_one(avh, avs, avv)
if cls is None:
print(avh, avs, avv)
continue
score = snh + sns + snv
if cls in result.keys():
result[cls] = max(score, result[cls])
else:
result[cls] = score
print(result)
return sorted(result.items(), key=lambda kv: (kv[1], kv[0]))[::-1]
def hsv2color_one(self, h_mean, s_mean, v_mean):
for cls, value in self.hsv_color.items():
if isinstance(value[0], list):
h_flag = value[0][0][0] <= h_mean <= value[0][0][1] or value[0][1][0] <= h_mean <= value[0][1][1]
else:
h_flag = value[0][0] <= h_mean <= value[0][1]
s_flag = value[1][0] <= s_mean <= value[1][1]
v_flag = value[2][0] <= v_mean <= value[2][1]
if h_flag and s_flag and v_flag:
return cls
return None
def classify(self, img):
img_hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
h_hist, s_hist, v_hist = self.get_hsv_hist(img_hsv)
infos = self.get_hsv_info(h_hist, s_hist, v_hist)
return self.hsv2color(infos)
用法也很简单,先实例化一个分类器,然后调用classify传入图片即可得到颜色类别:
classifier = ColorClassify(debug=True)
img = cv2.imread(img_path)
result = classifier.classify(img)
cls, score = result[0]
参考:
HSV颜色模型_百度百科
HSV基本颜色分量范围 - 百度文库
色域值各个标准对照表 - 百度文库
相关知识
利用OpenCV根据图片识别环境的亮度
深入浅出:利用OpenCV实现手写数字识别之旅
基于OpenCV的鲜花的图像分类系统详细设计与具体代码实现
基于深度学习YOLOv8\YOLOv5的花卉识别鲜花识别检测分类系统设计
基于机器视觉的昆虫种类及计数检测研究
基于机器视觉的害虫种类及计数检测研究
python 手写字识别
基于Python机器视觉的远程害虫种类识别和数量检测系统 报告+项目源码及数据
opencv深度学习昆虫识别系统图像识别 python
基于深度学习的yolov7植物病虫害识别及防治系统
网址: 基于OpenCV进行图片主要颜色识别 https://m.huajiangbk.com/newsview1094011.html
上一篇: python+opencv实现文 |
下一篇: openMV |