您的位置:首页 > 其它

基于颜色特征的图像识别

2017-10-13 16:40 351 查看
要做一个背景黑色,物体形态可变(比如项链,两次放置的形状肯定不一样)的图像识别。很直接的想法就是,提取图片中的主要颜色,计算有多少像素在这个颜色范围内,把像素个数作为识别的特征。

从网上找到了一段代码:

import colorsys

def get_dominant_color(image):

image = image.convert('RGBA')

#生成缩略图,减少计算量
image.thumbnail((200, 200))

max_score = 0
dominant_color = 0

for count, (r, g, b, a) in image.getcolors(image.size[0] * image.size[1]):
# 跳过纯黑色
if a == 0:
continue

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

# Calculate the score, preferring highly saturated colors.
# Add 0.1 to the saturation so we don't completely ignore grayscale
# colors by multiplying the count by zero, but still give them a low
# weight.
score = (saturation + 0.1) * count

if score > max_score:
max_score = score
dominant_color = (r, g, b)

return dominant_color
用的是python的PIL模块。当时不明白为什么要用HSV模型里的S分量计算得分,H才是表征色调的啊。换用第二种方式:直方图比对。用opencv的实现如下:

image = cv2.imread("image.jpg",cv2.IMREAD_COLOR)
image = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
hist = cv2.calcHist([image], [0,1], None, [180,256], [0, 180,0, 256])
comp = cv2.compareHist(hist1, hist2, cv2.HISTCMP_BHATTACHARYYA)
其中,cv2.calcHist是计算图像的直方图,这里选择计算H和S分量的二维直方图,所以第二个参数是[0,1];第三个参数是mask,掩模;第四个参数是直方图统计的份数,在H分量上统计180份,S分量上统计256份,如果要计算一定像素值间隔内的像素数,例如,S分量上0到31之间,32到63,...,224到255的像素数,则可将S分量的参数设为8;第五个参数是统计范围。cv2.compareHist即直方图比较,第三个参数是比较的方式,采用这种方式比较出来的结果在0~1之间,越小表明越匹配。

结果特别不理想,不管是不是同一物品匹配结果随机分布在0.2-0.5之间。

于是回过头去琢磨第一种方法,发现是自己受到直觉误导,主色调,并不是指颜色最多的,而是指最“醒目”的,醒目的话当然要用S分量来判断啦。

补充一下为什么要用HSV颜色模型而不是RGB。RGB空间的三个分量随着光照改变而改变,且两个相近的颜色其R、G、B值可能相差很大,同时RGB空间对目标的颜色描述相对复杂,各个分量之间冗余信息多。而HSV空间能够独立感知各颜色分量的变化,较好得反映人对色彩的感知和鉴别能力,同时,H和S分量可以减少光照变化的影响。

另,opencv中的HSV空间取值范围: H 0~180,S 0~255,V 0~255;

Android中的HSV空间取值范围: H 0~360,S 0~1,V 0~1;

Python,PIL中的HSV空间取值范围: H 0~1,S 0~1,V 0~1;
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: