2014-09-30 69 views
3

我試圖用leptonica處理後將圖像保存爲jpeg。我使用Python和ctypes的,我的代碼是:Leptonica - 應用otsu閾值後無法寫入圖像

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。我錯過了什麼?

編輯 -

我現在已經ammended每leptonica文檔以下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

可以檢查類型'otsu'?它看起來像一個帶有錯誤代碼的int,而不是一個pix指針。 – 101 2014-10-01 11:45:51

+0

是的類型是int。感謝你,我剛剛意識到這是爲什麼,並已修改函數,以反映這通過添加ctypes.c_void_p到otsu的argtypes列表的末尾,並提供一個輸出圖像的功能。它不返回一個不同的錯誤。請參閱上述問題的修正。 – ajrasp 2014-10-01 13:22:15

+0

'pixOtsuAdaptiveThreshold()'是否返回通過或錯誤?看起來你有一個比需要更少的參數。 – 101 2014-10-01 23:21:26

回答

2

我發現你在做什麼錯 - 如果你在函數簽名檢查,它需要在年底可選2個muttualy專屬參數 - 其中之一是一個數組爲它返回係數,而不是圖像 - 最後一個參數是繪製算法應用程序的空白圖像。

此外,最後2個參數是「指針的指針」一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,因爲它是現在(LIMTED到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) 
+0

非常感謝!這很好,但我還沒有得到它的工作。我在argtpyes中添加了額外的c_void_p,並且在函數中添加了ctypes.cvoid_p(0)。新的錯誤消息說'模塊對象沒有屬性cvoid_p'。我想這是在上面的打字錯誤,所以我把它改爲ctypes.c_void_p(0),現在錯誤說'ctypes.ArgumentError:參數6:<類型'exceptions.TypeError'>:錯誤的類型'。任何想法現在有什麼不對?再次感謝。 – ajrasp 2014-10-07 19:46:51

+0

好吧,我只是修復了錯誤,我錯誤地刪除了c_float。現在再次出現原始錯誤 - 「支持的最大圖像尺寸爲65500像素pixWriteStreamJpeg錯誤:內部jpeg錯誤pixWriteJpeg:pix未寫入流中錯誤」。爲了防止出現相同結果,試圖切換最後兩個變量的位置。 – ajrasp 2014-10-08 19:45:11