0

Not completely sure what to call this problem but I will try my best to explain it here.

I have the coordinates of a line I want to draw onto a numpy array. However, I don't just want a simple line, but a thick line where I can specify the falloff (brightness with distance from the line) with a curve or mathematic function. For example, I might want to have a gaussian falloff, which would look something similar to the example below where a gaussian blur was applied to the image.

Simple line drawn with the coordinates I have on the left, and an example of the line I would like to have on the right

However, using blur filters does not allow the flexibility in functions I would like and does not enable precise control of the falloff (for example, when I want points on the line to have exactly value 1.0 and points further than say 10 pixels away to be 0.0).

I have attempted to solve this problem by creating the falloff pattern for a point, and then drawing that pattern into a new numpy channel for every point of the line, before merging them via the max function. This works but is too slow.

Is there a more efficient way to draw such a line from my input coordinates?

  • You could use open cv to draw. You can give it a thickness and it does the blurring I believe. See https://stackoverflow.com/a/18633964/2640045 – Lukas S Oct 04 '21 at 14:07
  • Thanks @user2640045, but as explained in the question, blurring does not give enough control. For example, if I want a falloff with multiple maxima this is not possible by the blurring method. – a crazy Minion Oct 04 '21 at 14:45
  • 1
    @acrazyMinion can you express your operation as a linear space covariate system? can you create a point spread function that maps a single point to the manifold you want to draw? if you have a filter that does that with a single point, you can just use numpy's convolution function to compute your desired result – yann ziselman Oct 04 '21 at 15:04

1 Answers1

0

The solution I came up with is to make use of dilations. This method is more general and can be applied to any polygonal shape or binary mask.

  1. Rasterize geometry the simple way first. For points set the corresponding pixel; for lines draw 1 pixel thick lines with library function from opencv or similar; for polygons draw the boundary or fill the polygon with opencv functions. This results in the initial mask with value 1 on the lines.
  2. Iteratively apply dilations to this mask. This grows the mask pixel by pixel. Set the strength of the new mask according to an arbitrary falloff function.

The dilation operation is available in opencv. Alternatively, it can efficiently be implemented as a simple convolution with boolean matrices, which can then run on GPU devices.

An example of the results can be seen with the polygonal input:

enter image description here

Exponential falloff:

enter image description here

Sinusoidal falloff:

enter image description here