39 #include <visp3/core/vpHistogram.h>
40 #include <visp3/core/vpImageTools.h>
41 #include <visp3/imgproc/vpImgproc.h>
46 bool isBimodal(
const std::vector<float> &hist_float)
49 const int bimodalVal = 2;
50 size_t hist_float_size_m_1 = hist_float.size() - 1;
51 for (
size_t cpt = 1; cpt < hist_float_size_m_1; ++cpt) {
52 if ((hist_float[cpt - 1] < hist_float[cpt]) && (hist_float[cpt] > hist_float[cpt + 1])) {
56 if (modes > bimodalVal) {
61 return (modes == bimodalVal);
76 size_t hist_size = hist.
getSize();
77 for (first = 0; (first < hist_size) && (hist[static_cast<unsigned char>(first)] == 0); ++first) {
81 for (last = (hist_size - 1); (last > first) && (hist[
static_cast<unsigned char>(last)] == 0); --last) {
90 std::vector<float> S(last + 1);
91 std::vector<float> W(last + 1);
93 S[0] =
static_cast<float>(hist[0]);
95 for (
size_t i = std::max<size_t>(
static_cast<size_t>(1), first); i <= last; ++i) {
96 S[i] = S[i - 1] + hist[
static_cast<unsigned char>(i)];
97 W[i] = W[i - 1] + (i *
static_cast<float>(hist[
static_cast<unsigned char>(i)]));
102 float C =
static_cast<float>(last - first);
103 std::vector<float> Smu((last + 1) - first);
105 size_t smu_size = Smu.size();
106 for (
size_t i = 1; i < smu_size; ++i) {
107 float mu = 1 / (1 + (i / C));
108 Smu[i] = (-mu * std::log(mu)) - ((1 - mu) * std::log(1 - mu));
112 int bestThreshold = 0;
113 float bestEntropy = std::numeric_limits<float>::max();
115 for (
size_t threshold = first; threshold <= last; ++threshold) {
118 for (
size_t i = first; i <= threshold; ++i) {
119 entropy += Smu[
static_cast<size_t>(std::abs(
static_cast<int>(i) - mu))] * hist[
static_cast<unsigned char>(i)];
122 mu =
vpMath::round((W[last] - W[threshold]) / (S[last] - S[threshold]));
123 for (
size_t i = threshold + 1; i <= last; ++i) {
124 entropy += Smu[
static_cast<size_t>(std::abs(
static_cast<int>(i) - mu))] * hist[
static_cast<unsigned char>(i)];
127 if (bestEntropy > entropy) {
128 bestEntropy = entropy;
129 bestThreshold =
static_cast<int>(threshold);
133 return bestThreshold;
138 const unsigned int minSize = 3;
139 if (hist.
getSize() < minSize) {
157 std::vector<float> hist_float(hist.
getSize());
158 unsigned int hist_size = hist.
getSize();
159 for (
unsigned int cpt = 0; cpt < hist_size; ++cpt) {
160 hist_float[cpt] =
static_cast<float>(hist[cpt]);
164 const float nbPtsAverage = 3.;
165 const int maxIter = 10000;
168 size_t hist_float_size_m_1 = hist_float.size() - 1;
169 for (
size_t cpt = 1; cpt < hist_float_size_m_1; ++cpt) {
170 hist_float[cpt] = (hist_float[cpt - 1] + hist_float[cpt] + hist_float[cpt + 1]) / nbPtsAverage;
174 hist_float[0] = (hist_float[0] + hist_float[1]) / 2.0f;
177 const size_t var2 = 2;
178 hist_float[hist_float.size() - 1] = (((hist_float.size() - var2) + hist_float.size()) - 1) / 2.0f;
182 if (iter > maxIter) {
183 std::cerr <<
"Intermodes Threshold not found after " << maxIter <<
" iterations!" << std::endl;
190 size_t hist_float_size_m_1 = hist_float.size() - 1;
191 for (
size_t cpt = 1; cpt < hist_float_size_m_1; ++cpt) {
192 if ((hist_float[cpt - 1] < hist_float[cpt]) && (hist_float[cpt] > hist_float[cpt + 1])) {
194 tt +=
static_cast<int>(cpt);
198 return static_cast<int>(std::floor(tt / 2.0));
207 std::vector<float> cumsum(hist.
getSize(), 0.0f);
208 std::vector<float> sum_ip(hist.
getSize(), 0.0f);
209 cumsum[0] =
static_cast<float>(hist[0]);
211 unsigned int hist_size = hist.
getSize();
212 for (
unsigned int cpt = 1; cpt < hist_size; ++cpt) {
213 sum_ip[cpt] = (cpt *
static_cast<float>(hist[cpt])) + sum_ip[cpt - 1];
214 cumsum[cpt] =
static_cast<float>(hist[cpt]) + cumsum[cpt - 1];
220 float MBT = sum_ip[
static_cast<size_t>(T - 2)] / cumsum[
static_cast<size_t>(T - 2)];
221 float MAT = (sum_ip.back() - sum_ip[
static_cast<size_t>(T - 1)]) / (cumsum.back() - cumsum[
static_cast<size_t>(T - 1)]);
226 while (std::abs(T2 - T) >= 1) {
228 MBT = sum_ip[
static_cast<size_t>(T2 - val_2)] / cumsum[
static_cast<size_t>(T2 - val_2)];
229 MAT = (sum_ip.back() - sum_ip[
static_cast<size_t>(T2 - 1)]) / (cumsum.back() - cumsum[
static_cast<size_t>(T2 - 1)]);
245 unsigned int hist_size = hist.
getSize();
246 for (
unsigned int cpt = 0; cpt < hist_size; ++cpt) {
247 sum_ip += cpt *
static_cast<float>(hist[cpt]);
250 return static_cast<int>(std::floor(sum_ip / imageSize));
260 float sum_ip_all[256];
261 int hist_size =
static_cast<int>(hist.
getSize());
262 for (
int cpt = 0; cpt < hist_size; ++cpt) {
263 mu_T += cpt *
static_cast<float>(hist[cpt]);
264 sum_ip_all[cpt] = mu_T;
268 float w_B = 0.0f, w_F = 0.0f;
270 float max_sigma_b = 0.0f;
273 bool w_f_eq_nul =
false;
275 const int maxCpt = 256;
276 while ((cpt < maxCpt) && (!w_f_eq_nul)) {
278 bool w_b_eq_nul =
vpMath::nul(w_B, std::numeric_limits<float>::epsilon());
281 w_F =
static_cast<int>(imageSize) - w_B;
282 w_f_eq_nul =
vpMath::nul(w_F, std::numeric_limits<float>::epsilon());
286 float mu_B = sum_ip_all[cpt] /
static_cast<float>(w_B);
287 float mu_F = (mu_T - sum_ip_all[cpt]) /
static_cast<float>(w_F);
290 float sigma_b_sqr = w_B * w_F * (mu_B - mu_F) * (mu_B - mu_F);
292 if (sigma_b_sqr >= max_sigma_b) {
294 max_sigma_b = sigma_b_sqr;
313 int left_bound = -1, right_bound = -1, max_idx = -1, max_value = 0;
315 int hist_size =
static_cast<int>(hist.
getSize());
316 for (
int cpt = 0; cpt < hist_size; ++cpt) {
317 if ((left_bound == -1) && (hist[cpt] > 0)) {
318 left_bound =
static_cast<int>(cpt);
321 if ((right_bound == -1) && (hist[
static_cast<int>(hist.
getSize()) - 1 - cpt] > 0)) {
322 right_bound =
static_cast<int>(hist.
getSize()) - 1 - cpt;
325 if (
static_cast<int>(hist[cpt]) > max_value) {
326 max_value =
static_cast<int>(hist[cpt]);
332 left_bound = left_bound > 0 ? (left_bound - 1) : left_bound;
333 right_bound = right_bound < (static_cast<int>(hist.
getSize()) - 1) ? (right_bound + 1) : right_bound;
337 if ((max_idx - left_bound) < (right_bound - max_idx)) {
342 int cpt_right =
static_cast<int>(hist.
getSize()) - 1;
343 for (; cpt_left < cpt_right; ++cpt_left, --cpt_right) {
344 unsigned int temp = hist[cpt_left];
345 hist.
set(cpt_left, hist[cpt_right]);
346 hist.
set(cpt_right, temp);
349 left_bound =
static_cast<int>(hist.
getSize()) - 1 - right_bound;
350 max_idx =
static_cast<int>(hist.
getSize()) - 1 - max_idx;
360 float a =
static_cast<float>(max_value);
361 float b =
static_cast<float>(left_bound - max_idx);
362 float max_dist = 0.0f;
364 for (
int cpt = left_bound + 1; cpt <= max_idx; ++cpt) {
365 float dist = (a * cpt) + (b * hist[cpt]);
367 if (dist > max_dist) {
375 threshold =
static_cast<int>(hist.
getSize()) - 1 - threshold;
382 const unsigned char backgroundValue,
const unsigned char foregroundValue)
421 const unsigned char threshold2 = 255;
422 if (threshold != -1) {
424 vpImageTools::binarise(I,
static_cast<unsigned char>(threshold), threshold2, backgroundValue, foregroundValue,
Class to compute a gray level image histogram.
void set(const unsigned char level, unsigned int value)
unsigned int getSize() const
static bool nul(double x, double threshold=0.001)
static int round(double x)
VISP_EXPORT unsigned char autoThreshold(VISP_NAMESPACE_ADDRESSING vpImage< unsigned char > &I, const vpAutoThresholdMethod &method, const unsigned char backgroundValue=0, const unsigned char foregroundValue=255)
bool isBimodal(const std::vector< float > &hist_float)
int computeThresholdIntermodes(const vpHistogram &hist)
int computeThresholdIsoData(const vpHistogram &hist, unsigned int imageSize)
int computeThresholdMean(const vpHistogram &hist, unsigned int imageSize)
int computeThresholdOtsu(const vpHistogram &hist, unsigned int imageSize)
int computeThresholdTriangle(vpHistogram &hist)
@ AUTO_THRESHOLD_INTERMODES
@ AUTO_THRESHOLD_TRIANGLE
int computeThresholdHuang(const vpHistogram &hist)