marker_separation/cpp/palette.cpp

105 lines
2.4 KiB
C++
Raw Normal View History

2023-09-27 14:40:13 +00:00
#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;
}