What type of cost function do you have (if I am reading from your code it is just the summation of pixels which do not fall outside the white matter?)? If it is smooth and continuous, you could try gradient descent to find the minimum (since yours looks discrete, though, is there a way for you to approximate gradient descent?). This should function more efficiently than a random walk.
If maintaining randomness is important, then the best way to do that without suffering a lot of re-draws is to re-normalize the range of distribution you can select from. If I understand correctly, you have the white matter mask already, so one method that should allow you to do this would be:
1.) Assign a probability to all white matter pixels based on a Gaussian centered at your current location
2.) Re-normalize those probabilities so they sum to 1
3.) Pull a random number from a uniform distribution and find which pixel it corresponds to
4.) Move your control point there
So, for example, if you have four possible white matter pixels you could move to with probability 0.1, 0.17, 0.2, and 0.23
, at respective locations (x1,y1), (x2,y2), (x3, y3), (x4, y4)
with all other probable pixels (based on your Gaussian random step) being non-white matter pixels that will force you to re-draw, then you would re-scale your probabilities by dividing by their sum (0.7
in this case). Then pull a random number from a uniform distribution (let's say you pulled 0.3
). This would correspond to the second point (x2, y2)
based on the re-normalized probabilities, and you would move your control point there.
As you can see, this has a fair number of computational steps to perform, but will ensure you only pull one random target to update; any improvement in performance will therefore depend on the relative cost of these extra computations versus how often you are actually re-sampling. I also wrote this up pretty fast, so you might be able to come up with a more efficient way to limit the scope of your random selection to only the good pixels.