简体   繁体   English

使用PIL在Python中进行图像压纹 - 增加深度,方位角等

[英]Image embossing in Python with PIL — adding depth, azimuth, etc

I am trying to emboss an image using PIL . 我正在尝试使用PIL压印图像。

PIL provides a basic way to emboss an image ( using ImageFilter.EMBOSS ). PIL提供了一种压印图像的基本方法(使用ImageFilter.EMBOSS )。

In image editing packages like GIMP, you can vary parameters like Azimuth, depth and elevation in this embossed image. 在像GIMP这样的图像编辑软件包中,您可以更改此浮雕图像中的方位角,深度和高程等参数。

How to do this with PIL? 如何用PIL做到这一点? At the very least I want to adjust the "depth" of the embossed image. 至少我想调整浮雕图像的“深度”。

Update: I tried things suggested by Paul (modifying the filterargs such as scale, offset and the matrix), but I couldn't change the "depth" effect. 更新:我尝试了Paul建议的东西(修改filterargs ,如scale, offset和矩阵),但我无法改变“深度”效果。 So still looking for an answer. 所以还在寻找答案。

Here is the comparison of embossing effect using PIL (left) and GIMP (right). 这是使用PIL(左)和GIMP(右)的压花效果的比较。 The original picture is located here, http://www.linuxtopia.org/online_books/graphics_tools/gimp_advanced_guide/gimp_guide_node74.html . 原始图片位于http://www.linuxtopia.org/online_books/graphics_tools/gimp_advanced_guide/gimp_guide_node74.html

替代文字

If you cannot achieve your goal by using or combination of operations (like rotating, then applying the EMBOSS filter, the re-rotating), (or enhancing the contrast then embossing) then you may resort to changing (or creating your own) filter matrix. 如果您无法通过使用或组合操作来实现目标(例如旋转,然后应用EMBOSS滤镜,重新旋转),(或增强对比度然后进行压花),那么您可以采用更改(或创建自己的)滤镜矩阵。

Within ImageFilter.py you will find this class: 在ImageFilter.py中,你会发现这个类:

##
# Embossing filter.

class EMBOSS(BuiltinFilter):
    name = "Emboss"
    filterargs = (3, 3), 1, 128, (
        -1,  0,  0,
        0,  1,  0,
        0,  0,  0
        )

Placing a -1 in a different corner of the matrix will change the azimuth and making it a -2 may have the effect you are looking for. 在矩阵的不同角落放置-1将改变方位角并使其为-2 可能具有您正在寻找的效果。

The matrix is applied pixel-by-pixel. 矩阵逐像素地应用。 Each element in the matrix corresponds to the current pixel and surrounding pixels; 矩阵中的每个元素对应于当前像素和周围像素; the center value representing the current pixel. 表示当前像素的中心值。 The new, transformed current pixel will be created as a combination of all 9 pixels, weighted by the values in the matrix. 新的变换后的当前像素将被创建为所有9个像素的组合,由矩阵中的值加权。 For example, a matrix with all zeros and a 1 in the center will not change the image. 例如,全部为零且中心为1的矩阵不会更改图像。

Additional parameters are scale and offset . 其他参数是scaleoffset For the built-in EMBOSS, the values are 1 (scale) and 128 (offset). 对于内置EMBOSS,值为1(比例)和128(偏移)。 Changing these will change the overall strength of the result. 改变这些将改变结果的整体强度。

From ImageFilter.py: 来自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.

As I am unfamiliar with the effects of GIMP's "depth" parameter, I cannot say which is most likely to do what you want. 由于我不熟悉GIMP的“深度”参数的影响,我不能说哪个最有可能做你想要的。

You can also make the matrix a different size. 您还可以使矩阵具有不同的大小。 Replace the (3,3) with (5,5), and then create 25-element matrix. 用(5,5)替换(3,3),然后创建25元素矩阵。

To make temporary changes to the filter without re-saving source code, just do this: 要在不重新保存源代码的情况下对过滤器进行临时更改,只需执行以下操作:

ImageFilter.EMBOSS.filterargs=((3, 3), 1, 128, (-1, 0, 0, 0, 1, 0, 0, 0, 0))

Edit: (taking the NumPy approach) 编辑:(采用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')

I hope this helps. 我希望这有帮助。 I can see now why you were disappointed with PIL's results. 我现在可以看到为什么你对PIL的结果感到失望。 Wolfram Mathworld is a good resource for a vector algebra refresher. Wolfram Mathworld是矢量代数复习的一个很好的资源。

Before 之前

替代文字

After

替代文字

To increase the depth of an emboss filter, increase the radius of the filter's mask. 要增加浮雕滤镜的深度,请增加滤镜蒙版的半径。 Low depth: 深度较低:

h = [[1, 0, 0]
     [0, 0, 0]
     [0, 0, -1]]

versus high depth: 与高深度:

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]]

To change the azimuth, place the nonzero coefficients at a different angle: 要更改方位角,请将非零系数放在不同的角度:

h = [[0, 0, 1]
     [0, 0, 0]
     [-1, 0, 0]]

I'm not really sure about elevation. 我不太确定海拔高度。 You may need to change the nonzero coefficient values? 您可能需要更改非零系数值? I just know it needs to be a high-pass filter. 我只知道它需要是一个高通滤波器。

In any case, to compute and display the image using a Scipy solution: 无论如何,要使用Scipy解决方案计算和显示图像:

import scipy.misc, scipy.signal
im = scipy.misc.imread(filename)
im_out = scipy.signal.convolve2d(im, h, 'same')
scipy.misc.imshow(im_out)

Hope this helps. 希望这可以帮助。

EDIT: Okay, as Paul hinted with PIL, you can adjust filter parameters, or even define a completely new kernel. 编辑:好的,正如Paul暗示PIL,你可以调整过滤器参数,甚至可以定义一个全新的内核。 The scale and offset parameters have nothing to do with what you are looking for. 比例和偏移参数与您要查找的内容无关。 The size of the filter is most important for adjusting depth. 过滤器的大小对于调整深度最重要。

Upon further investigation, PIL does not let you change the filter size beyond 5x5. 经过进一步调查,PIL不允许您将过滤器大小更改为5x5以上。 Seems strange. 似乎很奇怪。 Therefore, you will not get as dramatic a change in depth as you probably expect. 因此,您不会像您预期的那样获得深度变化。

For total control, you may want to try the Scipy solution I and Paul mentioned earlier. 对于完全控制,您可能想要尝试我前面提到过的Scipy解决方案。 Change the filter size to something ridiculous, like 21x21, and see if it makes the type of difference you want. 将过滤器大小更改为荒谬的,如21x21,并查看它是否具有您想要的差异类型。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM