我正在使用 C++ 和 OpenCV 制作一个函数,它将检测图像中像素的颜色,确定它所在的颜色范围,并将其替换为通用颜色。例如,绿色的范围可以从深绿色到浅绿色,程序会确定它仍然是绿色并将其替换为简单的绿色,从而使输出图像看起来非常简单。一切都设置好了,但是我在定义每个范围的特征时遇到了麻烦,并且很好奇是否有人知道或者有一个公式,给定 BGR 值,可以确定像素的整体颜色。如果不是,我将不得不做很多实验并自己制作,但如果已经存在某些东西,那将节省时间。我做了很多研究,到目前为止还没有发现任何东西。
7921 次
3 回答
22
如果你想让你的图像更简单(即颜色更少),但好看,你有几个选择:
一种简单的方法是将图像除以一个因子(整数除法)
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;
}
于 2016-01-12T03:09:07.310 回答
5
是的,您所说的“像素的整体颜色”可能是指颜色的“色调”或“饱和度”。
因此,您需要一个将 RGB 转换为 HSV(色相、饱和度、值)的公式,然后您只会对色相或饱和度值感兴趣。
请参阅:在 0-255 范围内将 RGB 转换为 HSV 和 HSV 到 RGB 的算法
编辑:您可能需要最大化饱和度,然后将其转换回 RGB,并检查哪个值最高(例如(255,0,0)或(255,0,255)等。
于 2016-01-12T02:14:36.630 回答
-2
如果你想访问所有像素的 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);
}
}
}
于 2016-01-12T05:26:09.670 回答