Я пытаюсь использовать PythonMagickWand для использования искажения Shepards на изображении. Можно также видеть источник distort.c, который используется ImageMagick.
PythonMagickWand не делает поддержкой по умолчанию искажения Shepards. Для фиксации этого я включил:
ShepardsDistortion = DistortImageMethod(15)
выровнять 544 из PythonMagickWand (См. здесь для моего измененного PythonMagicWand). 15 указателей в отношении distort.h (строка 51) источника MagickWand, в котором ShepardsDistortion является 15-м объектом в списке. Это соответствует всем другим поддерживаемым методам искажения.
Теперь, что-то, что я могу делать неправильно, предполагает, что существующие методы искажения, которые поддерживаются PythonMagickWand, используют тот же тип аргументов как Shepards. Они не могли бы, но я не знать, как я могу сказать. Я знаю, что distort.c делает работу, но я не могу удаться, является ли аргументами, которые это принимает, то же или отличающийся.
У меня есть следующий код (отрывок):
from PythonMagickWand import *
from ctypes import *
arrayType = c_double * 8
pointsNew = arrayType()
pointsNew[0] = c_double(eyeLeft[0])
pointsNew[1] = c_double(eyeLeft[1])
pointsNew[2] = c_double(eyeLeftDest[0])
pointsNew[3] = c_double(eyeLeftDest[1])
pointsNew[4] = c_double(eyeRight[0])
pointsNew[5] = c_double(eyeRight[1])
pointsNew[6] = c_double(eyeRightDest[0])
pointsNew[7] = c_double(eyeRightDest[1])
MagickWandGenesis()
wand = NewMagickWand()
MagickReadImage(wand,path_to_image+'image_mod.jpg')
MagickDistortImage(wand,ShepardsDistortion, 8, pointsNew, False)
MagickWriteImage(wand,path_to_image+'image_mod22.jpg')
Я получаю следующую ошибку:
MagickDistortImage(wand,ShepardsDistortion, 8, pointsNew, False) ctypes.ArgumentError: argument 4:
Я знаю, что pointsNew является неправильным способом обеспечить аргументы.. Но я просто не знаю то, что является правильным форматом. Это - пример, искажают команду, которая работает, когда выполнено в Терминале:
convert image.jpg -virtual-pixel Black -distort Shepards 121.523809524,317.79638009 141,275 346.158730159,312.628959276 319,275 239.365079365,421.14479638 232,376 158.349206349,483.153846154 165,455 313.015873016,483.153846154 300,455 0,0 0,0 0,571.0 0,571.0 464.0,571.0 464.0,571.0 0,571.0 0,571.0 image_out.jpg
Таким образом, я предполагаю, что вопрос: Как я создаю список c_doubles, который будет принят PythonMagickWand? Или мой взлом должен добавить Искажение Shepards в PythonMagickWand полностью неправильно?
Я в основном должен воссоздать терминальную команду. У меня есть он работающий при помощи подпроцесса для выполнения команды из Python, но это не то, как я хочу сделать это.
От NeedMoreBeer на Reddit.com:
from PythonMagickWand import *
from ctypes import *
arrayType = c_double * 8
pointsNew = arrayType()
pointsNew[0] = c_double(121.523809524)
pointsNew[1] = c_double(317.79638009)
pointsNew[2] = c_double(141)
pointsNew[3] = c_double(275)
pointsNew[4] = c_double(346.158730159)
pointsNew[5] = c_double(312.628959276)
pointsNew[6] = c_double(319)
pointsNew[7] = c_double(275)
ShepardsDistortion = DistortImageMethod(14)
MagickWandGenesis()
wand = NewMagickWand()
MagickReadImage(wand,'/home/user/image.png')
MagickDistortImage(wand,ShepardsDistortion, 8, pointsNew, False)
MagickWriteImage(wand,'/home/user/image_mod22.jpg')
Конкретно для меня это была следующая строка:
ShepardsDistortion = DistortImageMethod(14)
Это помогло мне! Еще раз спасибо NeedMoreBeer с Reddit.
Это ОТ, но:
Мне очень понравилась волшебная палочка на питоне, но когда я использовал ее на 600+ изображениях, где-то произошла утечка памяти, которая съела всю память на (32-битной) машине. Я был склонен думать, возможно, в самом ImageMagick, но мог ошибаться.
В конце концов я узнал, что:
GraphicsMagick - это порт более ранней версии ImageMagick; но поскольку ImageMagick сильно меняет свой API, PythonMagickWant не будет работать с GraphicsMagick.
GraphicsMagick, похоже, также быстрее, чем ImageMagick (с улучшенной многозадачностью).
Чтобы мой скрипт работал быстро, через несколько дней я изменил его так, чтобы вместо использования ImageMagick скрипт загружал gimp, который затем запускал мой скрипт с использованием python-scriptfu. Казалось, все работает нормально.
Если это работает для вас, то используйте это; также парень PythonMagickWand действительно полезен + привязки хороши.
Как указано в сообщении об ошибке, функция ожидает указатель ( LP_c_double
), но у вас есть только массив.
Вам нужно будет явно привести свой массив к указателю, чтобы передать его как указатель на внешнюю функцию:
>>> arr = (c_double * 8)() >>> arr # just an array... <__main__.c_double_Array_8 object at 0x1004ad050> >>> arr[0] = 5 # ... >>> cast(arr, POINTER(c_double)) # now it's the right type <__main__.LP_c_double object at 0x1004ad0e0> >>> cast(arr, POINTER(c_double))[0] 5.0