C++ 如何使用OpenCV从图像中获取调色板

C++ 如何使用OpenCV从图像中获取调色板,c++,opencv,visual-c++,opencv3.0,C++,Opencv,Visual C++,Opencv3.0,我想提取图像的调色板,类似于以下内容(来源): 我需要它来提取特定的颜色,如黄色、绿色和棕色,并显示该颜色覆盖的面积百分比。此外,我可以添加更多的颜色来提取 如何减少原始图像中的颜色数量,以及如何获得调色板?这里有三种不同的情况 减少图像的颜色数量 获取图像的不同颜色 获取颜色名称 减少颜色的数量 有许多技术可以减少颜色的数量。您可以看到如何使用颜色量化和kmeans 另一种方法可以使用该算法(此处未显示) OpenCV提供了。您可以看到一些如何使用它的示例 获取图像的不同颜色 这很容易。只需

我想提取图像的调色板,类似于以下内容(来源):

我需要它来提取特定的颜色,如黄色、绿色和棕色,并显示该颜色覆盖的面积百分比。此外,我可以添加更多的颜色来提取


如何减少原始图像中的颜色数量,以及如何获得调色板?

这里有三种不同的情况

  • 减少图像的颜色数量
  • 获取图像的不同颜色
  • 获取颜色名称
  • 减少颜色的数量

    有许多技术可以减少颜色的数量。您可以看到如何使用颜色量化和kmeans

    另一种方法可以使用该算法(此处未显示)

    OpenCV提供了。您可以看到一些如何使用它的示例

    获取图像的不同颜色

    这很容易。只需迭代整个图像。如果看到新颜色,请存储其值,计数器等于1。如果您看到已经看到的颜色,请增加其计数器。std::map在这里可能很有用

    获取颜色名称

    我不会在这里展示。但在网上也有。您需要所有命名颜色的列表。请记住,并非每种颜色都有一个名称。事实上,RGB值的所有可能颜色都是
    256*256*256
    。因此,在列表中找到最接近的颜色,并将其名称指定给当前颜色


    例如,使用此输入图像

    使用kmeans方法,我得到了简化的彩色图像:

    其调色板为:

    Color: [14, 134, 225]    - Area: 5.28457%
    Color: [16, 172, 251]    - Area: 27.3851%
    Color: [22, 68, 101]     - Area: 3.41029%
    Color: [28, 154, 161]    - Area: 3.89029%
    Color: [40, 191, 252]    - Area: 22.3429%
    Color: [87, 204, 251]    - Area: 8.704%
    Color: [161, 222, 251]   - Area: 3.47429%
    Color: [253, 255, 255]   - Area: 25.5086%
    
    现在,您可以在列表中搜索最接近的颜色名称,您将获得所需的颜色。如何组成GUI来显示这些信息取决于您:数据都在那里

    代码:

    #包括
    #包括
    #包括
    #包括
    使用名称空间cv;
    使用名称空间std;
    // https://stackoverflow.com/a/34734939/5008845
    空隙减少颜色量化(常数Mat3b和src、Mat3b和dst)
    {
    uchar N=64;
    dst=src/N;
    dst*=N;
    }
    // https://stackoverflow.com/a/34734939/5008845
    无效还原色法(常数Mat3b和src、Mat3b和dst)
    {
    int K=8;
    int n=src.rows*src.cols;
    材料数据=钢筋混凝土重塑(1,n);
    数据转换(数据,CV_32F);
    矢量标签;
    Mat1f颜色;
    kmeans(数据、K、标签、cv::TermCriteria()、1、cv::kmeans\u PP\u中心、颜色);
    对于(int i=0;icout“Yellow”不是特定的颜色。
    7F1D33
    是特定的,而且很少见。它会抛出错误
    指定的比较器类型不提供常量调用运算符
    @user969068只需添加
    常量
    然后:
    布尔运算符()(常量Vec3b&lhs,常量Vec3b&rhs)常量{…
    #include <opencv2\opencv.hpp>
    #include <opencv2\photo.hpp>
    #include <iostream>
    #include <map>
    
    using namespace cv;
    using namespace std;
    
    // https://stackoverflow.com/a/34734939/5008845
    void reduceColor_Quantization(const Mat3b& src, Mat3b& dst)
    {
        uchar N = 64;
        dst = src / N;
        dst *= N;
    }
    
    // https://stackoverflow.com/a/34734939/5008845
    void reduceColor_kmeans(const Mat3b& src, Mat3b& dst)
    {
        int K = 8;
        int n = src.rows * src.cols;
        Mat data = src.reshape(1, n);
        data.convertTo(data, CV_32F);
    
        vector<int> labels;
        Mat1f colors;
        kmeans(data, K, labels, cv::TermCriteria(), 1, cv::KMEANS_PP_CENTERS, colors);
    
        for (int i = 0; i < n; ++i)
        {
            data.at<float>(i, 0) = colors(labels[i], 0);
            data.at<float>(i, 1) = colors(labels[i], 1);
            data.at<float>(i, 2) = colors(labels[i], 2);
        }
    
        Mat reduced = data.reshape(3, src.rows);
        reduced.convertTo(dst, CV_8U);
    }
    
    void reduceColor_Stylization(const Mat3b& src, Mat3b& dst)
    {
        stylization(src, dst);
    }
    
    void reduceColor_EdgePreserving(const Mat3b& src, Mat3b& dst)
    {
        edgePreservingFilter(src, dst);
    }
    
    
    struct lessVec3b
    {
        bool operator()(const Vec3b& lhs, const Vec3b& rhs) const {
            return (lhs[0] != rhs[0]) ? (lhs[0] < rhs[0]) : ((lhs[1] != rhs[1]) ? (lhs[1] < rhs[1]) : (lhs[2] < rhs[2]));
        }
    };
    
    map<Vec3b, int, lessVec3b> getPalette(const Mat3b& src)
    {
        map<Vec3b, int, lessVec3b> palette;
        for (int r = 0; r < src.rows; ++r)
        {
            for (int c = 0; c < src.cols; ++c)
            {
                Vec3b color = src(r, c);
                if (palette.count(color) == 0)
                {
                    palette[color] = 1;
                }
                else
                {
                    palette[color] = palette[color] + 1;
                }
            }
        }
        return palette;
    }
    
    
    int main()
    {
        Mat3b img = imread("path_to_image");
    
        // Reduce color
        Mat3b reduced;
    
        //reduceColor_Quantization(img, reduced);
        reduceColor_kmeans(img, reduced);
        //reduceColor_Stylization(img, reduced);
        //reduceColor_EdgePreserving(img, reduced);
    
    
        // Get palette
        map<Vec3b, int, lessVec3b> palette = getPalette(reduced);
    
        // Print palette
        int area = img.rows * img.cols;
    
        for (auto color : palette)
        {
            cout << "Color: " << color.first << " \t - Area: " << 100.f * float(color.second) / float(area) << "%" << endl;
        }
    
        return 0;
    }