OrcaSlicer latest
OrcaSlicer
Loading...
Searching...
No Matches
QuantKMeans Class Reference

#include </home/runner/work/OrcaSlicer/OrcaSlicer/src/libslic3r/ObjColorUtils.hpp>

Public Member Functions

 QuantKMeans (int alpha_thres=10)
void apply (cv::Mat &ori_image, cv::Mat &new_image, int num_cluster, int color_space)
void apply_aplha (cv::Mat &ori_image, cv::Mat &new_image, int num_cluster, int color_space)
void apply (cv::Mat &flatten_image, int num_cluster, int color_space)
void apply (const std::vector< std::array< float, 4 > > &ori_colors, std::vector< std::array< float, 4 > > &cluster_results, std::vector< int > &labels, int num_cluster=-1, int max_cluster=15, int color_space=2)
void apply (const cv::Mat &flatten_image8UC3, std::vector< std::array< float, 4 > > &cluster_results, std::vector< int > &labels, int num_cluster=-1, int max_cluster=15, int color_space=2)
bool more_than_request (const cv::Mat &image8UC3, int target_num)
int compute_num_colors (const cv::Mat &image8UC3)
bool is_in (const cv::Vec3b &cur_color, const std::vector< cv::Vec3b > &uniqueImage)
bool repeat_center (int cur_cluster, const cv::Mat &centers32FC3, int color_space)
void replace_centers (cv::Mat &ori_image, cv::Mat &new_image)
void repalce_centers_aplha (cv::Mat &ori_image, cv::Mat &new_image)
void convert_color_space (const cv::Mat &ori_image, cv::Mat &image, int color_space, bool reverse=false)
cv::Mat flatten (cv::Mat &image)
cv::Mat flatten_alpha (cv::Mat &image)
cv::Mat flatten_vector (const std::vector< std::array< float, 4 > > &ori_colors)

Public Attributes

int m_alpha_thres
cv::Mat m_flatten_labels
cv::Mat m_centers8UC3

Detailed Description

Constructor & Destructor Documentation

◆ QuantKMeans()

QuantKMeans::QuantKMeans ( int alpha_thres = 10)
inline
20: m_alpha_thres(alpha_thres) {}
int m_alpha_thres
Definition ObjColorUtils.hpp:17

References m_alpha_thres.

Member Function Documentation

◆ apply() [1/4]

void QuantKMeans::apply ( const cv::Mat & flatten_image8UC3,
std::vector< std::array< float, 4 > > & cluster_results,
std::vector< int > & labels,
int num_cluster = -1,
int max_cluster = 15,
int color_space = 2 )
inline
72 {
73 cv::Mat image8UC3;
74 convert_color_space(flatten_image8UC3, image8UC3, color_space);
75
76 cv::Mat image32FC3(image8UC3.rows, 1, CV_32FC3);
77 for (int i = 0; i < image8UC3.rows; i++)
78 image32FC3.at<cv::Vec3f>(i, 0) = image8UC3.at<cv::Vec3b>(i, 0);
79
80 int best_cluster = 1;
81 double cur_score = 0, best_score = 100;
82 num_cluster = fmin(num_cluster, max_cluster);
83 if (num_cluster < 1) {
84 if (!this->more_than_request(image8UC3, max_cluster)) max_cluster = compute_num_colors(image8UC3);
85 num_cluster = fmin(num_cluster, max_cluster);
86 cur_score = cv::kmeans(image32FC3, 1, this->m_flatten_labels, cv::TermCriteria(cv::TermCriteria::EPS + cv::TermCriteria::COUNT, 300, 0.5), 3, cv::KMEANS_PP_CENTERS);
87 best_score = cur_score;
88
89 for (int cur_cluster = 2; cur_cluster < max_cluster + 1; cur_cluster++) {
90 cv::Mat centers32FC3;
91 cur_score = cv::kmeans(image32FC3, cur_cluster, this->m_flatten_labels, cv::TermCriteria(cv::TermCriteria::EPS + cv::TermCriteria::COUNT, 300, 0.5), 3,
92 cv::KMEANS_PP_CENTERS, centers32FC3);
93 if (this->repeat_center(cur_cluster, centers32FC3, color_space))
94 break;
95 best_cluster = cur_score < best_score ? cur_cluster : best_cluster;
96 best_score = cur_score < best_score ? cur_score : best_score;
97 }
98 } else if (this->more_than_request(image8UC3, num_cluster))
99 best_cluster = num_cluster;
100 else {
101 best_cluster = compute_num_colors(image8UC3);
102 std::cout << "num of image color is " << best_cluster << ", less than custom number " << num_cluster << std::endl;
103 }
104
105 cv::Mat centers32FC3;
106 cv::kmeans(image32FC3, best_cluster, this->m_flatten_labels, cv::TermCriteria(cv::TermCriteria::EPS + cv::TermCriteria::COUNT, 300, 0.5), 3, cv::KMEANS_PP_CENTERS,
107 centers32FC3);
108 this->m_centers8UC3 = cv::Mat(best_cluster, 1, CV_8UC3);
109 for (int i = 0; i < best_cluster; i++) {
110 auto center = centers32FC3.row(i);
111 this->m_centers8UC3.at<cv::Vec3b>(i) = {uchar(center.at<float>(0)), uchar(center.at<float>(1)), uchar(center.at<float>(2))};
112 }
113 convert_color_space(this->m_centers8UC3, this->m_centers8UC3, color_space, true);
114
115 cluster_results.clear();
116 labels.clear();
117 for (int i = 0; i < flatten_image8UC3.rows; i++)
118 labels.emplace_back(this->m_flatten_labels.at<int>(i, 0));
119 for (int i = 0; i < best_cluster; i++) {
120 cv::Vec3f center = this->m_centers8UC3.at<cv::Vec3b>(i, 0);
121 cluster_results.emplace_back(std::array<float, 4>{center[0] / 255.f, center[1] / 255.f, center[2] / 255.f, 1.f});
122 }
123 }
void convert_color_space(const cv::Mat &ori_image, cv::Mat &image, int color_space, bool reverse=false)
Definition ObjColorUtils.hpp:207
bool repeat_center(int cur_cluster, const cv::Mat &centers32FC3, int color_space)
Definition ObjColorUtils.hpp:158
int compute_num_colors(const cv::Mat &image8UC3)
Definition ObjColorUtils.hpp:139
cv::Mat m_centers8UC3
Definition ObjColorUtils.hpp:19
bool more_than_request(const cv::Mat &image8UC3, int target_num)
Definition ObjColorUtils.hpp:125
cv::Mat m_flatten_labels
Definition ObjColorUtils.hpp:18
void center(ExPolygonsWithIds &e)
Definition Emboss.cpp:1382

References compute_num_colors(), convert_color_space(), more_than_request(), and repeat_center().

Here is the call graph for this function:

◆ apply() [2/4]

void QuantKMeans::apply ( const std::vector< std::array< float, 4 > > & ori_colors,
std::vector< std::array< float, 4 > > & cluster_results,
std::vector< int > & labels,
int num_cluster = -1,
int max_cluster = 15,
int color_space = 2 )
inline
60 {
61 // 0~255
62 cv::Mat flatten_image8UC3 = flatten_vector(ori_colors);
63
64 this->apply(flatten_image8UC3, cluster_results, labels, num_cluster, max_cluster, color_space);
65 }
void apply(cv::Mat &ori_image, cv::Mat &new_image, int num_cluster, int color_space)
Definition ObjColorUtils.hpp:21
cv::Mat flatten_vector(const std::vector< std::array< float, 4 > > &ori_colors)
Definition ObjColorUtils.hpp:258

References apply(), and flatten_vector().

Here is the call graph for this function:

◆ apply() [3/4]

void QuantKMeans::apply ( cv::Mat & flatten_image,
int num_cluster,
int color_space )
inline
44 {
45 cv::Mat centers32FC3;
46 num_cluster = fmin(flatten_image.rows, num_cluster);
47 kmeans(flatten_image, num_cluster, this->m_flatten_labels, cv::TermCriteria(cv::TermCriteria::EPS + cv::TermCriteria::COUNT, 300, 0.5), 3, cv::KMEANS_PP_CENTERS,
48 centers32FC3);
49 this->m_centers8UC3 = cv::Mat(num_cluster, 1, CV_8UC3);
50 for (int i = 0; i < num_cluster; i++) this->m_centers8UC3.at<cv::Vec3b>(i) = centers32FC3.at<cv::Vec3f>(i);
51
52 convert_color_space(this->m_centers8UC3, this->m_centers8UC3, color_space, true);
53 }

References convert_color_space().

Here is the call graph for this function:

◆ apply() [4/4]

void QuantKMeans::apply ( cv::Mat & ori_image,
cv::Mat & new_image,
int num_cluster,
int color_space )
inline
22 {
23 cv::Mat image;
24 convert_color_space(ori_image, image, color_space);
25 cv::Mat flatten_image = flatten(image);
26
27 apply(flatten_image, num_cluster, color_space);
28 replace_centers(ori_image, new_image);
29 }
cv::Mat flatten(cv::Mat &image)
Definition ObjColorUtils.hpp:227
void replace_centers(cv::Mat &ori_image, cv::Mat &new_image)
Definition ObjColorUtils.hpp:178

References apply(), convert_color_space(), flatten(), and replace_centers().

Referenced by apply(), apply(), apply_aplha(), and obj_color_deal_algo().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ apply_aplha()

void QuantKMeans::apply_aplha ( cv::Mat & ori_image,
cv::Mat & new_image,
int num_cluster,
int color_space )
inline
31 {
32 // cout << " *** DoAlpha *** " << endl;
33 cv::Mat flatten_image8UC3 = flatten_alpha(ori_image);
34 cv::Mat image8UC3;
35 convert_color_space(flatten_image8UC3, image8UC3, color_space);
36 cv::Mat image32FC3(image8UC3.rows, 1, CV_32FC3);
37 for (int i = 0; i < image8UC3.rows; i++)
38 image32FC3.at<cv::Vec3f>(i, 0) = image8UC3.at<cv::Vec3b>(i, 0);
39
40 apply(image32FC3, num_cluster, color_space);
41 repalce_centers_aplha(ori_image, new_image);
42 }
cv::Mat flatten_alpha(cv::Mat &image)
Definition ObjColorUtils.hpp:239
void repalce_centers_aplha(cv::Mat &ori_image, cv::Mat &new_image)
Definition ObjColorUtils.hpp:188

References apply(), convert_color_space(), flatten_alpha(), and repalce_centers_aplha().

Here is the call graph for this function:

◆ compute_num_colors()

int QuantKMeans::compute_num_colors ( const cv::Mat & image8UC3)
inline
140 {
141 std::vector<cv::Vec3b> uniqueImage;
142 cv::Vec3b cur_color;
143 for (int i = 0; i < image8UC3.rows; i++) {
144 cur_color = image8UC3.at<cv::Vec3b>(i, 0);
145 if (!is_in(cur_color, uniqueImage)) uniqueImage.emplace_back(cur_color);
146 }
147
148 return uniqueImage.size();
149 }
bool is_in(const cv::Vec3b &cur_color, const std::vector< cv::Vec3b > &uniqueImage)
Definition ObjColorUtils.hpp:151

References is_in().

Referenced by apply().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ convert_color_space()

void QuantKMeans::convert_color_space ( const cv::Mat & ori_image,
cv::Mat & image,
int color_space,
bool reverse = false )
inline
208 {
209 switch (color_space) {
210 case 0: image = ori_image; break;
211 case 1:
212 if (reverse)
213 cvtColor(ori_image, image, cv::COLOR_HSV2BGR);
214 else
215 cvtColor(ori_image, image, cv::COLOR_BGR2HSV);
216 break;
217 case 2:
218 if (reverse)
219 cvtColor(ori_image, image, cv::COLOR_Lab2BGR);
220 else
221 cvtColor(ori_image, image, cv::COLOR_BGR2Lab);
222 break;
223 default: break;
224 }
225 }

Referenced by apply(), apply(), apply(), apply_aplha(), and repeat_center().

Here is the caller graph for this function:

◆ flatten()

cv::Mat QuantKMeans::flatten ( cv::Mat & image)
inline
228 {
229 int num_pixels = image.rows * image.cols;
230 cv::Mat img(num_pixels, 1, CV_32FC3);
231 for (int i = 0; i < image.rows; i++) {
232 for (int j = 0; j < image.cols; j++) {
233 cv::Vec3f pixel = image.at<cv::Vec3b>(i, j);
234 img.at<cv::Vec3f>(i * image.cols + j, 0) = pixel;
235 }
236 }
237 return img;
238 }

Referenced by apply().

Here is the caller graph for this function:

◆ flatten_alpha()

cv::Mat QuantKMeans::flatten_alpha ( cv::Mat & image)
inline
240 {
241 int num_pixels = image.rows * image.cols;
242 for (int i = 0; i < image.rows; i++)
243 for (int j = 0; j < image.cols; j++) {
244 cv::Vec4b pixel = image.at<cv::Vec4b>(i, j);
245 if ((int) pixel[3] < this->m_alpha_thres) num_pixels--;
246 }
247
248 cv::Mat img(num_pixels, 1, CV_8UC3);
249 int cnt = 0;
250 for (int i = 0; i < image.rows; i++) {
251 for (int j = 0; j < image.cols; j++) {
252 cv::Vec4b pixel = image.at<cv::Vec4b>(i, j);
253 if ((int) pixel[3] >= this->m_alpha_thres) img.at<cv::Vec3b>(cnt++, 0) = cv::Vec3b(pixel[0], pixel[1], pixel[2]);
254 }
255 }
256 return img;
257 }

Referenced by apply_aplha().

Here is the caller graph for this function:

◆ flatten_vector()

cv::Mat QuantKMeans::flatten_vector ( const std::vector< std::array< float, 4 > > & ori_colors)
inline
259 {
260 int num_pixels = ori_colors.size();
261
262 cv::Mat image8UC3(num_pixels, 1, CV_8UC3);
263 for (int i = 0; i < num_pixels; i++) {
264 std::array<float, 4> pixel = ori_colors[i];
265 image8UC3.at<cv::Vec3b>(i, 0) = cv::Vec3b((int) (pixel[0] * 255.f), (int) (pixel[1] * 255.f), (int) (pixel[2] * 255.f));
266 }
267 return image8UC3;
268 }

Referenced by apply().

Here is the caller graph for this function:

◆ is_in()

bool QuantKMeans::is_in ( const cv::Vec3b & cur_color,
const std::vector< cv::Vec3b > & uniqueImage )
inline
152 {
153 for (auto &color : uniqueImage)
154 if (cur_color[0] == color[0] && cur_color[1] == color[1] && cur_color[2] == color[2]) return true;
155 return false;
156 }

Referenced by compute_num_colors(), more_than_request(), and repeat_center().

Here is the caller graph for this function:

◆ more_than_request()

bool QuantKMeans::more_than_request ( const cv::Mat & image8UC3,
int target_num )
inline
126 {
127 std::vector<cv::Vec3b> uniqueImage;
128 cv::Vec3b cur_color;
129 for (int i = 0; i < image8UC3.rows; i++) {
130 cur_color = image8UC3.at<cv::Vec3b>(i, 0);
131 if (!is_in(cur_color, uniqueImage)) {
132 uniqueImage.emplace_back(cur_color);
133 if (uniqueImage.size() >= target_num) return true;
134 }
135 }
136 return false;
137 }

References is_in().

Referenced by apply().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ repalce_centers_aplha()

void QuantKMeans::repalce_centers_aplha ( cv::Mat & ori_image,
cv::Mat & new_image )
inline
189 {
190 int cnt = 0;
191 int idx;
192 cv::Vec3b center;
193 for (int i = 0; i < ori_image.rows; i++) {
194 for (int j = 0; j < ori_image.cols; j++) {
195 cv::Vec4b pixel = ori_image.at<cv::Vec4b>(i, j);
196 if ((int) pixel[3] < this->m_alpha_thres)
197 new_image.at<cv::Vec4b>(i, j) = pixel;
198 else {
199 idx = this->m_flatten_labels.at<int>(cnt++, 0);
200 center = this->m_centers8UC3.at<cv::Vec3b>(idx);
201 new_image.at<cv::Vec4b>(i, j) = cv::Vec4b(center[0], center[1], center[2], pixel[3]);
202 }
203 }
204 }
205 }

Referenced by apply_aplha().

Here is the caller graph for this function:

◆ repeat_center()

bool QuantKMeans::repeat_center ( int cur_cluster,
const cv::Mat & centers32FC3,
int color_space )
inline
159 {
160 cv::Mat centers8UC3 = cv::Mat(cur_cluster, 1, CV_8UC3);
161 for (int i = 0; i < cur_cluster; i++) {
162 auto center = centers32FC3.row(i);
163 centers8UC3.at<cv::Vec3b>(i) = {uchar(center.at<float>(0)), uchar(center.at<float>(1)), uchar(center.at<float>(2))};
164 }
165 convert_color_space(centers8UC3, centers8UC3, color_space, true);
166 std::vector<cv::Vec3b> unique_centers;
167 cv::Vec3b cur_center;
168 for (int i = 0; i < cur_cluster; i++) {
169 cur_center = centers8UC3.at<cv::Vec3b>(i, 0);
170 if (!is_in(cur_center, unique_centers))
171 unique_centers.emplace_back(cur_center);
172 else
173 return true;
174 }
175 return false;
176 }

References convert_color_space(), and is_in().

Referenced by apply().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ replace_centers()

void QuantKMeans::replace_centers ( cv::Mat & ori_image,
cv::Mat & new_image )
inline
179 {
180 for (int i = 0; i < ori_image.rows; i++) {
181 for (int j = 0; j < ori_image.cols; j++) {
182 int idx = this->m_flatten_labels.at<int>(i * ori_image.cols + j, 0);
183 cv::Vec3b pixel = this->m_centers8UC3.at<cv::Vec3b>(idx);
184 new_image.at<cv::Vec3b>(i, j) = pixel;
185 }
186 }
187 }

Referenced by apply().

Here is the caller graph for this function:

Member Data Documentation

◆ m_alpha_thres

int QuantKMeans::m_alpha_thres

Referenced by QuantKMeans().

◆ m_centers8UC3

cv::Mat QuantKMeans::m_centers8UC3

◆ m_flatten_labels

cv::Mat QuantKMeans::m_flatten_labels

The documentation for this class was generated from the following file: