Python3实现图片主色识别:PIL与OpenCV两种方案对比

顾星河
顾星河
发布时间:2026-10-13 | 3人浏览过
原创

本文介绍Python3中识别图片主要颜色的两种方案。方案一利用PIL库截取图像,通过RGB转HSV算法统计颜色并输出RGB值,适用于简单场景。方案二采用OpenCV库,通过定义HSV颜色字典,利用cv2.inRange()进行背景过滤、二值化及形态学腐蚀膨胀处理,最终通过统计白色区域面积确定物体颜色。OpenCV方案在处理复杂背景时效果更佳,代码包含完整的颜色过滤与轮廓面积计算逻辑。

Python3图片主色识别方案概述

本文主要介绍两种实现方案:

方案一:参考网络现有代码,其实用性相对有限。该方法使用PIL库截取图像,将RGB颜色空间转换为HSV空间进行判断,统计识别出的颜色,最终输出对应的RGB数值。

方案二:使用OpenCV库函数进行处理,实际测试效果较好。

具体步骤如下: 1、将图片颜色空间转换为HSV; 2、使用cv2.inRange()函数进行背景颜色过滤; 3、对过滤后的颜色区域进行二值化处理; 4、执行形态学腐蚀与膨胀操作,调用cv2.dilate(); 5、统计白色区域的面积。

方案一:基于PIL的RGB转HSV分析

方案一详细解析:

转载来源:www.jb51.net/article/62526.htm

基于项目实际需求,需要对识别出的车辆进行颜色标记,因此采用以下方案:

1、通过import PIL.ImageGrab as ImageGrab模块,将识别出的汽车矩形框区域裁剪出来。


img_color=image.crop((left,right,top,bottom))

2、对裁剪得到的图像进行颜色识别处理。

RGB与HSV之间的转换关系在网上资料较多,此处未深入探究具体转换原理,只要功能可用即可。

附上测试代码,已封装为函数方法:


import colorsys
import PIL.Image as Image
 
def get_dominant_color(image):
  max_score = 0.0001
  dominant_color = None
  for count,(r,g,b) in image.getcolors(image.size[0]*image.size[1]):
    # 转为HSV标准
    saturation = colorsys.rgb_to_hsv(r/255.0, g/255.0, b/255.0)[1]
    y = min(abs(r*2104+g*4130+b*802+4096+131072)>>13,235)
    y = (y-16.0)/(235-16)
 
    #忽略高亮色
    if y > 0.9:
      continue
    score = (saturation+0.1)*count
    if score > max_score:
      max_score = score
      dominant_color = (r,g,b)
  return dominant_color
 
 
if __name__ == '__main__':
  image = Image.open('test.jpg')
  image = image.convert('RGB')
  print(get_dominant_color(image))

测试图片展示:


运行结果展示:


可通过在线工具查询RGB数值对应的具体颜色名称。

在线查询工具地址:http://tools.jb51.net/static/colorpicker/index.html


方案二:基于OpenCV的HSV颜色过滤与轮廓分析

方案二:利用OpenCV计算机视觉库函数进行处理。

1、定义HSV颜色字典,参考网络上已有的HSV颜色分类标准。


相关代码如下:


import numpy as np
import collections
 
#定义字典存放颜色分量上下限
#例如:{颜色: [min分量, max分量]}
#{'red': [array([160, 43, 46]), array([179, 255, 255])]}
 
def getColorList():
  dict = collections.defaultdict(list)
 
  # 黑色
  lower_black = np.array([0, 0, 0])
  upper_black = np.array([180, 255, 46])
  color_list = []
  color_list.append(lower_black)
  color_list.append(upper_black)
  dict['black'] = color_list
 
  # #灰色
  # lower_gray = np.array([0, 0, 46])
  # upper_gray = np.array([180, 43, 220])
  # color_list = []
  # color_list.append(lower_gray)
  # color_list.append(upper_gray)
  # dict['gray']=color_list
 
  # 白色
  lower_white = np.array([0, 0, 221])
  upper_white = np.array([180, 30, 255])
  color_list = []
  color_list.append(lower_white)
  color_list.append(upper_white)
  dict['white'] = color_list
 
  #红色
  lower_red = np.array([156, 43, 46])
  upper_red = np.array([180, 255, 255])
  color_list = []
  color_list.append(lower_red)
  color_list.append(upper_red)
  dict['red']=color_list
 
  # 红色2
  lower_red = np.array([0, 43, 46])
  upper_red = np.array([10, 255, 255])
  color_list = []
  color_list.append(lower_red)
  color_list.append(upper_red)
  dict['red2'] = color_list
 
  #橙色
  lower_orange = np.array([11, 43, 46])
  upper_orange = np.array([25, 255, 255])
  color_list = []
  color_list.append(lower_orange)
  color_list.append(upper_orange)
  dict['orange'] = color_list
 
  #黄色
  lower_yellow = np.array([26, 43, 46])
  upper_yellow = np.array([34, 255, 255])
  color_list = []
  color_list.append(lower_yellow)
  color_list.append(upper_yellow)
  dict['yellow'] = color_list
 
  #绿色
  lower_green = np.array([35, 43, 46])
  upper_green = np.array([77, 255, 255])
  color_list = []
  color_list.append(lower_green)
  color_list.append(upper_green)
  dict['green'] = color_list
 
  #青色
  lower_cyan = np.array([78, 43, 46])
  upper_cyan = np.array([99, 255, 255])
  color_list = []
  color_list.append(lower_cyan)
  color_list.append(upper_cyan)
  dict['cyan'] = color_list
 
  #蓝色
  lower_blue = np.array([100, 43, 46])
  upper_blue = np.array([124, 255, 255])
  color_list = []
  color_list.append(lower_blue)
  color_list.append(upper_blue)
  dict['blue'] = color_list
 
  # 紫色
  lower_purple = np.array([125, 43, 46])
  upper_purple = np.array([155, 255, 255])
  color_list = []
  color_list.append(lower_purple)
  color_list.append(upper_purple)
  dict['purple'] = color_list
 
  return dict
 
 
if __name__ == '__main__':
  color_dict = getColorList()
  print(color_dict)
 
  num = len(color_dict)
  print('num=',num)
 
  for d in color_dict:
    print('key=',d)
    print('value=',color_dict[d][1])

2、执行颜色识别逻辑。


import cv2
import numpy as np
import colorList
 
filename='car04.jpg'
 
#处理图片
def get_color(frame):
  print('go in get_color')
  hsv = cv2.cvtColor(frame,cv2.COLOR_BGR2HSV)
  maxsum = -100
  color = None
  color_dict = colorList.getColorList()
  for d in color_dict:
    mask = cv2.inRange(hsv,color_dict[d][0],color_dict[d][1])
    cv2.imwrite(d+'.jpg',mask)
    binary = cv2.threshold(mask, 127, 255, cv2.THRESH_BINARY)[1]
    binary = cv2.dilate(binary,None,iterations=2)
    img, cnts, hiera = cv2.findContours(binary.copy(),cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
    sum = 0
    for c in cnts:
      sum+=cv2.contourArea(c)
    if sum > maxsum :
      maxsum = sum
      color = d
 
  return color
 
 
if __name__ == '__main__':
  frame = cv2.imread(filename)
  print(get_color(frame))

3、查看最终识别结果。

原始测试图像(取自网络):

1)、使用cv2.inRange()函数过滤背景后的图片效果如下:


2)、可见,使用白色分量过滤背景后,车辆轮廓清晰显现。因此,可以计算白色区域的面积,面积最大的区域即代表该物体的颜色。


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持本站。

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表