web-dev-qa-db-ja.com

Matlabのimresizeをpython

MatlabのimresizeコードをPythonに転送しています。 scipyのimresizeを見つけましたが、Matlabからは異なる結果が得られます。

PythonでMatlabと同じ結果を得る方法。

Python/scipy imresize

from scipy.misc import imresize
import numpy as np

dtest = np.array(([1,2,3],[4,5,6],[7,8,9]))
scale = 1.4
dim = imresize(dtest,1/scale)

Matlab imresize

dtest = [1,2,3;
         4,5,6;
         7,8,9];
scale = 1.4;
dim = imresize(dtest,1/scale);

これらの2つのコードは、異なる結果を返します。

9
user3960019

scipy.misc.imresize関数は私には少し奇妙です。一つには、これは、この画像のscipy.misc.imresize呼び出しに提供したサンプルの2D画像を1.0のスケールで指定するとどうなるかです。理想的には、同じ画像が得られるはずですが、(IPythonで)次のようになります。

In [35]: from scipy.misc import imresize

In [36]: import numpy as np

In [37]: dtest = np.array(([1,2,3],[4,5,6],[7,8,9]))

In [38]: out = imresize(dtest, 1.0)

In [39]: out
Out[39]: 
array([[  0,  32,  64],
       [ 96, 127, 159],
       [191, 223, 255]], dtype=uint8)

出力のタイプをuint8に変更するだけでなく、値もスケールします。 1つには、画像の最大値が255に等しく、最小値が0に等しいように見えます。MATLABのimresizeはこれを行わず、予想どおりに画像のサイズを変更します。

>> dtest = [1,2,3;4,5,6;7,8,9];
>> out = imresize(dtest, 1)

out =

     1     2     3
     4     5     6
     7     8     9

ただし、MATLABがサイズ変更を実行することを認識しておく必要があります デフォルトでアンチエイリアシングが有効になっています 。ここでscipy.misc.resizeが何をするかはわかりませんが、アンチエイリアシングが有効になっていないことは間違いありません。

編集-2016年11月23日

以下のコメントでエリックが指摘しているように、画像を目的のタイプにプレキャストすると、期待どおりの結果が得られます。

In [10]: dtest = np.array([[1,2,3],[4,5,6],[7,8,9]], dtype=np.uint8)

In [11]: out = imresize(dtest, 1.0)

In [12]: out
Out[12]: 
array([[1, 2, 3],
       [4, 5, 6],
       [7, 8, 9]], dtype=uint8)

画像が[0,255]の範囲に拡大縮小されていないことがわかります。最終的に目的の場所に到達するには、画像の浮動小数点表現を取得する必要があります。 scipy.misc.imresizeには'mode'という追加のフラグがあり、これを'F'として指定して、出力が浮動小数点であることを確認できます。

In [14]: scale = 1.4

In [15]: out = imresize(dtest, 1/scale, mode='F')

In [16]: out
Out[16]: 
array([[ 2.5 ,  3.75],
       [ 6.25,  7.5 ]], dtype=float32)

後で見るように、scipy.misc.resizeで表示される結果は、MATLABで表示される結果と一致しません。

最良の結果を得るには、スケールを指定しないでください。結果を再現するためのターゲット出力サイズを指定してください。そのため、あなたの場合の1/scale2 x 2サイズの出力に近いので、MATLABで行うことは次のとおりです。

>> dtest = [1,2,3;4,5,6;7,8,9];
>> out = imresize(dtest, [2,2], 'bilinear', 'AntiAliasing', false)

out =

    2.0000    3.5000
    6.5000    8.0000

マトリックス内の一部の値がscipy.misc.resizeと一致していないことがわかります。 MATLABで表示されるものと一致させるため。必要なものに最も近いのは、OpenCVの resize 関数、またはscikit-imageの resize 関数です。これらは両方ともアンチエイリアシングがありません。 PythonとMATLABの両方を一致させたい場合は、双一次内挿法を使用します。MATLABのimresizeはデフォルトでバイキュービック内挿を使用しますが、MATLABがカスタムカーネルを使用すると、メソッド間でバイキュービック補間を使用する場合、出力を一致させることがはるかに困難になります。より有益な結果については、この投稿を参照してください。

MATLAB vs C++ vs OpenCV --imresize

Python OpenCV:

In [93]: import numpy as np

In [94]: import cv2

In [95]: dtest = np.array(([1,2,3],[4,5,6],[7,8,9]), dtype='float')

In [96]: out = cv2.resize(dtest, (2,2))

In [97]: out
Out[97]: 
array([[ 2. ,  3.5],
       [ 6.5,  8. ]])

Scikit-imageの場合:

In [100]: from skimage.transform import resize

In [101]: dtest = np.array(([1,2,3],[4,5,6],[7,8,9]), dtype='uint8')

In [102]: out = resize(dtest, (2,2), order=1, preserve_range=True)

In [103]: out
Out[103]: 
array([[ 2. ,  3.5],
       [ 6.5,  8. ]])

最後に注意すべき興味深い点は、浮動小数点スケールを指定するときのMATLAB、OpenCV、およびscikit-imageの動作が互いに異なることです。いくつかの実験を行いましたが、浮動小数点サイズを指定したため、一致する結果を得ることができませんでした。それに加えて、scikit-imageはスケールファクターの取り込みをサポートしていません。これは、スケールではなく出力サイズを明示的に示す理由です。

@ rayryengによる優れた回答 を調べているときに見つけたオプションをもう1つ追加します。

scipy.misc.imresize PILを使用します(したがって、画像をスケーリングされた整数に変換します)。しかし、ページは別の関数にリンクしています: scipy.ndimage.zoom

>>> from scipy import ndimage
>>> dtest = np.array(([1,2,3],[4,5,6],[7,8,9]), dtype='float')
>>> ndimage.zoom(dtest, 2/3)
array([[ 1.,  3.],
       [ 7.,  9.]])
>>> ndimage.zoom(dtest, 2/3, prefilter=False)
array([[ 2.33333333,  3.66666667],
       [ 6.33333333,  7.66666667]])

Matlabと同じ結果は得られませんが、次のようになります。

>> dtest = [1,2,3;4,5,6;7,8,9];
>> imresize(dtest, [2,2])

ans =
    2.1296    3.5648
    6.4352    7.8704

達成したいことによっては、これが役立つ場合があります。私にとっては、scipyがすでに使用されているため、プロジェクトに別のパッケージを含める必要がないという利点があります。

3
kratenko

たくさん掘り下げた後、アンチエイリアシングでmatlabのサイズ変更を複製する唯一の解決策は、 Alex(fatheral) at https://github.com/fatheral/ matlab_imresize 。現在、バイキュービックカーネルのみを使用していますが、Matlabで提供されている他のカーネルに簡単に拡張できます。

0
Vik