我正试图在python中使用Leptonica(C库)。该库有一个pixRead
方法,该方法将图像文件的绝对路径作为参数。目前,我成功地从python调用了这个:
leptonica = ctypes.cdll.LoadLibrary("/path/to/lept.so")
pix_image = leptonica.pixRead("/path/to/image.jgp")
但是,我想调用方法pixReadStream
,它将文件流作为输入参数。在我的python程序中,我可以使用OpenCV以numpy数组的形式访问图像。
问题
有没有任何方法可以将我在Python程序中作为numpy数组的图像传递给leptopnica C库中的pixReadStream
方法,该方法将文件流作为输入参数?
roi #OpenCV image numpy array
leptonica = ctypes.cdll.LoadLibrary("/path/to/lept.so")
pix_image = leptonica.pixReadStream(##any way to pass roi here?##)
从Numpy数组创建Leptonica PIX
结构可以在不将数据编码为用于存储的图像格式的情况下完成,并以某种方式通过内核将其作为文件在同一进程中传输。将OpenCV中的数组数据转换为RGBA数据,并从Leptonica中包装足够的数据,以创建适当大小的空PIX
结构,然后将数组中的数据复制到PIX
中。
以下是一个小示例,说明如何使用OpenCV加载图像,将其转换为包裹PIX
结构的Python对象,并使用Leponica将图像数据再次保存到文件中:
#!/usr/bin/env python
# coding: utf8
from __future__ import absolute_import, division, print_function
from ctypes import c_char_p, c_uint32, c_void_p, CDLL, memmove, pointer, POINTER
from ctypes.util import find_library
import cv2
LEPTONICA = CDLL(find_library('lept'))
_pix_create = LEPTONICA.pixCreate
_pix_create.argtypes = [c_uint32, c_uint32, c_uint32]
_pix_create.restype = c_void_p
_pix_destroy = LEPTONICA.pixDestroy
_pix_destroy.argtypes = [POINTER(c_void_p)]
_pix_destroy.restype = None
_pix_get_data = LEPTONICA.pixGetData
_pix_get_data.argtypes = [c_void_p]
_pix_get_data.restype = POINTER(c_uint32)
_pix_endian_byte_swap = LEPTONICA.pixEndianByteSwap
_pix_endian_byte_swap.argtypes = [c_void_p]
_pix_endian_byte_swap.restype = c_uint32
_pix_write_implied_format = LEPTONICA.pixWriteImpliedFormat
_pix_write_implied_format.argtypes = [c_char_p, c_void_p, c_uint32, c_uint32]
_pix_write_implied_format.restype = c_uint32
class Pix(object):
def __init__(self, width, height, depth):
self._as_parameter_ = _pix_create(width, height, depth)
self._pointer = pointer
self._pix_destroy = _pix_destroy
def __del__(self):
pix_pointer = self._pointer(c_void_p(self._as_parameter_))
self._pix_destroy(pix_pointer)
assert pix_pointer[0] is None
@property
def data(self):
return _pix_get_data(self)
def endian_byte_swap(self):
_pix_endian_byte_swap(self)
def save(self, filename, quality=0, progessive=False):
_pix_write_implied_format(filename, self, quality, progessive)
@classmethod
def from_rgba(cls, array):
width, height, depth = array.shape
if depth != 4 and array.itemsize != 1:
raise ValueError('array has wrong format')
result = cls(width, height, 32)
memmove(result.data, array.ctypes.data, array.size * array.itemsize)
result.endian_byte_swap()
return result
def main():
image = cv2.imread('test.jpg')
image = cv2.cvtColor(image, cv2.cv.CV_BGR2RGBA)
pix = Pix.from_rgba(image)
pix.save('test.png')
if __name__ == '__main__':
main()
这可能对您有帮助吗?
给出的答案是"您可以从中使用PyFile_AsFile。"
- 对于转换,您可以使用numpy.load函数。。。http://docs.scipy.org/doc/numpy-1.10.1/reference/generated/numpy.load.html
https://github.com/numpy/numpy/blob/v1.10.1/numpy/lib/npyio.py#L257-L419
- 为了与c沟通,你可以有ctypes或cffi
https://kogs-www.informatik.uni-hamburg.de/~seppke/content/taching/wise1314/20131107_pridoehl-cffi.pdf