我想将图像放置在背景图像之上,并使用 Python 在图像上应用“斜角/浮雕”效果。我尝试使用 PIL 库,但也欢迎对其他库提出建议。
它应该是这样的:
我有以下代码:
from PIL import Image
from PIL import ImageFilter
img = Image.open('./image.jpeg', 'r')
# this doesn't do what I want...
img = img .filter(ImageFilter.EMBOSS)
background = Image.open('./bg.png', 'r')
background.paste(img)
我使用 Affinity Photo 作为示例图像。在 Photoshop 中应该是差不多的。以下是我使用的设置:
我仍然不知道如何在 python 中执行此操作,但我找到了一种方法,结合使用批处理作业和 Affinity Photo 中的宏功能。
此处描述了如何启动批处理作业:http://www.millermattson.com/blog/batch-processing-with-affinity-photo/
我在谷歌搜索试图弄清楚如何使用 PIL 对文本进行斜角和浮雕时发现了这个问题。这花了几个小时的时间,但我对解决方案非常满意并想分享:
def draw_embossed_text(image, text, font, position, fill, highlight, shadow):
"""
Create an embossed text effect on an image
:param image: PIL Image object to write on
:param text: The text to write
:param font: The ImageFont for the text
:param position: Tuple (x, y) of the position to write the text
:param fill: The color of the text as an RGB tuple
:param highlight: Highlight color as an RGB tuple
:param shadow: Shadow color as an RGB tuple
:return: Modified PIL Image object with embossed text
"""
# Convert image to RGBA
image = image.convert('RGBA')
# Create text mask
text_mask = Image.new('L', image.size, 0)
draw = ImageDraw.Draw(text_mask)
draw.text(position, text, font=font, fill=255)
# Create a layer for the fill color text
fill_text_layer = Image.new('RGBA', image.size, (0, 0, 0, 0))
fill_draw = ImageDraw.Draw(fill_text_layer)
fill_draw.text(position, text, font=font, fill=fill + (255,))
# Apply emboss filter to the text mask
embossed_mask = text_mask.filter(ImageFilter.EMBOSS)
embossed_mask = ImageOps.autocontrast(embossed_mask).filter(ImageFilter.GaussianBlur(3))
# Create a layer for the embossed effect using the mask
embossed_layer = Image.new('RGBA', image.size, fill + (0,))
embossed_layer.putalpha(embossed_mask)
# Convert embossed layer to NumPy array for pixel manipulation
embossed_array = np.array(embossed_layer)
alpha_channel = embossed_array[:, :, 3]
# Determine highlight and shadow areas
highlight_area = alpha_channel > 128
shadow_area = alpha_channel < 128
# Apply highlight and shadow
embossed_array[highlight_area, :3] = highlight
embossed_array[shadow_area, :3] = shadow
# Adjust intensity
intensity = np.minimum(np.minimum(np.abs(alpha_channel - 128), np.abs(128 - alpha_channel)) * 2, 255)
embossed_array[:,:,3] = np.where(highlight_area | shadow_area, intensity, 0)
# Convert back to PIL Image
embossed_layer = Image.fromarray(embossed_array)
# Composite the embossed text onto the original image
image_with_text = Image.alpha_composite(image, fill_text_layer)
final_image = Image.alpha_composite(image_with_text, embossed_layer)
return final_image