我正在使用C++和OpenCV编写一个函数,用于检测图像中像素的颜色,确定其所处的颜色范围,并将其替换为一种通用颜色。例如,绿色可以从深绿到浅绿变化,程序将确定它仍然是绿色,并将其替换为简单的绿色,使输出图像看起来非常简单。所有设置都已完成,但是我在定义每个范围的特征方面遇到了问题,想知道是否有公式可以根据BGR值确定像素的整体颜色。如果没有,我就必须进行大量实验并自己制定这个公式,但如果已经存在某些东西,那就可以节省时间。我已经做了大量研究,到目前为止还没有找到任何东西。
我正在使用C++和OpenCV编写一个函数,用于检测图像中像素的颜色,确定其所处的颜色范围,并将其替换为一种通用颜色。例如,绿色可以从深绿到浅绿变化,程序将确定它仍然是绿色,并将其替换为简单的绿色,使输出图像看起来非常简单。所有设置都已完成,但是我在定义每个范围的特征方面遇到了问题,想知道是否有公式可以根据BGR值确定像素的整体颜色。如果没有,我就必须进行大量实验并自己制定这个公式,但如果已经存在某些东西,那就可以节省时间。我已经做了大量研究,到目前为止还没有找到任何东西。
如果您想让图像变得更加简单(例如减少颜色),但又要好看,您有几个选择:
一种简单的方法是通过一个因子 N
进行整数除法运算,然后再乘以一个因子 N
。
或者您可以使用一些聚类算法,比如在这里展示的 kmeans
算法或中值切割算法,将图像分成 K
种颜色。
原始图像:
减少颜色(量化,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;
}
是的,你可能指的是“像素的整体颜色”,实际上是颜色的“色调”或“饱和度”。
所以你需要一个将RGB转换为HSV(色调、饱和度、明度)的公式,然后只关心色调或饱和度的值。
参见:将RGB转换为HSV和HSV转换为RGB的算法,在范围0-255内均适用
编辑:你可能需要将饱和度最大化,然后将其转换回RGB,并检查哪个值最高(例如(255,0,0)或(255,0,255)等)。
#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);
}
}
}
int three_reds = int(floor(R / 3)); ...
然后,你只需将每个范围映射到RGB空间中的单个颜色即可。 - Pyrce