Avoid code duplication
There's duplicated code in otsu_threshold() because normalize_histogram() returns completely different types depending on ElementT. There are several ways to avoid this:
What about non-integral element types?
Your function only deals with images with integer pixel values. However, what if ElementT is float? If you think that floating point images would result in huge histograms, please realize that std::uint32_t has just as many possible values as a float does. I think your code will handle floats just fine if you just remove the constraint.
But this also brings me to the following:
Consider that the histogram might be huge
Your algorithm is \$O(N^2)\$ where \$N\$ is the size of the histogram. For 8-bit images, that's totally fine. For 16-bit images, it will execute the code in the inner loops \$2^32\$ times, regardless of the image size.
You can save some time by realizing that you don't need to recompute all of w_background/w_foreground/etc each time, as only one element is added/removed from the sums each iteration of the outer loop.
For 32-bit images, your code might actually be more or less efficient, depending on the number of distinct pixel values. Still, you must consider that the size of the histogram might be equal to the total number of pixels in the image, if each pixel has a unique value.
There several possible approaches you can take for dealing with huge histograms:
- Just limit the number of histogram bins. This might result in a slightly optimal threshold value.
- Use a heuristic or bisection to find the right value in less amount of time.