21#include <allheaders.h>
24#if defined(USE_OPENCL)
38int OtsuThreshold(
Image src_pix,
int left,
int top,
int width,
int height, std::vector<int> &thresholds,
39 std::vector<int> &hi_values) {
40 int num_channels = pixGetDepth(src_pix) / 8;
43 int best_hi_value = 1;
44 int best_hi_index = 0;
45 bool any_good_hivalue =
false;
46 double best_hi_dist = 0.0;
47 thresholds.resize(num_channels);
48 hi_values.resize(num_channels);
53 std::vector<int> histogramAllChannels(
kHistogramSize * num_channels);
57 if (od.selectedDeviceIsOpenCL() && (num_channels == 1 || num_channels == 4) && top == 0 &&
59 od.HistogramRectOCL(pixGetData(src_pix), num_channels, pixGetWpl(src_pix) * 4, left, top, width,
63 for (
int ch = 0;
ch < num_channels; ++
ch) {
69 int best_t =
OtsuStats(histogram, &H, &best_omega_0);
70 if (best_omega_0 == 0 || best_omega_0 == H) {
77 int hi_value = best_omega_0 < H * 0.5;
78 thresholds[
ch] = best_t;
79 if (best_omega_0 > H * 0.75) {
80 any_good_hivalue =
true;
82 }
else if (best_omega_0 < H * 0.25) {
83 any_good_hivalue =
true;
87 double hi_dist = hi_value ? (H - best_omega_0) : best_omega_0;
88 if (hi_dist > best_hi_dist) {
89 best_hi_dist = hi_dist;
90 best_hi_value = hi_value;
97 for (
int ch = 0;
ch < num_channels; ++
ch) {
105 int best_t =
OtsuStats(histogram, &H, &best_omega_0);
106 if (best_omega_0 == 0 || best_omega_0 == H) {
113 int hi_value = best_omega_0 < H * 0.5;
114 thresholds[
ch] = best_t;
115 if (best_omega_0 > H * 0.75) {
116 any_good_hivalue =
true;
118 }
else if (best_omega_0 < H * 0.25) {
119 any_good_hivalue =
true;
123 double hi_dist = hi_value ? (H - best_omega_0) : best_omega_0;
124 if (hi_dist > best_hi_dist) {
125 best_hi_dist = hi_dist;
126 best_hi_value = hi_value;
135 if (!any_good_hivalue) {
137 hi_values[best_hi_index] = best_hi_value;
148 int num_channels = pixGetDepth(src_pix) / 8;
149 channel =
ClipToRange(channel, 0, num_channels - 1);
150 int bottom = top + height;
152 int src_wpl = pixGetWpl(src_pix);
153 l_uint32 *srcdata = pixGetData(src_pix);
154 for (
int y = top;
y < bottom; ++
y) {
155 const l_uint32 *linedata = srcdata +
y * src_wpl;
156 for (
int x = 0;
x < width; ++
x) {
157 int pixel = GET_DATA_BYTE(linedata, (
x + left) * num_channels + channel);
166int OtsuStats(
const int *histogram,
int *H_out,
int *omega0_out) {
171 mu_T +=
static_cast<double>(
i) * histogram[
i];
177 int omega_0, omega_1;
178 int best_omega_0 = 0;
179 double best_sig_sq_B = 0.0;
180 double mu_0, mu_1, mu_t;
184 omega_0 += histogram[t];
185 mu_t += t *
static_cast<double>(histogram[t]);
189 omega_1 = H - omega_0;
193 mu_0 = mu_t / omega_0;
194 mu_1 = (mu_T - mu_t) / omega_1;
195 double sig_sq_B = mu_1 - mu_0;
196 sig_sq_B *= sig_sq_B * omega_0 * omega_1;
197 if (best_t < 0 || sig_sq_B > best_sig_sq_B) {
198 best_sig_sq_B = sig_sq_B;
200 best_omega_0 = omega_0;
203 if (H_out !=
nullptr) {
206 if (omega0_out !=
nullptr) {
207 *omega0_out = best_omega_0;
T ClipToRange(const T &x, const T &lower_bound, const T &upper_bound)
void HistogramRect(Image src_pix, int channel, int left, int top, int width, int height, int *histogram)
int OtsuStats(const int *histogram, int *H_out, int *omega0_out)
int OtsuThreshold(Image src_pix, int left, int top, int width, int height, std::vector< int > &thresholds, std::vector< int > &hi_values)