学习这件事不在乎有没有人教你,最重要的是在于你自己有没有觉悟和恒心。————法布尔

编程

Python 识别图片主题颜色

  • 2018-11-02 11:19
简介 :有个需求: 需要程序去判断图片的主题颜色 , 问了下朋友说python有个库可以实现,做下记录.

前言 : 程序识别图片颜色影响因素比较多,比如:曝光度,图片质量,等等一系列不可更改原因,导致程序识别真正的实物颜色误差比较大 , python新手看手册写的,代码low , 见谅.

程序思路 : 通过裁剪图片中央位置作为主题识别图 , 调用colors库返回跟数据库RGB颜色误差范围内最小的RGB值作为该图片的主题颜色.

直接放代码:

  • #-*- coding: UTF-8 -*-
  • from PIL import Image
  • import MySQLdb
  • import sys , os , time , colorsys , json , operator
  • import config as cf
  • class ImageColorIdentify:
  • filename = None # 需要识别的图片地址
  • Wimg = 0 # 自定义裁剪宽默认
  • Himg = 0 # 自定义裁剪高默认
  • rgb_float_int = 300 # 定义颜色误差浮动范围 < 300 , 该值越大查找次数越多
  • is_cutting = True # 是否裁剪指定区域后再识别
  • SavefileName = None # 保存新文件的名字,不带后缀
  • SavefilePath = None # 保存新文件的全地址
  • def __init__( self , filename ):
  • if not os.path.exists(filename): # 先判断文件是否存在IO忽略
  • print('文件不存在~~')
  • return None
  • else:
  • self.filename = filename;
  • def CuttingImageCenter( self , cuttingList = [] ):
  • try:
  • if self.filename is not None:
  • img_info = Image.open( self.filename );
  • except IOError:
  • print("Error: 没有找到文件或读取文件失败")
  • return False
  • else:
  • self.SavefileName = str( int( time.time() ) ) # 转str类型下面有拼接
  • imgsize = img_info.size;
  • width = imgsize[0]
  • heigth = imgsize[1]
  • if len( cuttingList ) > 0:
  • if cuttingList[0] < 0 or cuttingList[1] < 0:
  • print('输入的要裁剪的宽高不能小于零')
  • return False
  • else:
  • self.Wimg = cuttingList[0]
  • self.Himg = cuttingList[1]
  • else:
  • # 默认按照比例 4:3 来计算
  • self.Wimg = width * 3 / 4
  • self.Himg = heigth * 3 / 4
  • if width and self.Wimg:
  • _left = abs(width-self.Wimg)/2
  • if heigth and self.Himg:
  • _top = abs(heigth-self.Himg)/2
  • crop_info = ( _left , _top , _left+self.Wimg , _top+self.Himg )
  • new_img = img_info.crop( crop_info )
  • if img_info.format is 'JPEG':
  • fileExt = 'jpg'
  • else:
  • fileExt = img_info.format.lower()
  • fileSave = self.SavefileName + '.' + fileExt
  • new_img.save(fileSave)
  • self.SavefilePath = fileSave
  • def getBseriesPicColorList( self , bseries_id = 0):
  • _config = cf.config()
  • if len(_config) <= 0 or bseries_id <= 0:
  • return False
  • # 打开数据库连接
  • db = MySQLdb.connect(_config['host'], _config['user'], _config['pwd'], _config['dbname'], charset=_config['charset'] )
  • try:
  • # 使用cursor()方法获取操作游标
  • cursor = db.cursor()
  • except InternalError:
  • print("Error 游标创建有误!")
  • return False
  • # 使用execute方法执行SQL语句
  • getListSQL = "SELECT %s FROM `%s` WHERE id >= %d LIMIT 1" % ( 'sys_count_color' , 'prd_categorysubclass' , bseries_id )
  • try:
  • cursor.execute(getListSQL)
  • except ProgrammingError as err:
  • print("SQL执行错误:",err)
  • return False
  • # 使用 fetchone() 方法获取一条数据
  • data = cursor.fetchone()
  • if len(data) <= 0:
  • return False
  • new_data = list( data )[0].strip('|').split('|')
  • color_data = []
  • for i , j in enumerate(new_data):
  • param_color = j.split(':')[2]
  • color_data.append(param_color)
  • del data , new_data
  • # 关闭数据库连接
  • db.close()
  • return color_data
  • def ExtractImagesColor( self , bseries_id , option = [] ):
  • filePath = None
  • if self.is_cutting:
  • self.CuttingImageCenter( option ) # 如果裁剪, 调用裁剪图像
  • if self.SavefilePath is not None:
  • filePath = self.SavefilePath
  • else:
  • filePath = self.filename
  • else:
  • filePath = self.filename
  • try:
  • image = Image.open(filePath).convert('RGBA')
  • except IOError as err:
  • print( "识别颜色图片打开有误!" , err )
  • return False
  • #生成缩略图
  • image.thumbnail((400, 300))
  • # 车系颜色代码
  • bseries_color = self.getBseriesPicColorList( bseries_id )
  • count_color_dict = {} # 定义一个临时字典, 主要是存放识别的颜色信息
  • qita_dict = {}
  • max_score = 0
  • min_count = 0
  • for count, (r, g, b, a) in image.getcolors(image.size[0] * image.size[1]):
  • 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
  • # 忽略纯黑色
  • # if a == 0:
  • # continue
  • qita_dict[(r,g,b)] = count
  • score = (saturation+0.1)*count
  • if score > max_score:
  • max_score = score
  • # 处理车系的颜色代码 跟 图片颜色进行对比
  • if bseries_color:
  • bseries_color = ['#C3694B','#000000','#544540']; # 測試數據
  • for bi , bj in enumerate( bseries_color ):
  • br = int( bj[1:3] , 16 )
  • bg = int( bj[3:5] , 16 )
  • bb = int( bj[5:7] , 16 )
  • if r == br and bg == g and bb == b: # 是否有命中的颜色
  • count_color_dict[bj] = (r,g,b)
  • break
  • elif abs(br-r) < self.rgb_float_int and abs(bg-g) < self.rgb_float_int and abs(bb-b) < self.rgb_float_int:
  • if count_color_dict.has_key(bj):
  • if min_count > abs(br-r):
  • count_color_dict[bj] = (r,g,b)
  • min_count = abs(br-r)
  • else:
  • min_count = abs(br-r)
  • count_color_dict[bj] = (r,g,b)
  • break
  • else:
  • count_color_dict[bj] = ()
  • continue
  • qita_dict = sorted(qita_dict.iteritems(), key=operator.itemgetter(1),reverse=True)
  • count_color_dict['program'] = qita_dict[0][0]
  • del qita_dict
  • return count_color_dict
  • def __del__( self ):
  • if os.path.exists(self.SavefilePath): #删除临时文件
  • os.remove(self.SavefilePath)
  • else:
  • pass
  • ImageObj = ImageColorIdentify('333.jpg'); # 图片原地址
  • a =ImageObj.ExtractImagesColor(3133);
  • print(a)
Top