基于图像的主颜色分析

一般来说,直接分析RGB色彩域的颜色分布不是一个好的思路,我们一般转换到HSV域来分析。但是本文只要是应网友提问,实现最基本的RGB 色彩域的主颜色分析。
代码分为以下部分:
1、生成测试图片。为了测试算法是否准确,主动生成 具有25种不同颜色同比重的图片(每种4%)的 测试图片。
     创建具有25种不同颜色同比重的图片
    Mat src  = Mat( 250, 250,CV_8UC3,Scalar( 0));
     //生成时间种子
    time_t t;time( &t);
    RNG rng(t);
     //创建图片
     for ( int i  =  0;i < 250;i += 10)
        rectangle(src,Point( 0,i),Point(src.cols,i + 9),Scalar(rng.uniform( 0, 255),rng.uniform( 0, 255),rng.uniform( 0, 255)), - 1);
    imshow( "src",src);
    imwrite( "e:/template/maincolor.jpg",src);
生成的结果大概是这个样子的。
2、读取图片数据,保存到3维数组中去。
     //bgr立方体 
     int  *iTable  =  new  int [ 256, 256, 256];
     for ( int b = 0;b < 256;b ++)
    {
         for ( int g = 0;g < 256;g ++)
        {
             for ( int r = 0;r < 256;r ++)
            {
                iTable[b,g,r]  =  0;
            }
        }
    }
     //出现过的颜色
    vector <Vec3b > colorAppeared;
     //读取数据
     for ( int i = 0;i <src.cols;i ++)
    {
         for ( int j = 0;j <src.rows;j ++)
        {
             int b  = src.at <Vec3b >(i,j)[ 0];
             int g  = src.at <Vec3b >(i,j)[ 1];
             int r  = src.at <Vec3b >(i,j)[ 2];
             if (iTable[b,g,r]  ==  0)
                colorAppeared.push_back(src.at <Vec3b >(i,j));
            iTable[b,g,r]  ++;
        }
    }
 
3、将数组结果保存到vector中,使用标准库的排序方法。需要注意的是这里重载了vector的比较函数
//重载用于排序的比较函数
bool Comp( const std : :pair <Vec3b, int >  &a, const std : :pair <Vec3b, int >  &b)
{
     return a.second  > b.second;
}
  //将出现过的数据插入标准库
     for ( int i = 0;i <colorAppeared.size();i ++)
    {
        Vec3b vec3b  = colorAppeared[i];
         int b  = vec3b[ 0];
         int g  = vec3b[ 1];
         int r  = vec3b[ 2];
        std : :pair <Vec3b, int > apair(vec3b,iTable[b,g,r]);
        result.push_back(apair);
    }
     //进行排序
    sort(result.begin(),result.end(),Comp);
 
4、显示最后结果
  显示结果 前20
    Mat matResult  = Mat( 200, 200,CV_8UC3,Scalar( 0));
     for ( int i  =  0;i < 20;i ++)
    {
        Vec3b vec3b  = result[i].first;
         int iint  = result[i].second;
         float dpercent  = ( float)iint  / (src.rows  * src.cols);
        rectangle(matResult,Point( 0,i * 10),Point( 200,i * 10 + 9),vec3b, - 1);
        printf( "第%d种颜色,占比例为%f\n",i + 1,( float)dpercent);
    }
    imshow( "matResult",matResult);
5、完整的代码如下。感谢阅读,希望有所收获,欢迎交流。
// jsxyhelu (jsxyhelu@foxmail.com)
# include  "stdafx.h"
# include  <opencv2 /core /utility.hpp >
# include  "opencv2/imgproc.hpp"
# include  "opencv2/imgcodecs.hpp"
# include  "opencv2/highgui.hpp"
# include  <opencv2 /photo.hpp >
# include  <fstream >
# include  <iostream >
using  namespace cv;
using  namespace std;
//重载用于排序的比较函数
bool Comp( const std : :pair <Vec3b, int >  &a, const std : :pair <Vec3b, int >  &b)
{
     return a.second  > b.second;
}
int main(  int argc,  const  char * * argv )
{
     创建具有25种不同颜色同比重的图片
    Mat src  = Mat( 250, 250,CV_8UC3,Scalar( 0));
     //生成时间种子
    time_t t;time( &t);
    RNG rng(t);
     //创建图片
     for ( int i  =  0;i < 250;i += 10)
        rectangle(src,Point( 0,i),Point(src.cols,i + 9),Scalar(rng.uniform( 0, 255),rng.uniform( 0, 255),rng.uniform( 0, 255)), - 1);
    imshow( "src",src);
    imwrite( "e:/template/maincolor.jpg",src);
     进行主要颜色分析
     //用于保存当前出现过的颜色数据结构
    std : :vector <std : :pair <Vec3b, int >> result;
     //bgr立方体 
     int  *iTable  =  new  int [ 256, 256, 256];
     for ( int b = 0;b < 256;b ++)
    {
         for ( int g = 0;g < 256;g ++)
        {
             for ( int r = 0;r < 256;r ++)
            {
                iTable[b,g,r]  =  0;
            }
        }
    }
     //出现过的颜色
    vector <Vec3b > colorAppeared;
     //读取数据
     for ( int i = 0;i <src.cols;i ++)
    {
         for ( int j = 0;j <src.rows;j ++)
        {
             int b  = src.at <Vec3b >(i,j)[ 0];
             int g  = src.at <Vec3b >(i,j)[ 1];
             int r  = src.at <Vec3b >(i,j)[ 2];
             if (iTable[b,g,r]  ==  0)
                colorAppeared.push_back(src.at <Vec3b >(i,j));
            iTable[b,g,r]  ++;
        }
    }
     //将出现过的数据插入标准库
     for ( int i = 0;i <colorAppeared.size();i ++)
    {
        Vec3b vec3b  = colorAppeared[i];
         int b  = vec3b[ 0];
         int g  = vec3b[ 1];
         int r  = vec3b[ 2];
        std : :pair <Vec3b, int > apair(vec3b,iTable[b,g,r]);
        result.push_back(apair);
    }
     //进行排序
    sort(result.begin(),result.end(),Comp);
     显示结果 前20
    Mat matResult  = Mat( 200, 200,CV_8UC3,Scalar( 0));
     for ( int i  =  0;i < 20;i ++)
    {
        Vec3b vec3b  = result[i].first;
         int iint  = result[i].second;
         float dpercent  = ( float)iint  / (src.rows  * src.cols);
        rectangle(matResult,Point( 0,i * 10),Point( 200,i * 10 + 9),vec3b, - 1);
        printf( "第%d种颜色,占比例为%f\n",i + 1,( float)dpercent);
    }
    imshow( "matResult",matResult);
    waitKey();
     return  0;
}

 

posted on 2022-12-03 15:31  jsxyhelu  阅读(59)  评论(0编辑  收藏  举报

导航