zoukankan      html  css  js  c++  java
  • 从 Python 调用 MATLAB 函数的三种方法

    0. 实验环境

    • Ubuntu 16.04
    • Matlab R2015b

    1. 借助于 mlab 库

    安装方法非常简单,只需一行命令 sudo pip install mlab 即可。

    import numpy as np
    from PIL import Image
    from mlab.releases import latest_release as matlab
    
    image = Image.open('1.jpg')
    image = np.array(image)
    h, w = image.shape
    print(image.shape) # (413, 295)
    

    在上面的代码中,我们先读入一个图片,然后将其转化为一个 Numpy 数组。接下来,假如我们想通过调用 MATLAB 的 imresize 函数来对这幅图像进行 4 倍上采样,那么我们要做的就是将这个 Numpy 数组传递到 MATLAB 中,然后调用相应的函数,最后再将结果返回到 Python 中。

    但是,MATLAB 并不支持将 Python 中的 Numpy 数组直接映射为矩阵,具体映射方式可参考 从 Python 将数据传递到 MATLAB。所以,我们需要先将数组转化为列表,然后通过 matlab.double(initializer=None, size=None, is_complex=False) 构造函数 在 Python 中创建 MATLAB 数组,最后再调整到原来图片的大小。这时候,我们就可以调用 MATLAB 的函数得到我们想要的结果了。

    image = image.reshape(-1, 1)
    image = image.tolist()
    image = matlab.double(image)
    image = matlab.reshape(image, (h, w))
    resized_image = matlab.imresize(image, 4, 'bicubic')
    print(resized_image.shape) # (1652, 1180)
    

    如果我们想要调用自定义函数,比如下面这样的 m 文件。

    function c = add(a, b)
    	c = a + b;
    end
    

    那么只需要传递相应的参数进去即可,这里 Python 中的浮点数会映射为 MATLAB 中的 double 类型。

    result = matlab.add(2.0, 3.0)
    print(result) # 5.0
    

    但是,目前在我这边发现 mlab 不支持 Python 3,安装后会提示 ImportError: No module named 'mlabwrap' 之类的错误,暂时还没找到解决方案。

    2. 借助于 MATLAB 自带的引擎 API

    首先,需要 安装用于 Python 的 MATLAB 引擎 API。比如,在我的工作环境下,需要进入到 MATLAB 对应的安装路径 /usr/local/MATLAB/R2015b/extern/engines/python,然后运行命令 sudo python setup.py install 即可。

    由于我的 MATLAB 版本还比较低,目前只支持到 Python 3.4,更高的版本则会报错 OSError: MATLAB Engine for Python supports Python version 2.7, 3.3 and 3.4, but your version of Python is 3.5

    >>> import matlab.engine
    >>> eng = matlab.engine.start_matlab()
    >>> import numpy as np
    >>> image = np.random.randn(30, 30)
    >>> image.shape
    (30, 30)
    >>> resized_image = eng.imresize(image, 4, 'bicubic')
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "/usr/local/lib/python2.7/dist-packages/matlab/engine/matlabengine.py", line 79, in __call__
        out=_stdout, err=_stderr)
    TypeError: unsupported Python data type: numpy.ndarray
    >>> image = image.reshape(-1, 1)
    >>> image = image.tolist()
    >>> image = matlab.double(image)
    >>> image.reshape((30, 30))
    >>> resize_image = eng.imresize(image, 4, 'bicubic')
    >>> resize_image.size
    (120, 120)
    
    >>> eng.add(2.0, 3.0)
    5.0
    >>>
    

    用法和第一种类似,但是在我这边测试发现只能运行在交互模式下,直接运行对应的 py 文件则会报错。

    senius@HP:~/Downloads$ python2 test1.py 
    Traceback (most recent call last):
      File "test1.py", line 3, in <module>
        import matlab.engine
      File "/usr/local/lib/python2.7/dist-packages/matlab/engine/__init__.py", line 60, in <module>
        raise EnvironmentError('The installation of MATLAB Engine for Python is '
    EnvironmentError: The installation of MATLAB Engine for Python is corrupted.  
    Please reinstall it or contact MathWorks Technical Support for assistance.
    

    上面两种方法都只能进行一些简单的调用,而且还需要在 Python 和 MATLAB 之间进行数据转化,非常不方便,下面介绍的第三种方法则非常简单有效。

    3. 借助于 transplant 库

    transplant 库支持 Python 3.4-3.7,安装方法非常简单 sudo pip3 install transplant。Python 中的列表会转化为 MATLAB 中的元胞数组,Numpy 数组会转化为 MATLAB 中的矩阵,更多详细信息可参阅 github教程。同样地,我们可以这样对图像进行上采样。

    >>> import transplant
    >>> import numpy as np
    >>> matlab = transplant.Matlab(jvm=False, desktop=False)
    
                                < M A T L A B (R) >
                      Copyright 1984-2015 The MathWorks, Inc.
                       R2015b (8.6.0.267246) 64-bit (glnxa64)
                                  August 20, 2015
    
     
    For online documentation, see http://www.mathworks.com/support
    For product information, visit www.mathworks.com.
     
    >>> image = np.random.randn(30, 30)
    >>> image.shape
    (30, 30)
    >>> resized_image = matlab.imresize(image, 4, 'bicubic')
    >>> resized_image[0]
    array([[ 0.78619134,  0.7167187 ,  0.57147529, ..., -0.1314248 ,
            -0.19615895, -0.22226921],
           [ 0.69992414,  0.63668882,  0.50463212, ..., -0.10023177,
            -0.16053713, -0.18483134],
           [ 0.51579787,  0.46606682,  0.36253926, ..., -0.01897913,
            -0.07015085, -0.09065985],
           ...,
           [ 0.27508006,  0.27579099,  0.28756401, ..., -0.70385557,
            -0.80006309, -0.84680474],
           [ 0.23260259,  0.23527929,  0.25076149, ..., -0.75840955,
            -0.80315767, -0.82872907],
           [ 0.21943022,  0.2228168 ,  0.2396492 , ..., -0.78075353,
            -0.80353953, -0.8200766 ]])
    >>> resized_image[0].shape
    (120, 120)
    >>>
    

    针对如下所示的多个自定义函数存在互相调用的复杂情况,transplant 也可以轻松胜任。

    比如,我们需要通过 Python 调用 NGmeet_DeNoising( N_Img, O_Img, nSig ) 这个函数,它有三个输入,N_Img 为长×宽×波段的三维噪声高光谱图像,O_Img 为对应的干净图像,而 nSig 为噪声等级。那么只需在 Python 中将两个 Numpy 数组和一个整数传给对应的函数即可。

    clean = np.load('GT_crop.npy')
    h, w, b = clean.shape
    sigma = 25
    noisy = clean + np.random.randn(h, w, b) * sigma / 255
    print(cal_psnr(clean, noisy)) # 20.1707
    c = matlab.NGmeet_DeNoising(255.0*noisy, 255.0*clean, sigma)
    print(c.shape, c.dtype) # (200, 200, 191) float64
    print(matlab.mpsnr(c/255, clean)) # 34.5712
    

    如果报如下的错误,则因为 par_nSig 是将 Python 中的 sigma=25 转化为了 MATLAB 中的 int64,而 int64 数据不能与 double 类数据相乘。而解决办法也很简单,double(par_nSig) 将其数据转化为 double 类型即可。

    获取更多精彩,请关注「seniusen」!

  • 相关阅读:
    三个心态做人做学问 沧海
    成功走职场要找准自己的"快捷键" 沧海
    免费离线下载 拂晓风起
    Hibernate 获取某个表全部记录时 奇怪现象 (重复出现某个记录) 拂晓风起
    无法读取mdb 如果连接不了ACCESS mdb文件,就尝试安装MDAC 拂晓风起
    Netbeans 使用 Hibernate 逆向工程 生成hbm和pojo 拂晓风起
    如何点击单选框 radio 后面的文字,选中单选框 拂晓风起
    Java 连接access 使用access文件 不用配置 拂晓风起
    mysql下如何执行sql脚本 拂晓风起
    Hibernate配置access Hibernate 连接 access 拂晓风起
  • 原文地址:https://www.cnblogs.com/seniusen/p/12171305.html
Copyright © 2011-2022 走看看