def halftone(cmyk, size, angles, fill, sharpness):
"""
Generates a halftone image from a cmyk image
Args:
cmyk (numpy array): 0.0-1.0 r x c x 4 image
size (int): half size of the averaging kernel in pixels
angles (list of float): 4 angles for the relative rotation of each channel
Returns:
numpy array: 0.0-1.0 r x c x 4 halftoned image
"""
halftone_image = np.zeros(cmyk.shape)
for i, (channel, angle) in enumerate(zip(np.rollaxis(cmyk, 2), angles)):
# total width of the kernel
s = 2 * size + 1
# rotate the image to eliminate overlap between the channels
rotated = rotate(channel, angle, reshape=True, prefilter=False, order=1)
# apply a gaussian filter to average over a the region of the kernel
averaged = gaussian_filter(rotated, size)
# find the central value of the filtered image; this is the average intensity in the region
halftone_weights = averaged[size::s, size::s]
# tile the weight image with the average intensity value
halftone_weights = np.repeat(np.repeat(halftone_weights, s, 0), s, 1)
halftone_weights = resize(halftone_weights, rotated.shape)
# TODO: consider using sigma to scale with magnitude
# create a 2D gaussian kernel that will be the "dot"; normalize it to be 1.0 in the center
kernel = gauss_kernel(size, sigma=fill*size)
# Apply the sharpness multiplier and clip the kernel to 1.0
kernel *= sharpness / np.max(kernel)
kernel = np.clip(kernel, 0.0, 1.0)
# tile the kernel across the image
num_kernels = np.array(rotated.shape) / s + 1
tiled_kernel = np.tile(kernel, num_kernels)
tiled_kernel = resize(tiled_kernel, rotated.shape)
# multiply the kernel image with the weights to generate the halftone image
halftone = tiled_kernel * halftone_weights
# rotate the image back to zero
halftone = rotate(halftone, -angle, prefilter=False, order=1)
# crop the image to the original size
halftone = crop_center(halftone, channel.shape)
# add this chanel to the full cmyk image
halftone_image[:,:,i] = halftone
# Image.fromarray(halftone*255).show()
# Image.fromarray(cmyk_to_rgb(halftone_image)).show()
return halftone_image
评论列表
文章目录