Python中使用PIL进行图像浮雕处理--添加深度,方位等。

7
我正在尝试使用PIL浮雕图像。
PIL提供了一种基本的方法来浮雕图像(使用ImageFilter.EMBOSS)。
在像GIMP这样的图像编辑软件中,您可以在这个浮雕图像中改变参数如方位角、深度和高程。
如何使用PIL做到这一点?至少我想调整浮雕图像的“深度”。
更新:我尝试了保罗建议的事情(修改filterargs,如scale, offset和矩阵),但我无法改变“深度”效果。所以仍在寻找答案。
这是使用PIL(左)和GIMP(右)的浮雕效果比较。原始图片位于此处,http://www.linuxtopia.org/online_books/graphics_tools/gimp_advanced_guide/gimp_guide_node74.html

alt text


要更改“深度”,您可以尝试在EMBOSS滤镜中更改“比例”和“偏移”参数(我猜测减小偏移并增加比例)。请参见我的答案补充。 - Paul
1
安装Gimp并阅读此文档:http://www.linuxtopia.org/online_books/graphics_tools/gimp_advanced_guide/gimp_guide_node74.html 后,显然Gimp和PIL对浮雕的定义不同。即,颜色(Gimp)与入射向量上梯度差成比例,而不仅仅是浮雕本身。如果您有兴趣,可以使用NumPy精确复制此过程,但可能还存在PIL解决方案。也许如果您上传示例图像(原始和期望结果),就能更好地解决问题。 - Paul
2
发布图片不应该是一个很大的挑战。http://www.techieblogger.com/2009/09/free-image-hosting-and-photo-sharing-sites.html在某些方面,您受到这些网站的限制吗?我不会为您编写复制GIMP功能的代码。但是,步骤如下:1)将图像转换为黑白。2)将其转换为numpy数组,并将其乘以您的“深度”值。3)计算梯度(只需应用“gradient”函数)。4)定义您的入射向量(来自方位角,高程)。5)找到grad和vector之间的差异。6)转换回img。 - Paul
嗨,我现在已经在主要问题中上传了凸起的图像。感谢numpy过程。我会尝试一下。 - cppb
抱歉耽搁了。我在度假。我添加了一些代码,提供了一个简单的Numpy方法。希望能有所帮助。 - Paul
显示剩余6条评论
2个回答

10
如果你不能通过使用操作或操作组合(例如旋转,然后应用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的矩阵不会改变图像。
其他参数包括比例和偏移量。对于内置的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的"depth"参数的影响,因此无法确定哪个选项最有可能实现你想要的效果。
你也可以更改矩阵的大小。将(3,3)替换为(5,5),然后创建25个元素的矩阵。
如果想临时更改滤镜而不必重新保存源代码,请执行以下操作:
ImageFilter.EMBOSS.filterargs=((3, 3), 1, 128, (-1, 0, 0, 0, 1, 0, 0, 0, 0))

编辑:(采用 NumPy 的方法)

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 是一个很好的向量代数复习资源。 之前

alt text

之后

alt text


谢谢您的回答!是的,我尝试调整3 X 3矩阵中的参数。但是我没有得到期望的效果...也就是说,我想要“增加深度效果”。您能否解释一下这些矩阵元素是什么..我找不到解释...再次感谢! - cppb

2

要增加浮雕滤镜的深度,需增大滤镜掩模的半径。低深度:

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)

希望这能帮到你。
编辑:好的,正如保罗暗示的那样,您可以调整滤波器参数,甚至定义一个全新的内核。比例和偏移参数与您要查找的内容无关。滤波器的大小对于调整深度非常重要。
经过进一步调查,PIL不允许您将滤波器大小更改超过5x5。看起来很奇怪。因此,您将无法获得您可能期望的如此明显的深度变化。
为了完全控制,您可能想尝试我和保罗之前提到的Scipy解决方案。将滤波器大小更改为荒谬的21x21,看看它是否会产生您想要的类型差异。

是的,PIL不允许您指定超过5x5的滤波器大小。这篇文章很有用(正如你和bpowah所解释的那样,我认为numpy/scipy是一个好的解决方案。) - cppb

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接