39 #include <visp3/core/vpHistogram.h>
40 #include <visp3/core/vpImageTools.h>
41 #include <visp3/imgproc/vpImgproc.h>
45 bool isBimodal(
const std::vector<float> &hist_float)
49 size_t hist_float_size_m_1 = hist_float.size() - 1;
50 for (
size_t cpt = 1; cpt < hist_float_size_m_1; ++cpt) {
51 if ((hist_float[cpt - 1] < hist_float[cpt]) && (hist_float[cpt] > hist_float[cpt + 1])) {
75 size_t hist_size = hist.
getSize();
76 for (first = 0; (first < hist_size) && (hist[static_cast<unsigned char>(first)] == 0); ++first) {
80 for (last = (hist_size - 1); (last > first) && (hist[
static_cast<unsigned char>(last)] == 0); --last) {
89 std::vector<float> S(last + 1);
90 std::vector<float> W(last + 1);
92 S[0] =
static_cast<float>(hist[0]);
94 for (
size_t i = std::max<size_t>(
static_cast<size_t>(1), first); i <= last; ++i) {
95 S[i] = S[i - 1] + hist[
static_cast<unsigned char>(i)];
96 W[i] = W[i - 1] + (i *
static_cast<float>(hist[
static_cast<unsigned char>(i)]));
101 float C =
static_cast<float>(last - first);
102 std::vector<float> Smu((last + 1) - first);
104 size_t smu_size = Smu.size();
105 for (
size_t i = 1; i < smu_size; ++i) {
106 float mu = 1 / (1 + (i / C));
107 Smu[i] = (-mu * std::log(mu)) - ((1 - mu) * std::log(1 - mu));
111 int bestThreshold = 0;
112 float bestEntropy = std::numeric_limits<float>::max();
114 for (
size_t threshold = first; threshold <= last; ++threshold) {
117 for (
size_t i = first; i <= threshold; ++i) {
118 entropy += Smu[
static_cast<size_t>(std::abs(
static_cast<int>(i) - mu))] * hist[
static_cast<unsigned char>(i)];
121 mu =
vpMath::round((W[last] - W[threshold]) / (S[last] - S[threshold]));
122 for (
size_t i = threshold + 1; i <= last; ++i) {
123 entropy += Smu[
static_cast<size_t>(std::abs(
static_cast<int>(i) - mu))] * hist[
static_cast<unsigned char>(i)];
126 if (bestEntropy > entropy) {
127 bestEntropy = entropy;
128 bestThreshold =
static_cast<int>(threshold);
132 return bestThreshold;
135 int computeThresholdIntermodes(
const vpHistogram &hist)
155 std::vector<float> hist_float(hist.
getSize());
156 unsigned int hist_size = hist.
getSize();
157 for (
unsigned int cpt = 0; cpt < hist_size; ++cpt) {
158 hist_float[cpt] =
static_cast<float>(hist[cpt]);
162 while (!isBimodal(hist_float)) {
164 size_t hist_float_size_m_1 = hist_float.size() - 1;
165 for (
size_t cpt = 1; cpt < hist_float_size_m_1; ++cpt) {
166 hist_float[cpt] = (hist_float[cpt - 1] + hist_float[cpt] + hist_float[cpt + 1]) / 3;
170 hist_float[0] = (hist_float[0] + hist_float[1]) / 2.0f;
173 hist_float[hist_float.size() - 1] = (((hist_float.size() - 2) + hist_float.size()) - 1) / 2.0f;
178 std::cerr <<
"Intermodes Threshold not found after 10000 iterations!" << std::endl;
185 size_t hist_float_size_m_1 = hist_float.size() - 1;
186 for (
size_t cpt = 1; cpt < hist_float_size_m_1; ++cpt) {
187 if ((hist_float[cpt - 1] < hist_float[cpt]) && (hist_float[cpt] > hist_float[cpt + 1])) {
189 tt +=
static_cast<int>(cpt);
193 return static_cast<int>(std::floor(tt / 2.0));
196 int computeThresholdIsoData(
const vpHistogram &hist,
unsigned int imageSize)
202 std::vector<float> cumsum(hist.
getSize(), 0.0f);
203 std::vector<float> sum_ip(hist.
getSize(), 0.0f);
204 cumsum[0] =
static_cast<float>(hist[0]);
206 unsigned int hist_size = hist.
getSize();
207 for (
unsigned int cpt = 1; cpt < hist_size; ++cpt) {
208 sum_ip[cpt] = (cpt *
static_cast<float>(hist[cpt])) + sum_ip[cpt - 1];
209 cumsum[cpt] =
static_cast<float>(hist[cpt]) + cumsum[cpt - 1];
215 float MBT = sum_ip[
static_cast<size_t>(T - 2)] / cumsum[
static_cast<size_t>(T - 2)];
216 float MAT = (sum_ip.back() - sum_ip[
static_cast<size_t>(T - 1)]) / (cumsum.back() - cumsum[
static_cast<size_t>(T - 1)]);
221 while (std::abs(T2 - T) >= 1) {
222 MBT = sum_ip[
static_cast<size_t>(T2 - 2)] / cumsum[
static_cast<size_t>(T2 - 2)];
223 MAT = (sum_ip.back() - sum_ip[
static_cast<size_t>(T2 - 1)]) / (cumsum.back() - cumsum[
static_cast<size_t>(T2 - 1)]);
233 int computeThresholdMean(
const vpHistogram &hist,
unsigned int imageSize)
239 unsigned int hist_size = hist.
getSize();
240 for (
unsigned int cpt = 0; cpt < hist_size; ++cpt) {
241 sum_ip += cpt *
static_cast<float>(hist[cpt]);
244 return static_cast<int>(std::floor(sum_ip / imageSize));
247 int computeThresholdOtsu(
const vpHistogram &hist,
unsigned int imageSize)
254 float sum_ip_all[256];
255 int hist_size =
static_cast<int>(hist.
getSize());
256 for (
int cpt = 0; cpt < hist_size; ++cpt) {
257 mu_T += cpt *
static_cast<float>(hist[cpt]);
258 sum_ip_all[cpt] = mu_T;
262 float w_B = 0.0f, w_F = 0.0f;
264 float max_sigma_b = 0.0f;
267 for (
int cpt = 0; cpt < 256; ++cpt) {
269 if (
vpMath::nul(w_B, std::numeric_limits<float>::epsilon())) {
273 w_F =
static_cast<int>(imageSize) - w_B;
274 if (
vpMath::nul(w_F, std::numeric_limits<float>::epsilon())) {
279 float mu_B = sum_ip_all[cpt] /
static_cast<float>(w_B);
280 float mu_F = (mu_T - sum_ip_all[cpt]) /
static_cast<float>(w_F);
283 float sigma_b_sqr = w_B * w_F * (mu_B - mu_F) * (mu_B - mu_F);
285 if (sigma_b_sqr >= max_sigma_b) {
287 max_sigma_b = sigma_b_sqr;
302 int left_bound = -1, right_bound = -1, max_idx = -1, max_value = 0;
304 int hist_size =
static_cast<int>(hist.
getSize());
305 for (
int cpt = 0; cpt < hist_size; ++cpt) {
306 if ((left_bound == -1) && (hist[cpt] > 0)) {
307 left_bound =
static_cast<int>(cpt);
310 if ((right_bound == -1) && (hist[
static_cast<int>(hist.
getSize()) - 1 - cpt] > 0)) {
311 right_bound =
static_cast<int>(hist.
getSize()) - 1 - cpt;
314 if (
static_cast<int>(hist[cpt]) > max_value) {
315 max_value =
static_cast<int>(hist[cpt]);
321 left_bound = left_bound > 0 ? left_bound - 1 : left_bound;
322 right_bound = right_bound < static_cast<int>(hist.
getSize()) - 1 ? right_bound + 1 : right_bound;
326 if ((max_idx - left_bound) < (right_bound - max_idx)) {
331 int cpt_right =
static_cast<int>(hist.
getSize()) - 1;
332 for (; cpt_left < cpt_right; ++cpt_left, --cpt_right) {
333 unsigned int temp = hist[cpt_left];
334 hist.
set(cpt_left, hist[cpt_right]);
335 hist.
set(cpt_right, temp);
338 left_bound =
static_cast<int>(hist.
getSize()) - 1 - right_bound;
339 max_idx =
static_cast<int>(hist.
getSize()) - 1 - max_idx;
349 float a =
static_cast<float>(max_value);
350 float b =
static_cast<float>(left_bound - max_idx);
351 float max_dist = 0.0f;
353 for (
int cpt = left_bound + 1; cpt <= max_idx; ++cpt) {
354 float dist = (a * cpt) + (b * hist[cpt]);
356 if (dist > max_dist) {
364 threshold =
static_cast<int>(hist.
getSize()) - 1 - threshold;
374 const unsigned char backgroundValue,
const unsigned char foregroundValue)
386 threshold = computeThresholdHuang(histogram);
390 threshold = computeThresholdIntermodes(histogram);
394 threshold = computeThresholdIsoData(histogram, I.
getSize());
398 threshold = computeThresholdMean(histogram, I.
getSize());
402 threshold = computeThresholdOtsu(histogram, I.
getSize());
406 threshold = computeThresholdTriangle(histogram);
413 if (threshold != -1) {
415 vpImageTools::binarise(I,
static_cast<unsigned char>(threshold),
static_cast<unsigned char>(255), 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(vpImage< unsigned char > &I, const vp::vpAutoThresholdMethod &method, const unsigned char backgroundValue=0, const unsigned char foregroundValue=255)
@ AUTO_THRESHOLD_INTERMODES
@ AUTO_THRESHOLD_TRIANGLE