zoukankan      html  css  js  c++  java
  • 基于图像的主颜色分析

    一般来说,直接分析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 ",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 ",i+1,(float)dpercent);
        }
        imshow("matResult",matResult);
        waitKey();
        return 0;
    }
  • 相关阅读:
    文件下载的多种方法
    WebService返回DataTable问题
    PowerDesigner设置
    C#中简单的写日志的方法
    sql server 汉字的长度
    validateRequest="false"属性及xss攻击
    TotoiseSVN的基本使用方法
    有选择性的生成一个表的插入脚本,不是选择全部数据生成
    xml2-config not found.
    Ueditor编辑旧文章,从数据库中取出要修改的内容
  • 原文地址:https://www.cnblogs.com/jsxyhelu/p/7008525.html
Copyright © 2011-2022 走看看