颜色名称是人类对颜色的语言标签。比如以下11个色块我们进行语言标签
我们经常使用它们,来描述我们周围的世界,他们主要研究了视觉心理学、人类学和语言学等领域的研究。在计算机视觉上下文中的颜色命名是将语言颜色标签分配给图像像素的作用。利用机器学习算法自动从谷歌图片搜索学习颜色名称。
例如以下图片,
我们大体看到以下三种颜色:蓝色、绿色、橘色
Joost van de Weijer通过以下两篇文章:
《Learning Color Names from Real-World Images 》
《Learning Color Names for Real-World Applications 》
详细介绍了利用PLSA概率潜语义分析,从goole图片中学习了11种颜色,并给出了matlab代码。作者只给出了训练的结果。我用openCV复现了一遍。
-----------------------------------------------------------------------------------------------------------------------------------
我们只需要将BGR颜色空间,每一个通道的值0-255,每8个步长,进行分割,那么一共分为256/8=32个区间,因为有三个通道,那么一共给有32*32*32种组合。
opencv-代码:
#include<iostream>
using namespace std;
#include<opencv2\core\core.hpp>
#include<opencv2\highgui\highgui.hpp>
using namespace cv;
Mat floorMat(const Mat & doubleMat);
int main(int argc,char * argv[])
{
//读取图片
Mat image = imread(argv[1],1);
//判断是否有图片
if(!image.data)
return 0;
//判断是否是彩色图片
if( image.channels() != 3)
return 0;
int rows = image.rows;
int cols = image.cols;
int areas = rows*cols;
//分离通道
vector<Mat> bgr_planes;
split(image,bgr_planes);
//把各通道转为64F
Mat bplanes,gplanes,rplanes;
bgr_planes[0].convertTo(bplanes,CV_64FC1);
bgr_planes[1].convertTo(gplanes,CV_64FC1);
bgr_planes[2].convertTo(rplanes,CV_64FC1);
//floor(各通道/8.0)
Mat fbplanes,fgplanes,frplanes;
fbplanes = floorMat(bplanes);
fgplanes = floorMat(gplanes);
frplanes = floorMat(rplanes);
Mat index_im = frplanes+32*fgplanes+32*32*fbplanes;//index_im最大值可能为:31+31*32+32*32*31=32767
Mat index_im_col;
index_im_col = index_im.reshape(1,areas);
//读取w2cM
FileStorage fs(argv[2],FileStorage::READ);
Mat w2cM;
fs["w2cM"]>>w2cM;
cout << "12"<<endl;
//index_col存放的0-10之间的数值,代表11种颜色
Mat index_col(areas,1,CV_32SC1);
int tempIndex;
for(int r = 0;r< areas;r++)
{
tempIndex = index_im_col.at<int>(r,0);
index_col.at<int>(r,0) = w2cM.at<int>(tempIndex,0);
}
//reshape
Mat out2 = index_col.reshape(1,rows);
/* ----------------------11种颜色值----------------------------------*/
Mat color_values(11,1,CV_64FC3);
//black-黑色 [0 0 0]
color_values.at<Vec3d>(0,0) = Vec3d(0,0,0);
//blue-蓝色 [1 0 0]
color_values.at<Vec3d>(1,0) = Vec3d(1,0,0);
//brown-棕色(褐色) [0.25 0.4 0.5]
color_values.at<Vec3d>(2,0) = Vec3d(0.25,0.4,0.5);
//grey-灰色[0.5 0.5 0.5]
color_values.at<Vec3d>(3,0) = Vec3d(0.5,0.5,0.5);
//green-绿色[0 1 0]
color_values.at<Vec3d>(4,0) = Vec3d(0,1,0);
//orange-橘色[0 0.8 1]
color_values.at<Vec3d>(5,0) = Vec3d(0,0.8,1);
//pink-粉红色[1 0.5 1]
color_values.at<Vec3d>(6,0) = Vec3d(1,0.5,1);
//purple-紫色[1 0 1]
color_values.at<Vec3d>(7,0) = Vec3d(1,0,1);
//red-红色 [0 0 1]
color_values.at<Vec3d>(8,0) = Vec3d(0,0,1);
//white-白色 [1 1 1]
color_values.at<Vec3d>(9,0) = Vec3d(1,1,1);
//yellow-黄色[0 1 1]
color_values.at<Vec3d>(10,0) = Vec3d(0,1,1);
/*--------------------------------------------------------*/
Mat out(rows,cols,CV_64FC3);
for(int r = 0 ;r<rows;r++)
{
for(int c =0;c<cols;c++)
{
int tindex = out2.at<int>(r,c);
out.at<Vec3d>(r,c) = color_values.at<Vec3d>(tindex,0)*255;
}
}
Mat colorMap;
out.convertTo(colorMap,CV_8UC3);
namedWindow("colorMap",1);
imshow("colorMap",colorMap);
//关闭文件
fs.release();
waitKey(0);
return 0;
}
//注意参数只为 CV_64FC1
Mat floorMat(const Mat & doubleMat)
{
int rows = doubleMat.rows;
int cols = doubleMat.cols;
Mat flo(rows,cols,CV_32SC1);
for(int r = 0;r < rows;r++)
{
for(int c = 0;c < cols ;c++)
{
flo.at<int>(r,c)= floor(doubleMat.at<double>(r,c)/8.0);
}
}
return flo;
}
已经将w2c.mat转换为w2c.xml文件,下载地址:
【运行结果显示】:
上述图片进行颜色标签的结果为:
【黄色】【黑色】【橘色】
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
该算法可以用于基于颜色的图像检索、识别、运动物体跟踪等。。基于颜色识别我们可以用HLS、HSV颜色空间进行分割,也会有不错的效果,下一篇再写。