Draw differentiable rectangle?

Is there any way to draw a rectangle on a canvas in a way that is differentiable (i.e. can be backproped through)?

I am guessing something like would not be possible since indexing breaks backprop:

def draw_rect(canvas_tensor, x0, y0, x1, y1, color):
    canvas_tensor[..., y0:y1, x0:x1] = color

(where all parameters are trainable parameters)

some hints to help you think:

  1. think first in terms of a circle ( it is simpler and has many of the similar requirements as this)
  2. the gaussian function in 2d with a diagonal covariance matrix, and equal x and y variances makes circles. the mean and variance are the parameters for this.
  3. the differentiable color is the easiest part of the problem that i guess you’ll get quickly.

if you can solve the circle problem, i think you might get ideas for the rectangle.

Thanks for the pointers!

I will try this out and see if I can extend it to rectangles as well. If nothing else, it might be possible to add circles in a manner similar to a fourier transform.

I will report back during the week.

I am still having some problems with this.
Even in the case of drawing circles, how would I actually put them on a canvas?

Say that I start of with a blank canvas = torch.zeros([1, 1, 256, 256], requires_grad=True)
Given a covariance matrix (or a mean and a variance), what torch operation could translate/plot these into pixels on my canvas?

I managed to draw a circle at least!

s = 256

canvas = torch.zeros([1, 1, s, s])

ss = torch.linspace(0, 1, s)
x, y = torch.meshgrid(ss, ss)

px = 0.5
py = 0.5
w = 0.5
h = 0.5

image = 1 - 2*(((x - px)**2) / w**2 + ((y - py)**2) / h**2)
image2 = image.clamp(0, 1)
canvas[0, 0] = image2

Tomorrow it’s time for rectangles.

1 Like

I updated my previous code for a circle to draw a squircle instead.

It is close enough to a square.

s = 256

canvas = torch.zeros([1, 1, s, s])

ss = torch.linspace(0, 1, s)
x, y = torch.meshgrid(ss, ss)

px = 0.5
py = 0.5
w = 0.5
h = 0.5
exp = 10

image = 1 - 2*(abs((x - px)/w)**exp + abs((y - py)/h)**exp)
image2 = image.clamp(0, 1)
canvas[0, 0] = image2