2013-11-23 33 views
12

私はAPIによってscipy.ndimage.interpolation.affine_transformに惑わされています。そして、私が唯一の人ではないと判断したのはthis issueです。私は実際には画像を回転させるよりももっと興味深いことをしたいと思っていますが、ローテーションはまず初心者のために行います。affine_transform (そして、はい、私はscipy.ndimage.interpolation.rotateをよく知っていますが、どのように運転するかを考えてaffine_transformが私に興味を持っています)。私は、OpenGLのようなシステムではこの種のものをしたい場合はscipy.ndimage.interpolation.affine_transformを使用してイメージを中心に回転させるにはどうすればよいですか?

が、私は(p-c)R+cを形質転換された中央cについての2x2の回転行列Rを適用する変換を計算し、そのためのポイントpの思考の観点から考えます= pR+c-cRであり、変換の変換成分として使用される用語を与える。上記の問題によれば、しかし、scipyのダウンロードのaffine_transformない「オフセット最初」私たちは、実際に計算する必要があるオフセットがs、このような再配置のビットとR'Rの逆であるs=(c-cR)R'を与える(p-c)R+c=(p+s)R

私はipythonのノートブックにこれを差し込む場合(pylabモードは、多分次のコードは、いくつかの追加輸入を必要とします):

img=scipy.misc.lena() 
#imshow(img,cmap=cm.gray);show() 
centre=0.5*array(img.shape) 
a=15.0*pi/180.0 
rot=array([[cos(a),sin(a)],[-sin(a),cos(a)]]) 
offset=(centre-centre.dot(rot)).dot(linalg.inv(rot)) 
rotimg=scipy.ndimage.interpolation.affine_transform(
    img,rot,order=2,offset=offset,cval=0.0,output=float32 
) 
imshow(rotimg,cmap=cm.gray);show() 

は、私は残念ながら周りに回転されていない

rotated but not about centre lena image

を取得センター。

私はここで欠けているトリックは何ですか?

+1

汚れたテスト私はあなたのオフセットの負の値を取ることが中心について回転しているようだと気付いた。 – treddy

+0

ああ!はい、優秀、ここで確認しました。 scipyのシステムのモデルは '(p-s)R'でなければなりません。それを答えに入れ、私はそれを受け入れるだろう。 – timday

答えて

4

ちょっとしたことをやり直してください。&汚れたテスト私は、あなたのオフセットの負の値を取ることが中心を中心に回転しているように感じました。

13

treddyの答えが私に作用基線を与えたら、affine_transformのより良い作業モデルを得ることができました。元の質問のヒントにリンクされている問題ほど実際には奇妙ではありません。

基本的に、出力画像の各点(座標)pTsはマトリックスであり、関数に渡されたオフセットpT+sに変換されます。 我々は出力の点c_outはにマッピングされ、回転R、我々はs = (c_int-c_out)TT=RSで)生成する再配置することができるpT+s = (p-c_out)RS+c_in必要Sスケーリング(おそらく異方性)と、入力画像からc_inからサンプリングしたいそうである場合。

何らかの理由で私はtransform.Tをに渡す必要がありますが、あまり心配するつもりはありません。おそらく右の変換(上で想定)と行座標の関係と左の変換の列座標との関係です。

は、だからここに簡単なテストを中心とした画像の回転です:それは別の画像用に変更です。ここ

src=scipy.misc.lena() 
c_in=0.5*array(src.shape) 
c_out=array((256.0,256.0)) 
for i in xrange(0,7): 
    a=i*15.0*pi/180.0 
    transform=array([[cos(a),-sin(a)],[sin(a),cos(a)]]) 
    offset=c_in-c_out.dot(transform) 
    dst=scipy.ndimage.interpolation.affine_transform(
     src,transform.T,order=2,offset=offset,output_shape=(512,512),cval=0.0,output=float32 
    ) 
    subplot(1,7,i+1);axis('off');imshow(dst,cmap=cm.gray) 
show() 

Spinning Lena

src=scipy.misc.lena()[::2,::2] 
c_in=0.5*array(src.shape) 
c_out=array((256.0,256.0)) 
for i in xrange(0,7): 
    a=i*15.0*pi/180.0 
    transform=array([[cos(a),-sin(a)],[sin(a),cos(a)]]) 
    offset=c_in-c_out.dot(transform) 
    dst=scipy.ndimage.interpolation.affine_transform(
     src,transform.T,order=2,offset=offset,output_shape=(512,512),cval=0.0,output=float32 
    ) 
    subplot(1,7,i+1);axis('off');imshow(dst,cmap=cm.gray) 
show() 

Spinning small Lena

をサイズと、ここでのバージョンです補償する異方性スケーリングソース画像の異方性解像度の場合はnsate。そのmatrixoffset @timdayからの洞察に基づいて

src=scipy.misc.lena()[::2,::4] 
c_in=0.5*array(src.shape) 
c_out=array((256.0,256.0)) 
for i in xrange(0,7): 
    a=i*15.0*pi/180.0 
    transform=array([[cos(a),-sin(a)],[sin(a),cos(a)]]).dot(diag(([0.5,0.25]))) 
    offset=c_in-c_out.dot(transform) 
    dst=scipy.ndimage.interpolation.affine_transform(
     src,transform.T,order=2,offset=offset,output_shape=(512,512),cval=0.0,output=float32 
    ) 
    subplot(1,7,i+1);axis('off');imshow(dst,cmap=cm.gray) 
show() 

Spinning anisotropic Lena

+0

すごい、どうやって回転させて画面いっぱいにすることができますか? (角に黒/透明な空間を残すことなく回転するか? –

+0

画像の中心について十分に高いズーム係数を変換に組み込む必要があります。正方形のウィンドウの正方形の画像の場合、sqrt(2) – timday

+1

2016 +でこれに来る人は、最近のscipyバグ修正があったようですが、これは上記のいくつかの詳細を変更するかもしれません; https://github.com/scipy/scipy/issues/を参照してください。 2255とhttps://github.com/scipy/scipy/pull/5794 – timday

9

出力座標系で定義されている、私は標準的な線形代数での表記としてフィットする問題の以下の読み取りを、提供します画像のスケーリングも理解できます。ここでは、T.inv=T^-1を、行列の逆数を意味する擬似パイソン表記とし、*をドット積を意味するものとして使用します。出力画像の各点oについて

affine_transformmatrix=T.invが2x2の変換の一つはフォワードアフィン変換を定義するために使用するマトリックスとoffset=sあるi=T.inv*o+sなどの入力画像の対応する点iを発見出力座標で定義された変換です。純粋な回転の場合T=R=[[cos,-sin],[sin,cos]]、この特殊な場合はmatrix=T.inv=T.Tです。なぜなら、@timdayが転置をまだ適用しなければならない理由があります(代わりに、負の角度を使うこともできます)。

オフセットsの値が正確な方法は@timdayによって記述見出される:c_inc_outで、アフィン変換後、配置されることになっている場合(例えば、入力中心が出力中央に配置されなければならない)、次いでc_in=T.inv*c_out+sまたはs=c_in-T.inv*c_out(ここで使用されている行列積の従来の数学的順序、matrix * vectorに注意してください。なぜなら、逆順を使用した@timdayは、コードのこの時点で転置を必要としないからです)。

1スケーリングS最初にして回転Rを望んでいるなら、それはT=R*Sので、T.inv=S.inv*R.invが(逆の順番に注意してください)と考えています。たとえば、画像を列方向( 'x')に2倍にしたい場合は、S=diag((1, 2))、したがってS.inv=diag((1, 0.5))となります。

src = scipy.misc.lena() 
c_in = 0.5 * array(src.shape) 
dest_shape = (512, 1028) 
c_out = 0.5 * array(dest_shape) 
for i in xrange(0, 7): 
    a = i * 15.0 * pi/180.0 
    rot = array([[cos(a), -sin(a)], [sin(a), cos(a)]]) 
    invRot = rot.T 
    invScale = diag((1.0, 0.5)) 
    invTransform = dot(invScale, invRot) 
    offset = c_in - dot(invTransform, c_out) 
    dest = scipy.ndimage.interpolation.affine_transform(
     src, invTransform, order=2, offset=offset, output_shape=dest_shape, cval=0.0, output=float32 
    ) 
    subplot(1, 7, i + 1);axis('off');imshow(dest, cmap=cm.gray) 
show() 

Lena: first stretched, then rotated

画像が最初に伸ばし、その後、回転させる場合は、ドット積の順序を逆にする必要があります

だけでいくつかの簡単なをやっ
invTransform = dot(invRot, invScale) 

Lena: first rotated, then stretched

関連する問題