Why is my conical/angle gradient image distorted?

Tags: , , , ,

I’m currently trying to create a conical gradient, and it kind of works. However, it doesn’t look quite right and I can’t wrap my hand around to why:

sample output image

The line that goes up from the center is slightly angled to the right and at the bottom there is a visible (not too noticable) line.

Code is as follows:

import math
import numpy
from PIL import Image

def newImg(w,h):
    data = numpy.zeros((h, w, 3), dtype=numpy.uint8)
    for y in range(h):
        for x in range(w):
            p = [y,x]
            center = [h/2,w/2]
            angle = math.atan2(center[1]-p[1], center[0]-p[0])
            data[y,x] = angle*(255/math.pi/2)

    return data

image = Image.fromarray(newImg(2000,2000))

Oh, and another thing is that NumPy/Pillow swaps width and height, but that’s something I can work around. Would be nice to have an explanation for that, though.


The problem is that you get negative values for angle from math.atan2, since its value range is -pi ... pi. Following, you get negative values in data causing integer underflows (since the dtype of data is numpy.uint8), which finally lead to numerical errors.

To prevent that, just add math.pi to each angle:

angle = math.atan2(center[1]-p[1], center[0]-p[0]) + math.pi

So, the value range becomes 0 ... 2*pi for angle, and properly 0 ... 255 for data. Of course, your gradient image is rotated by 180┬░ then, but rotating the final image shouldn’t be a problem, right?

The output image:


Now, to further improve your code, get rid of the two (slooooow) loops, and use the vectorization abilities of NumPy:

def newImg(w,h):
    x, y = numpy.meshgrid(range(w), range(h))
    x = w/2 - x
    y = h/2 - y
    angles = numpy.arctan2(y, x) + numpy.pi
    data = (angles * (255 / numpy.pi / 2)).astype(numpy.uint8)

    return data

There’s a heavy speed-up for the 2000 x 2000 image, and the output image is identical.

System information
Platform:      Windows-10-10.0.16299-SP0
Python:        3.9.1
NumPy:         1.20.1
Pillow:        8.1.0

Source: stackoverflow