note.nkmk.me

Generate gradient image with Python, NumPy

Posted: 2019-05-14 / Tags: Python, NumPy, Image Processing

By treating images as NumPy array ndarray, you can manipulate existing images or generate new images using NumPy functions.

This article introduces an example of generating a gradient image with NumPy functions.

  • np.linspace() and np.tile()
  • Sample code to generate a gradient image
Sponsored Link

np.linspace() and np.tile()

Although various methods are conceivable, in this article, create a gradient image by the following flow.

  • Generate 1D arrays that increase or decrease at regular intervals with numpy.linspace()
  • Arrange it in 2D with numpy.tile()

The gradient direction is vertical or horizontal only. It does not support diagonal or radial (round).

np.linspace()

np.linspace() is a function that returns an equally spaced 1D array, given the start value start, the end value stop, and the number of samples num.

Unlike range() and np.arange(), np.linspace() is convenient because it calculates intervals (steps) automatically.

import numpy as np

print(np.linspace(0, 10, 3))
# [ 0.  5. 10.]

print(np.linspace(0, 10, 4))
# [ 0.          3.33333333  6.66666667 10.        ]

print(np.linspace(0, 10, 5))
# [ 0.   2.5  5.   7.5 10. ]

It will handle properly if start > stop.

print(np.linspace(10, 0, 5))
# [10.   7.5  5.   2.5  0. ]

See the following article for details of np.arange() and np.linspace().

np.tile()

np.tile() is a function that arranges the array vertically and horizontally.

It is useful for creating the array that repeat patterns.

Set the original array and the number of iterations. When arranging in two dimensions, the number of repetitions is (the number of repetitions of rows (vertical), the number of repetitions of columns (horizontal)).

import numpy as np

a = np.array([0, 1, 2, 3])

print(np.tile(a, 2))
# [0 1 2 3 0 1 2 3]

print(np.tile(a, (3, 2)))
# [[0 1 2 3 0 1 2 3]
#  [0 1 2 3 0 1 2 3]
#  [0 1 2 3 0 1 2 3]]

print(np.tile(a, (2, 1)))
# [[0 1 2 3]
#  [0 1 2 3]]

2D arrays can be handled in the same way.

a = np.array([[11, 12], [21, 22]])

print(np.tile(a, 2))
# [[11 12 11 12]
#  [21 22 21 22]]

print(np.tile(a, (3, 2)))
# [[11 12 11 12]
#  [21 22 21 22]
#  [11 12 11 12]
#  [21 22 21 22]
#  [11 12 11 12]
#  [21 22 21 22]]

print(np.tile(a, (2, 1)))
# [[11 12]
#  [21 22]
#  [11 12]
#  [21 22]]

See the following article for more information on np.tile().

Sample code to generate a gradient image

Define a function that generates a 2D ndarray that increases or decreases at equal intervals in the vertical or horizontal direction. This ndarray corresponds to a monochrome (grayscale) gradient image.

The value changes in the horizontal direction when is_horizontal is True, and in the vertical direction when False. For vertical orientation, use .T to create a transposed matrix.

def get_gradient_2d(start, stop, width, height, is_horizontal):
    if is_horizontal:
        return np.tile(np.linspace(start, stop, width), (height, 1))
    else:
        return np.tile(np.linspace(start, stop, height), (width, 1)).T

Expand this to three dimensions. Set start, stop, and is_horizontal for each color in a list, and create a gradient image for each channel with the function for 2D.

def get_gradient_3d(width, height, start_list, stop_list, is_horizontal_list):
    result = np.zeros((height, width, len(start_list)), dtype=np.float)

    for i, (start, stop, is_horizontal) in enumerate(zip(start_list, stop_list, is_horizontal_list)):
        result[:, :, i] = get_gradient_2d(start, stop, width, height, is_horizontal)

    return result

An example of generating and saving a gradient image is as follows.

from PIL import Image

array = get_gradient_3d(512, 256, (0, 0, 0), (255, 255, 255), (True, True, True))
Image.fromarray(np.uint8(array)).save('data/dst/gray_gradient_h.jpg', quality=95)

NumPy gray gradient image horizontal

array = get_gradient_3d(512, 256, (0, 0, 0), (255, 255, 255), (False, False, False))
Image.fromarray(np.uint8(array)).save('data/dst/gray_gradient_v.jpg', quality=95)

NumPy gray gradient image vertical

It is also possible to change the gradient direction for each RGB.

array = get_gradient_3d(512, 256, (0, 0, 192), (255, 255, 64), (True, False, False))
Image.fromarray(np.uint8(array)).save('data/dst/color_gradient.jpg', quality=95)

NumPy color gradient image

Sponsored Link
Share

Related Categories

Related Articles