Leptonica - 应用otsu阈值后无法写入图像

时间:2014-09-30 16:09:04

标签: python ctypes leptonica

我试图用leptonica处理后将图像保存到jpeg。我使用python与ctypes,我的代码是:

import ctypes

leptlib = "liblept.so"
leptonica = ctypes.cdll.LoadLibrary(leptlib)

filename = "IMAG0724.jpg"
img = leptonica.pixRead(filename)

leptonica.pixConvertTo8.argtypes = [ctypes.c_void_p, 
                                    ctypes.c_int32]

pix_image = leptonica.pixConvertTo8(img, False)

leptonica.pixOtsuAdaptiveThreshold.argtypes = [ctypes.c_void_p, 
                                               ctypes.c_int32, 
                                               ctypes.c_int32, 
                                               ctypes.c_int32, 
                                               ctypes.c_int32, 
                                               ctypes.c_float]

otsu = leptonica.pixOtsuAdaptiveThreshold(pix_image,20,20,0,0,0.1)

leptonica.pixWriteJpeg.argtypes = [ctypes.c_void_p, 
                                   ctypes.c_void_p, 
                                   ctypes.c_int32, 
                                   ctypes.c_int32]

leptonica.pixWriteJpeg("otsu-lept", otsu, 75, 0)

此代码产生错误:

pixWriteJpeg出错:pix未定义

我相信这是因为我需要在应用otsu之后但在编写新图像之前做一些事情。我错过了什么?

修改 -

我现在已经推荐了以下每个leptonica docs http://tpgit.github.io/Leptonica/binarize_8c.html

leptonica.pixOtsuAdaptiveThreshold.argtypes = [ctypes.c_void_p, 
                                               ctypes.c_int32, 
                                               ctypes.c_int32, 
                                               ctypes.c_int32, 
                                               ctypes.c_int32, 
                                               ctypes.c_float,
                                               ctypes.c_void_p]

leptonica.pixOtsuAdaptiveThreshold(pix_image,20,20,0,0,0.1, img)

leptonica.pixWriteJpeg("otsu-lept", img, 75, 0)

现在出现新错误:

支持的最大图片尺寸为65500像素 pixWriteStreamJpeg出错:内部jpeg错误 pixWriteJpeg出错:pix没有写入流

我的图像分辨率为1552 x 2592,并且当otsu功能行被注释掉时,leptonica.pixWriteJpeg正常工作,因此看起来问题仍然是otsu函数返回的图像。

****编辑2 ****

当我使用leptonica检查输出img时,它告诉我宽度是一个大数字,这似乎每次运行函数时都会变化(例如149996048)并且高度保持正确,与输入图像的值相同。看起来otsu函数由于某种原因将图像宽度改变为这个大值。

编辑3

下面的jsbueno为我提供了这个问题的解决方案,我将在这里分享。问题是因为当实际需要将指针指针传递给随后工作的函数时,我将图像直接传递给函数。最终工作代码如下:

import ctypes

leptlib = "liblept.so"
leptonica = ctypes.cdll.LoadLibrary(leptlib)

filename = "IMAG0724.jpg"
img = leptonica.pixRead(filename)

leptonica.pixConvertTo8.argtypes = [ctypes.c_void_p, 
                                    ctypes.c_int32
                                    ]

pix_image = leptonica.pixConvertTo8(img, False)
w = leptonica.pixGetWidth(img)
h = leptonica.pixGetHeight(img)
pixa_out = leptonica.pixCreate(w,h,8)
pixa = ctypes.c_void_p(pixa_out)
leptonica.pixOtsuAdaptiveThreshold.argtypes = [ctypes.c_void_p, 
                                               ctypes.c_int32, 
                                               ctypes.c_int32, 
                                               ctypes.c_int32, 
                                               ctypes.c_int32, 
                                               ctypes.c_float,
                                               ctypes.c_void_p,
                                               ctypes.c_void_p
                                               ]

otsu = leptonica.pixOtsuAdaptiveThreshold(pix_image,
                                          20,
                                          20,
                                          0,
                                          0,
                                          0.1,
                                          None,
                                          ctypes.addressof(pixa)
                                          )


leptonica.pixWritePng("otsu-lept", pixa, 8)

1 个答案:

答案 0 :(得分:2)

我发现你做错了什么 - 如果你检查函数签名,它最后需要2个muttualy独占参数 - 其中一个是一个数组,它返回系数,而不是图像 - 非常最后一个参数是一个空图像,用于绘制算法的应用程序。

此外,最后两个参数是leptonica PIX对象的“指针指针” - 您可以创建一个包含ctypes.c_void_p对象的Python变量,并传递 ctypes.addressof它是leptonica的功能。

outsu函数的文档如下:

/*------------------------------------------------------------------*
 *                 Adaptive Otsu-based thresholding                 *
 *------------------------------------------------------------------*/
/*!
 *  pixOtsuAdaptiveThreshold()
 *
 *      Input:  pixs (8 bpp)
 *              sx, sy (desired tile dimensions; actual size may vary)
 *              smoothx, smoothy (half-width of convolution kernel applied to
 *                                threshold array: use 0 for no smoothing)
 *              scorefract (fraction of the max Otsu score; typ. 0.1;
 *                          use 0.0 for standard Otsu)
 *              &pixth (<optional return> array of threshold values
 *                      found for each tile)
 *              &pixd (<optional return> thresholded input pixs, based on
 *                     the threshold array)
 *      Return: 0 if OK, 1 on error
 *

PS。在研究这个时,我设法为leptonica 1.7.1构建了python-leptonica绑定 - 一旦我清理了我到达那里的混乱,我应该再发布一次。

对于任何能够运行python-leptonica的人来说,就像现在一样(在没有黑客攻击的情况下限制为leptonica 1.6.0) - 使用此函数的代码将是:

import leptonica
import ctypes
img = leptonica.functions.pixRead("t1.png")
imggray = leptonica.functions.pixConvertRGBToGrayMinMax(img, 1)
img = leptonica.functions.pixRead("t1.png")
output = leptonica.functions.pixCreate(imggray.w, imggray.h, 1)
a = ctypes.c_voidp()
leptonica.functions.pixOtsuAdaptiveThreshold(imggray, 20, 20, 0, 0, .1, None, ctypes.addressof(a))
output  = leptonica.PIX(from_address=a)
leptonica.functions.pixWritePng("t3.png", c, 1)