-
Notifications
You must be signed in to change notification settings - Fork 2
/
mashiro.h
220 lines (195 loc) · 5.27 KB
/
mashiro.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
//
// mashiro.hpp
// Mashiro
//
// Created by BlueCocoa on 16/2/2.
// Copyright © 2016 BlueCocoa. All rights reserved.
//
#ifndef MASHIRO_H
#define MASHIRO_H
#include <assert.h>
#include <cmath>
#include <float.h>
#include <functional>
#include <map>
#include <string>
#include <tuple>
#include <utility>
#include <vector>
#include "MersenneTwister.h"
/**
* @brief Forward
*/
namespace cv { class Mat; };
class mashiro;
class MashiroColor;
/**
RGB色彩空间
*/
enum MashiroColorSpaceRGB { Red, Green, Blue };
/**
* @brief 颜色与其出现的次数
*/
using MashiroColorWithCount = std::pair<MashiroColor, std::uint32_t>;
/**
* @brief 聚类后的颜色
*/
using Cluster = std::vector<MashiroColor>;
/**
* @brief 某一类的颜色
*/
using ClusteredPoint = std::map<std::uint32_t, std::vector<MashiroColorWithCount>>;
/**
* @brief 聚类完成后的回调函数
*
* @param image 分析的是哪张图
* @param colors 它的主要颜色
*/
using MashiroColorCallback = std::function<void(cv::Mat& image, const Cluster& colors)>;
class mashiro {
public:
/**
* @brief 使用cv::Mat初始化
*/
mashiro(cv::Mat& image) noexcept;
/**
* @brief 开始识别主要颜色
*
* @param number 需要几种主要颜色
* @param callback 聚类完成后的回调
*/
void color(std::uint32_t number, MashiroColorCallback callback, int convertColor = -1) noexcept;
/**
* @brief 快速访问std::tuple里的元素
*
* @param enumerator 需要指定一个枚举类型
*
* @return 对应位置上的值
*/
template<typename E>
static constexpr auto toType(E enumerator) noexcept {
return static_cast<std::underlying_type_t<E>>(enumerator);
};
/**
* @brief 调整图片大小
*
* @param src 源图片
* @param dest 调整后的图片
* @param width 宽度
* @param height 高度
* @param interpolation 方法
*/
static void resize(cv::Mat &src, cv::Mat &dest, int width, int height, int interpolation) noexcept;
/**
* @brief 获取一张图上所有的颜色及其出现的次数
*
* @param image 源图片
*
* @return 图上所有的颜色及其出现的次数
*/
static std::vector<MashiroColorWithCount> pixels(cv::Mat &image) noexcept;
/**
* @brief 给定一组带出现次数的颜色求其中心
*
* @param colors 一组带出现次数的颜色
*
* @return 该组颜色的中心值
*/
static MashiroColor center(const std::vector<MashiroColorWithCount>& colors) noexcept;
private:
/**
* @brief 需要处理的图像
*/
cv::Mat& image;
/**
* @brief kmeans聚类
*
* @param pixels 图上出现的颜色及其次数
* @param k 聚类种数
* @param min_diff 偏差
*
* @return 聚类后的k个颜色
*/
Cluster kmeans(const std::vector<MashiroColorWithCount>& pixels, std::uint32_t k, double min_diff = 1.0) noexcept;
};
/**
* @brief 颜色
*/
class MashiroColor {
public:
MashiroColor(double component1, double component2, double component3) noexcept;
double operator [](int value) const {
assert((0 <= value && value <= 2));
return this->component[value];
}
double & operator [](int index) {
assert((0 <= index && index <= 2));
return component[index];
}
int operator < (const MashiroColor& color2) const {
const MashiroColor color1 = * this;
if (color1[0] < color2[0]) {
return -1;
} else if (color1[0] == color2[0]) {
if (color1[1] < color2[1]) {
return -1;
} else if (color1[1] == color2[1]) {
if (color1[2] < color2[2]) {
return -1;
} else if (color1[2] == color2[2]) {
return 0;
} else {
return 1;
}
} else {
return 1;
}
} else {
return 1;
}
}
/**
* @brief 计算两个颜色的欧几里得距离
*
* @discussion 仅限RGB
*
* @param color1 Color 1
* @param color2 Color 2
*
* @return 两个颜色的欧几里得距离
*/
static double euclidean(const MashiroColor& color1, const MashiroColor& color2) noexcept;
/**
* @brief 计算与另一个颜色的欧几里得距离
*
* @discussion 仅限RGB
*
* @param color1 Color 1
* @param color2 Color 2
*
* @return 两个颜色的欧几里得距离
*/
double euclidean(const MashiroColor& color) noexcept;
/**
* @brief 将RGB颜色转为HSV颜色
*
* @param color RGB颜色
*
* @return HSV颜色
*/
static const MashiroColor RGB2HSV(const MashiroColor& color) noexcept;
/**
* @brief 将HSV颜色转为RGB颜色
*
* @param color HSV颜色
*
* @return RGB颜色
*/
static const MashiroColor HSV2RGB(const MashiroColor& color) noexcept;
private:
/**
* @brief RGB颜色分量
*/
double component[3];
};
#endif /* MASHIRO_H */