Тиснение изображений в Python с PIL – добавление глубины, азимута и т. Д.

Я пытаюсь выбить изображение с помощью PIL .

PIL обеспечивает базовый способ ImageFilter.EMBOSS изображения (используя 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

  • Использование Python PIL для превращения RGB-изображения в чистое черно-белое изображение
  • Изменение размера изображения с помощью django?
  • Поиск субимажа внутри изображения Numpy
  • PIL Лучший способ заменить цвет?
  • Python: модуль _imagingft C не установлен
  • Умножение кортежа на скаляр
  • Как показать изображения PIL на экране?
  • Проблема с использованием библиотеки PIL python для обрезки и сохранения изображения
  • 2 Solutions collect form web for “Тиснение изображений в Python с PIL – добавление глубины, азимута и т. Д.”

    Если вы не можете достичь своей цели, используя или комбинацию операций (например, вращение, а затем применение фильтра 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, я не могу сказать, что, скорее всего, сделает то, что вы хотите.

    Вы также можете сделать матрицу разного размера. Замените (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

    Чтобы увеличить глубину фильтра тиснения, увеличьте радиус маски фильтра. Низкая глубина:

     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) 

    Надеюсь это поможет.

    EDIT: Хорошо, как Павел намекал на PIL, вы можете настроить параметры фильтра или даже определить совершенно новое ядро. Параметры масштаба и смещения не имеют ничего общего с тем, что вы ищете. Размер фильтра наиболее важен для регулировки глубины.

    При дальнейшем исследовании PIL не позволяет изменять размер фильтра за пределы 5×5. Кажется странным. Таким образом, вы не получите столь резкого изменения глубины, как вы, вероятно, ожидаете.

    Для полного контроля вы можете попробовать решение Scipy I и Paul, упомянутое ранее. Измените размер фильтра на что-то смешное, например 21×21, и посмотрите, не делает ли он тип разницы, который вы хотите.

    Python - лучший язык программирования в мире.