-
Notifications
You must be signed in to change notification settings - Fork 0
/
otsu.c
52 lines (37 loc) · 1.5 KB
/
otsu.c
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
#include "../include/thresholding/otsu.h"
#include "../include/logging.h"
#include "../include/smoothing/grayscale.h"
#include "../include/thresholding/global.h"
#include <assert.h>
#include <math.h>
#include <stdio.h>
#define GRAYSCALE 256
void cv_apply_otsu_threshold(Image *img) {
cv_apply_grayscale(img);
int imgLength = img->width * img->height * img->channels;
int histogram[GRAYSCALE] = {0};
for (int i = 0; i < imgLength; i++) {
histogram[img->bytes[i]]++;
}
float normHistogram[GRAYSCALE] = {0};
for (int i = 0; i < GRAYSCALE; i++) {
normHistogram[i] = (float)histogram[i] / imgLength;
}
float cumulativeSum = normHistogram[0], cumulativeMean = 0.0;
float globalMean = 0.0, classVariance = 0.0, maxVariance = 0.0;
int optimalThreshold = 0;
for (int i = 0; i < GRAYSCALE; i++) {
cumulativeSum += normHistogram[i];
cumulativeMean += i * normHistogram[i];
globalMean = cumulativeMean;
float mean1 = cumulativeMean / cumulativeSum,
mean2 = (globalMean - cumulativeMean) / (1 - cumulativeSum);
classVariance = cumulativeSum * (1 - cumulativeSum) * (mean1 - mean2) * (mean1 - mean2);
if (classVariance > maxVariance) {
maxVariance = classVariance;
optimalThreshold = i;
}
}
CV_INFO("Applying optimal threshold of %d\n", optimalThreshold);
cv_apply_global_threshold(img, optimalThreshold);
}