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:
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)) image.save('test.png') image.show()
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.
Advertisement
Answer
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 ----------------------------------------