是否有公式可以确定给定 BGR 值的整体颜色?(OpenCV 和 C++)

2021-12-10 00:00:00 opencv colors c++ pixels bgr

我正在使用 C++ 和 OpenCV 制作一个函数,该函数将检测图像中像素的颜色,确定它所在的颜色范围,并将其替换为通用颜色.例如,绿色的范围可以从深绿色到浅绿色,程序会确定它仍然是绿色并用简单的绿色替换它,从而使输出图像看起来非常简单.一切都已设置,但我无法定义每个范围的特征,并且很好奇是否有人知道或公式可以根据 BGR 值确定像素的整体颜色.如果没有,我将不得不做很多实验并自己制作,但如果已经存在可以节省时间的东西.我已经做了很多研究,但到目前为止还没有发现任何东西.

I am making a function using C++ and OpenCV that will detect the color of a pixel in an image, determine what color range it is in, and replace it with a generic color. For example, green could range from dark green to light green, the program would determine that its still green and replace it with a simple green, making the output image very simple looking. everything is set up but I'm having trouble defining the characteristics of each range and was curious if anyone knows or a formula that, given BGR values, could determine the overall color of a pixel. If not I'll have to do much experimentation and make it myself, but if something already exists that'd save time. I've done plenty of research and haven't found anything so far.

推荐答案

如果你想让你的图像更简单(即颜色更少),但好看,你有几个选择:

If you want to make your image simpler (i.e. with less colors), but good looking, you have a few options:

  • 一个简单的方法是将图像除以(整数除法)一个因子 N,然后乘以一个因子 N.

  • A simple approach would be to divide (integer division) by a factor N the image, and then multiply by a factor N.

或者您可以使用一些聚类算法(例如此处显示的 kmeans 或中值切割算法)将图像划分为 K 种颜色.

Or you can divide your image into K colors, using some clustering algorithm such as kmeans showed here, or median-cut algorithm.

原图:

减少颜色(量化,N = 64):

减少颜色(聚集,K = 8):

代码量化:

#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;

int main()
{
    Mat3b img = imread("path_to_image");

    imshow("Original", img);

    uchar N = 64;
    img  /= N;
    img  *= N;

    imshow("Reduced", img);
    waitKey();

    return 0;
}

代码kmeans:

#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;

int main()
{
    Mat3b img = imread("path_to_image");

    imshow("Original", img);

    // Cluster

    int K = 8;
    int n = img.rows * img.cols;
    Mat data = img.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, img.rows);
    reduced.convertTo(reduced, CV_8U);


    imshow("Reduced", reduced);
    waitKey();

    return 0;
}

相关文章