[英]Image embossing in Python with PIL — adding depth, azimuth, etc
我正在尝试使用PIL压印图像。
PIL提供了一种压印图像的基本方法(使用ImageFilter.EMBOSS
)。
在像GIMP这样的图像编辑软件包中,您可以更改此浮雕图像中的方位角,深度和高程等参数。
如何用PIL做到这一点? 至少我想调整浮雕图像的“深度”。
更新:我尝试了Paul建议的东西(修改filterargs
,如scale, offset
和矩阵),但我无法改变“深度”效果。 所以还在寻找答案。
这是使用PIL(左)和GIMP(右)的压花效果的比较。 原始图片位于http://www.linuxtopia.org/online_books/graphics_tools/gimp_advanced_guide/gimp_guide_node74.html 。
如果您无法通过使用或组合操作来实现目标(例如旋转,然后应用EMBOSS滤镜,重新旋转),(或增强对比度然后进行压花),那么您可以采用更改(或创建自己的)滤镜矩阵。
在ImageFilter.py中,你会发现这个类:
##
# Embossing filter.
class EMBOSS(BuiltinFilter):
name = "Emboss"
filterargs = (3, 3), 1, 128, (
-1, 0, 0,
0, 1, 0,
0, 0, 0
)
在矩阵的不同角落放置-1将改变方位角并使其为-2 可能具有您正在寻找的效果。
矩阵逐像素地应用。 矩阵中的每个元素对应于当前像素和周围像素; 表示当前像素的中心值。 新的变换后的当前像素将被创建为所有9个像素的组合,由矩阵中的值加权。 例如,全部为零且中心为1的矩阵不会更改图像。
其他参数是scale
和offset
。 对于内置EMBOSS,值为1(比例)和128(偏移)。 改变这些将改变结果的整体强度。
来自ImageFilter.py:
# @keyparam scale Scale factor. If given, the result for each
# pixel is divided by this value. The default is the sum
# of the kernel weights.
# @keyparam offset Offset. If given, this value is added to the
# result, after it has been divided by the scale factor.
由于我不熟悉GIMP的“深度”参数的影响,我不能说哪个最有可能做你想要的。
您还可以使矩阵具有不同的大小。 用(5,5)替换(3,3),然后创建25元素矩阵。
要在不重新保存源代码的情况下对过滤器进行临时更改,只需执行以下操作:
ImageFilter.EMBOSS.filterargs=((3, 3), 1, 128, (-1, 0, 0, 0, 1, 0, 0, 0, 0))
from PIL import Image
import numpy
# defining azimuth, elevation, and depth
ele = numpy.pi/2.2 # radians
azi = numpy.pi/4. # radians
dep = 10. # (0-100)
# get a B&W version of the image
img = Image.open('daisy.jpg').convert('L')
# get an array
a = numpy.asarray(img).astype('float')
# find the gradient
grad = numpy.gradient(a)
# (it is two arrays: grad_x and grad_y)
grad_x, grad_y = grad
# getting the unit incident ray
gd = numpy.cos(ele) # length of projection of ray on ground plane
dx = gd*numpy.cos(azi)
dy = gd*numpy.sin(azi)
dz = numpy.sin(ele)
# adjusting the gradient by the "depth" factor
# (I think this is how GIMP defines it)
grad_x = grad_x*dep/100.
grad_y = grad_y*dep/100.
# finding the unit normal vectors for the image
leng = numpy.sqrt(grad_x**2 + grad_y**2 + 1.)
uni_x = grad_x/leng
uni_y = grad_y/leng
uni_z = 1./leng
# take the dot product
a2 = 255*(dx*uni_x + dy*uni_y + dz*uni_z)
# avoid overflow
a2 = a2.clip(0,255)
# you must convert back to uint8 /before/ converting to an image
img2 = Image.fromarray(a2.astype('uint8'))
img2.save('daisy2.png')
我希望这有帮助。 我现在可以看到为什么你对PIL的结果感到失望。 Wolfram Mathworld是矢量代数复习的一个很好的资源。
之前
后
要增加浮雕滤镜的深度,请增加滤镜蒙版的半径。 深度较低:
h = [[1, 0, 0]
[0, 0, 0]
[0, 0, -1]]
与高深度:
h = [[1, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, -1]]
要更改方位角,请将非零系数放在不同的角度:
h = [[0, 0, 1]
[0, 0, 0]
[-1, 0, 0]]
我不太确定海拔高度。 您可能需要更改非零系数值? 我只知道它需要是一个高通滤波器。
无论如何,要使用Scipy解决方案计算和显示图像:
import scipy.misc, scipy.signal
im = scipy.misc.imread(filename)
im_out = scipy.signal.convolve2d(im, h, 'same')
scipy.misc.imshow(im_out)
希望这可以帮助。
编辑:好的,正如Paul暗示PIL,你可以调整过滤器参数,甚至可以定义一个全新的内核。 比例和偏移参数与您要查找的内容无关。 过滤器的大小对于调整深度最重要。
经过进一步调查,PIL不允许您将过滤器大小更改为5x5以上。 似乎很奇怪。 因此,您不会像您预期的那样获得深度变化。
对于完全控制,您可能想要尝试我前面提到过的Scipy解决方案。 将过滤器大小更改为荒谬的,如21x21,并查看它是否具有您想要的差异类型。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.