Is there a name for the following problem? Is there a measure of quality of a given solution? How can we even define what a proper solution is?
Context: I want to detect long lines (most lines over 1000 pixel long) in an image. It is known that most of the lines have similar alignment. To detect those I use the Standard Hough Transform. To detect long lines I need a high angle resolution of the accumulator. Now the idea is not to use an equidistant partition of the angle axis but to create a new partition based on the number of votes for each angle.
The Problem: Given weights $$a_0, \ldots, a_{n-1} \in [0,1] \text{ with } \sum_{k=0}^{n-1}a_k = 1$$ which correspond to the equidistant partition of the interval $[0,1[$ $$0, \frac{1}{n}, \frac{2}{n}, ..., \frac{n-1}{n},$$ return a new partition with less or equal elements which is "finer" around points with larger weights and "coarser" around points with smaller weights. E.g. given the weights $(0.75, 0, 0, 0.25)$ on the partition $(0, 0.25, 0.5, 0.75)$ the result should be a new partition like $(-0.083, 0.0, 0.083, 0.75)$. As $0$ seems to be a point of interest there are three points near it which reflects that.
My solution: The idea is to treat the vector of weights as a density function and to use the quantile function of its cumulative distribution function (cdf).
Example: Given the weights $(0, 0.5, 0, 0.5, 0)$ we construct the density function:
Then the cdf looks like this:
Now we shift the given equidistant partition by $+1/(2n) = 1/10$ and put its values into the quantile function, i.e. we put those values on the $y$-axis and search for corresponding $x$-values of the cdf as marked by the blue lines. $y=0.5$ is omitted since it "cannot decide" which peak it contributes to. The so obtained $x$-values are shifted by $-1/(2n) = -1/10$ and returned as the new partition. The returned partition in this example is $(0.14, 0.22, 0.58, 0.66)$.
Here is a C++ function which performes those tasks, where the vector "weights" represents the input weights and "sample" contains the new partition after execution:
#include <vector>
using std::vector;
void weighted_partition(vector<double>& sample, const vector<double>& weights) {
const int n = (int)weights.size();
double y;
double F = 0.0;
int i = 0;
for (int j = 1; j < 2*n; j += 2) {
y = (double)j/(2*n);
while (F < y) {
F += weights[i];
++i;
}
if (F == y) {
continue;
}
--i;
F -= weights[i];
sample.push_back((y - F + weights[i] * i) / (weights[i] * n) - 1.0/(2.0 * n));
}
}
This algorithm seems to return solutions which are intuitively correct but how can you define "correct"?