Существует ли формула для определения общего цвета с учетом значений BGR? (OpenCV и C ++)

Я делаю функцию с использованием C ++ и OpenCV, которая будет определять цвет пикселя на изображении, определять его цветовую гамму и заменять его на общий цвет. Например, зеленый может варьироваться от темно-зеленого до светло-зеленого, программа определит, что он все еще зеленый, и заменит его простым зеленым, что сделает выходное изображение очень простым. все настроено, но у меня возникают проблемы с определением характеристик каждого диапазона, и мне было любопытно, если кто-нибудь знает или формула, которая, учитывая значения BGR, может определить общий цвет пикселя. Если нет, мне придется много экспериментировать и делать это самому, но если что-то уже существует, это сэкономит время. Я провел много исследований и пока не нашел ничего.

7

Решение

Если вы хотите сделать свое изображение проще (то есть с меньшим количеством цветов), но хорошо выглядящий, у вас есть несколько вариантов:

  • Простой подход будет разделить (целочисленное деление) фактором N изображение, а затем умножить на коэффициент N,

  • Или вы можете разделить свое изображение на K цвета, используя некоторый алгоритм кластеризации, такой как kmeans показанный здесь, или алгоритм медианного разреза.

Исходное изображение:

введите описание изображения здесь

Уменьшенные цвета (квантованные, 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;
}
14

Другие решения

Да, то, что вы, вероятно, подразумеваете под «общим цветом пикселя», является «Оттенок» или «Насыщенность» цвета.

Поэтому вам нужна формула, которая преобразует RGB в HSV (оттенок, насыщенность, значение), и тогда вас будут интересовать только значения оттенка или насыщенности.

Увидеть: Алгоритм преобразования RGB в HSV и HSV в RGB в диапазоне 0-255 для обоих

РЕДАКТИРОВАТЬ: вам может потребоваться максимально увеличить насыщенность, а затем преобразовать ее обратно в RGB и проверить, какое значение является самым высоким (например, (255,0,0) или (255,0255) и т. Д.

4

Если вы хотите получить доступ к значению RGB всех пикселей, то ниже приведен код,

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

int main()
{
Mat image = imread("image_path");

for(int row = 1; row < image.rows; row++)
{
for(int col = 1; col < image.cols; col++)
{
Vec3b rgb = image.at<Vec3b>(row, col);
}
}

}
-1