Trying to trace an image using Fourier Transformations, but the output is upside down - why?

48 Views Asked by At

newbie here. I've watched a couple videos on Fourier Transformations(mainly 3b1b's), and made my own implementation with Manim. Initially, I fed in the svg of a heart and the output was as expected. Traced out the image correctly. However, when I fed an svg of the letter pi, the output is upside down.

Output Input svg

I have two sets of "vectors", the one with positive exponents(that rotate counter-clockwise), and the other with negative(clockwise). Hence I need to separate out the coefficients(cpos and cneg).

Here are the relevant bits of code:

  1. This generates the coefficients given an svg that contains only one path. The loops are essentially numerical integration of:

$$\int_0^1 f(t) e^{-2n{\pi}it}\ dt = c_n$$

The 1e-4 is present to scale the coefficients down so the output doesn't go out of my viewport when rendering.

SAMPLE = 1000
N=10   # proportional to the number of vectors if you will
filename = "pi"
paths, attributes = svg2paths(f'{filename}.svg')
if len(paths) == 1: 
    path = paths[0]

def point_t(t):
    return path.point(t)

for i in range(N):
    sum=0
    for j in range(SAMPLE):
        sum += 1e-4*point_t(j/SAMPLE)*cmath.exp(i*-2*cmath.pi*1j*j/SAMPLE)
        
    cpos.append(sum)
    
for i in range(N):
    sum=0
    for j in range(SAMPLE):
        sum += 1e-4*point_t(j/SAMPLE)*cmath.exp(i*2*cmath.pi*1j*j/SAMPLE)
        
    cneg.append(sum)
        
print(cpos)
print(cneg)
  1. Rendering the output

This piece of code will generate the vectors, joined tip to end. Here, tracker.get_value() is essentially the varying t. The initial two vectors is the constant vector. The for loop first adds the negative rotation vector, then positive just to make the output a little more chaotic, there's no real reason to do it this way. c_pos[] and c_neg[] are lists that contain the coefficients starting with c[0] = c0. The first elements of both c_pos and c_neg are the coefficients for the constant vector.

The function e2m() takes in in numbers of the form re^i*theta and returns a list [rcostheta, rsintheta, 0]. The library requires the start and end to be in the form of a list.

def create_vecs(n):
    
    arrows_pos.append(Arrow(start=ORIGIN, end=e2m(c_pos[0]*cmath.exp(0*2*PI*1j*tracker.get_value())), buff=0))
    arrows_neg.append(Arrow(start=ORIGIN, end=e2m(c_neg[0]*cmath.exp(0*2*PI*1j*tracker.get_value())), buff=0))
    self.add(arrows_pos[0])

    for i in range(1, n):
        arrows_pos.append(Arrow(start=arrows_neg[i-1].get_end(), end=arrows_neg[i-1].get_end() + e2m(c_pos[i]*cmath.exp(float(i)*2*PI*1j*tracker.get_value())), buff=0))
        self.add(arrows_pos[i])
        
        arrows_neg.append(Arrow(start=arrows_pos[i].get_end(), end=arrows_pos[i].get_end() + e2m(c_neg[i]*cmath.exp(-float(i)*2*PI*1j*tracker.get_value())), buff=0))
        self.add(arrows_neg[i])

--

Is there anything wrong with the way I compute stuff? Why is my output upside down, and how can I fix this? Thank you for your time!