PythonMagickWand谢泼德失真(ctypes LP_c_double问题)

1 投票
3 回答
2009 浏览
提问于 2025-04-15 23:39

我正在尝试使用 PythonMagickWand 来对一张图片应用 Shepards失真。你也可以查看 ImageMagick使用的distort.c源代码

默认情况下,PythonMagickWand不支持Shepards失真。为了解决这个问题,我在:

ShepardsDistortion = DistortImageMethod(15)

中添加了这行代码到PythonMagickWand的第544行(这里是我修改后的PythonMagicWand)。这里的15是指 distort.h(第51行)中的内容,其中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: <type 'exceptions.TypeError'>: expected LP_c_double instance instead of list

我知道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

所以我想问的是:我该如何创建一个可以被PythonMagickWand接受的c_doubles列表? 或者 我把Shepards失真添加到PythonMagickWand的这个方法完全错误吗?

我基本上需要重新创建这个终端命令。我已经通过使用subprocess从Python运行这个命令让它工作了,但我并不想这样做。

3 个回答

0

根据错误信息来看,这个函数需要一个指针(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
0

这段话有点偏题,不过我想说:

我之前很喜欢用 Python 的 Magick Wand,但当我在 600 多张图片上使用它时,发现有个地方出现了内存泄漏,导致我这台 32 位的机器内存全被吃光了。我开始怀疑可能是 ImageMagick 本身的问题,但也许我错了。

最后我发现:

GraphicsMagick 是 ImageMagick 早期版本的一个移植版;但是因为 ImageMagick 经常改动它的接口,PythonMagickWant 就不能和 GraphicsMagick 一起使用。

而且,GraphicsMagick 似乎比 ImageMagick 更快,因为它在多任务处理上做得更好。

为了让我的脚本快速运行,我在几天内把它改成了不使用 ImageMagick,而是加载 GIMP,然后用 python-scriptfu 来运行我的脚本。一切看起来都正常。

如果这个方法对你有效,那就用吧;另外,PythonMagickWand 的开发者真的很乐于助人,而且它的绑定也很不错。

2

来自 NeedMoreBeerReddit.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

撰写回答