Efficiently convert System.Single[,] to numpy array

冷暖自知 提交于 2019-11-30 15:50:21

问题


Using Python 3.6 and Python for dotNET/pythonnet I have manged to get hold of an image array. This is of type System.Single[,]

I'd like to convert that to a numpy array so that I can actually do something with it in Python. I've set up a function to step through that array and convert it elementwise - but is there something more sensible (and faster) that I could use?

def MeasurementArrayToNumpy(TwoDArray):
    hBound = TwoDArray.GetUpperBound(0)
    vBound = TwoDArray.GetUpperBound(1)

    resultArray = np.zeros([hBound, vBound])

    for c in range(TwoDArray.GetUpperBound(0)):            
            for r in range(TwoDArray.GetUpperBound(1)):
                resultArray[c,r] = TwoDArray[c,r]
    return resultArray

回答1:


@denfromufa - that is a very useful link.

The suggestion there is to do a direct memory copy, either using Marshal.Copy or np.frombuffer. I couldn't manage to get the Marshal.Copy version working - some shenanigans are required to use a 2D array with Marshal and that changed the contents of of the array somehow - but the np.frombuffer version seems to work for me and reduced the time to complete by a factor of ~16000 for a 3296*2471 array (~25s -> ~1.50ms). This is good enough for my purposes

The method requires a couple more imports, so I've included those in the code snippet below

import ctypes
from System.Runtime.InteropServices import GCHandle, GCHandleType

def SingleToNumpyFromBuffer(TwoDArray):
    src_hndl = GCHandle.Alloc(TwoDArray, GCHandleType.Pinned)

    try:
        src_ptr = src_hndl.AddrOfPinnedObject().ToInt32()
        bufType = ctypes.c_float*len(TwoDArray)
        cbuf = bufType.from_address(src_ptr)
        resultArray = np.frombuffer(cbuf, dtype=cbuf._type_)
    finally:
        if src_hndl.IsAllocated: src_hndl.Free()
    return resultArray



回答2:


I modified rbp109 function so that it can be used with RGB images of the type System.Int32[,,]. The resulting numpy array is then re-shaped so that the image can be displayed in a opencv window

def net2Numpy(net_img,width,height):  

    src_hndl = GCHandle.Alloc(net_img, GCHandleType.Pinned)
    try:
        src_ptr = src_hndl.AddrOfPinnedObject().ToInt32()
        bufType = ctypes.c_int*len(net_img)
        cbuf = bufType.from_address(src_ptr)
        resultArray = np.frombuffer(cbuf, dtype=cbuf._type_)
    finally:
        if src_hndl.IsAllocated: src_hndl.Free()

    resultArray = resultArray.astype(dtype=np.uint8)
    resultArray = resultArray.reshape((height,width,3),order='C')

    return resultArray


来源:https://stackoverflow.com/questions/43910749/efficiently-convert-system-single-to-numpy-array

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!