105 lines
2.4 KiB
C++
105 lines
2.4 KiB
C++
|
#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;
|
||
|
}
|