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