这次我们利用opencv为水果图片提取颜色特征,我的思路是:设置几种颜色区间,让opencv根据每种颜色区间画出对应颜色的部分,然后我们统计这些颜色的轮廓面积,计算出颜色占水果面积的比例。
构建颜色区间
opencv有多种表示颜色的方式,如:RGB,HSV等我采用的是HSV,网上找的区间图如下:
import numpy as np
import collections
#颜色名称和hsv区间构成一个字典
def getColorDict():
dict=collections.defaultdict(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 #关联一个列表
# 黄色
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_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_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
return dict
把常规的几种颜色写进去,然后开始读取图片并记录颜色的面积:
import os
import cv2
#返回图片的颜色
def getColor(filename):
img=cv2.imread(filename)
savefold=filename.split('/')[1].split('.')[0]
if not os.path.exists(os.getcwd()+'/image/'+savefold): #不存在就创建文件夹
os.mkdir(os.getcwd()+'/image/'+savefold)
#转hsv
hsv=cv2.cvtColor(img,cv2.COLOR_BGR2HSV)
color_area={} #保存颜色和区域面积
color_dict=getColorDict() #获取颜色和hsv对应的字典
#print(color_dict)
for each in color_dict:
mask=cv2.inRange(hsv,color_dict[each][0],color_dict[each][1])
#cv2.imshow("mask",mask)
cv2.imwrite("image/"+savefold+"/"+each+"_mask.jpg",mask) #保存每种颜色对应的图片
#找到每种颜色的所有轮廓
cnts=cv2.findContours(mask,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)[1]
area=0 #统计面积
for c in cnts:
area+=cv2.contourArea(c)
color_area[each]=area #保存在字典里面
#按键排序
color_area=sorted(color_area.items(),key=lambda item:item[0],reverse=False)
return dict(color_area) #转为字典
测试的图片:
在计算颜色占水果的比例前,我们需要统计一下,水果的总像素,也就是我们要对水果做出一定的过滤,毕竟图片的长宽不是水果的长宽:
import numpy
import cv2
img=cv2.imread("image/orange.jpg") #读取图片
shape=img.shape #获取维度
newimg=numpy.zeros((500,500,3),numpy.uint8) #新建空白图,我的水果图片是500*500的
imgarea=0 #水果像素面积
for i in range(shape[0]):
for j in range(shape[1]):
#把RGB均大于150的去掉,也就是背景的白点
if img[i,j,0]>150 and img[i,j,1]>150 and img[i,j,2]>150:
continue
newimg[i,j]=img[i,j] #写入新图片
imgarea+=1
cv2.imwrite("image/newimg.jpg",newimg)
我们看下新图片的效果:
因为背景不够白,还有一些粉红,但大体上是和水果的面积一致了~~~~~~~
计算比例:
获取上面的代码返回的颜色和区域面积的字典,再结合统计出来的水果面积,就可以计算颜色占的比例了:
color_area=getColor("image/orange.jpg") #获取颜色和像素面积的字典
for keys,values in color_area.items():
print(keys,values/imgarea) #打印结果