How to use intel IPP ippiRemap function using ctypes in python?

101 Views Asked by At

I am trying to use ippiRemap from intel IPP library shared object (libipp.so). by installing ipp using conda.

conda install -c intel ipp 

The library shared object files are installed in the environment directory. When trying to use ippiRemap function for image processing with python ctypes

import ctypes
ipp = ctypes.cdll.loadLibrary('libippi.so')
ippiRemap = ipp.ippiRemap

I got the error undefined symbol: ippiRemap. However, this is might be due to name mangling of function symbol names by C++. Trying readelf command I got the following output:

$ readelf -D --symbol /home/user_name/anaconda3/envs/env_name/lib/libippi.so |grep -E "FUNC.*GLOBAL.*ippIRemap.*"

 376: 000000000006a180    32 FUNC    GLOBAL DEFAULT   10 ippiRemap_16s_AC4R
   663: 000000000006a100    32 FUNC    GLOBAL DEFAULT   10 ippiRemap_16u_AC4R
   685: 000000000006a080    32 FUNC    GLOBAL DEFAULT   10 ippiRemap_8u_AC4R
   773: 000000000006a120    32 FUNC    GLOBAL DEFAULT   10 ippiRemap_16s_C1R
   862: 000000000006a140    32 FUNC    GLOBAL DEFAULT   10 ippiRemap_16s_C3R
   910: 000000000006a020    32 FUNC    GLOBAL DEFAULT   10 ippiRemap_8u_C1R
   920: 000000000006a160    32 FUNC    GLOBAL DEFAULT   10 ippiRemap_16s_C4R
  1028: 000000000006a040    32 FUNC    GLOBAL DEFAULT   10 ippiRemap_8u_C3R
  1079: 000000000006a060    32 FUNC    GLOBAL DEFAULT   10 ippiRemap_8u_C4R
  1433: 000000000006a200    32 FUNC    GLOBAL DEFAULT   10 ippiRemap_32f_AC4R
  1794: 000000000006a280    32 FUNC    GLOBAL DEFAULT   10 ippiRemap_64f_AC4R
  1866: 000000000006a0a0    32 FUNC    GLOBAL DEFAULT   10 ippiRemap_16u_C1R
  1985: 000000000006a0c0    32 FUNC    GLOBAL DEFAULT   10 ippiRemap_16u_C3R
  2049: 000000000006a0e0    32 FUNC    GLOBAL DEFAULT   10 ippiRemap_16u_C4R
  2424: 000000000006a220    32 FUNC    GLOBAL DEFAULT   10 ippiRemap_64f_C1R
  2451: 000000000006a1a0    32 FUNC    GLOBAL DEFAULT   10 ippiRemap_32f_C1R
  2523: 000000000006a240    32 FUNC    GLOBAL DEFAULT   10 ippiRemap_64f_C3R
  2562: 000000000006a1c0    32 FUNC    GLOBAL DEFAULT   10 ippiRemap_32f_C3R
  2585: 000000000006a260    32 FUNC    GLOBAL DEFAULT   10 ippiRemap_64f_C4R
  2615: 000000000006a1e0    32 FUNC    GLOBAL DEFAULT   10 ippiRemap_32f_C4R

trying one of symbol names works.

>> ippiRemap = ipp.ippiRemap_16s_AC4R
>> ippiRemap
 <_FuncPtr object at 0x7fc277ba2c80>

So my question what is difference between each symbol name, are they the same function? is there a standard way to use it with ctypes ?

1

There are 1 best solutions below

0
On

I just refer to documentation for ippiRemap function in intel ipp. I don't have much experience with it. however, I would like to share this solution on how to interface with this function using ctypes from python. So, as far as I understand ippiRemap had several versions (It might not be name mangling as I mentioned in My question). So, this was the documentation from Intel.

enter image description here

so as long as I use a single channel grey microscopic image, I used ippiRemap_8u_C1R for single channel-raw major-uint_8 image.

    import ctypes 
    import ctypes.util 
    
    
    ippcore = None 
    ipp = None 
    
    ippi_path = ctypes.util.find_library('ippi')   
    ippcore_path = ctypes.util.find_library('ippcore') 
    
    if ippi_path:
      ipp = ctypes.cdll.LoadLibrary(ippi_path) 
    if ippcore_path: 
      ippcore = ctypes.cdll.LoadLibrary(ippcore_path) 
    
    
    IPPI_INTER_NN = 1 
    IPPI_INTER_LINEAR = 3 
    IPPI_INTER_CUBIC = 6 
    IPPI_INTER_LANCZOS = 16 
    
    
    #defining c++ structures needed for the function.
    
    #Intel ipp IppiSize c++ structure
    class IppiSize(ctypes.Structure):
      _fields_ = [('width', ctypes.c_int), ('height', ctypes.c_int)]
    
    #Intel ipp IppiRect c++ structure
    class IppiRect(ctypes.Structure):
      _fields_ = [
        ('x', ctypes.c_int),
        ('y', ctypes.c_int),
        ('width', ctypes.c_int),
        ('height', ctypes.c_int)
      ]
    
    
    
    def ippGetStatusString(status):
      c_status = ctypes.c_int(status) 
      c_ippGetStatusString = ippcore.ippGetStatusString
      c_ippGetStatusString.argtypes = [
        ctypes.c_int 
      ]
      c_ippGetStatusString.restype = ctypes.c_char_p 
    
      c_status_string = c_ippGetStatusString(c_status)
      return c_status_string.decode() 
    
    
    def ippiRemap(src, dst, x_map, y_map, interpolation = IPPI_INTER_NN):

    if ipp == None : 
      raise Exception("Error: libippi library was not found")

      # IPPI_INTER_NN: Nearest-neighbor interpolation
      # IPPI_INTER_LINEAR: Linear interpolation
      # IPPI_INTER_CUBIC: Cubic interpolation
      # IPPI_INTER_LANCZOS: Lanczos interpolation
      # IPPI_INTER_MITCHELL: Mitchell-Netravali interpolation
    
    c_ippiRemap = getattr(ipp, "ippiRemap_8u_C1R")
    
    #telling ctypes about the c++ function prototype
    
    c_ippiRemap.argtypes = [
      ctypes.POINTER(ctypes.c_uint8),
      IppiSize,
      ctypes.c_int, 
      IppiRect, 
      ctypes.POINTER(ctypes.c_float),
      ctypes.c_int, 
      ctypes.POINTER(ctypes.c_float),
      ctypes.c_int, 
      ctypes.POINTER(ctypes.c_uint8),
      ctypes.c_int, 
      IppiSize,
      ctypes.c_int
    ]
    
    c_ippiRemap.restype = ctypes.c_int 

    c_src_size = IppiSize(src.shape[0], src.shape[1])
    c_dst_size = IppiSize(dst.shape[0], dst.shape[1])

    x_map_ptr = x_map.ctypes.data_as(ctypes.POINTER(ctypes.c_float))
    y_map_ptr = y_map.ctypes.data_as(ctypes.POINTER(ctypes.c_float))

    
    src_ptr = src.ctypes.data_as(ctypes.POINTER(ctypes.c_uint8))
    dst_ptr = dst.ctypes.data_as(ctypes.POINTER(ctypes.c_uint8))


    src_roi = IppiRect(0, 0, c_src_size.width, c_src_size.height)
    dst_roi_size = IppiSize(c_dst_size.width, c_dst_size.height)

    x_map_step = ctypes.sizeof(ctypes.c_float) 
    y_map_step = ctypes.sizeof(ctypes.c_float)  * c_src_size.width 

    status = c_ippiRemap(
        src_ptr,
        c_src_size,
        ctypes.c_int(src.shape[0]),
        src_roi,
        x_map_ptr, 
        x_map_step,
        y_map_ptr,
        y_map_step,
        dst_ptr,
        ctypes.c_int(dst.shape[0]),
        dst_roi_size,
        ctypes.c_int(interpolation),
    )


    if status != 0 : #from Intel ipp documentation non-zero status is a failure
      errString = ippGetStatusString(status)
      print(errString)