11

次のように配置された2点の画像があります。

|----------------|
|                |
|    .           |
|                |
|          .     |
|                |
|----------------|

両方の点に X、Y 座標があり、画像を X 度回転する必要があるため、代わりに次のようになります。

|----------------|
|                |
|                |
|    .     .     |
|                |
|                |
|----------------|

基本的に、それらは互いに隣り合って整列しますが、これの計算は何ですか? (C# のコード例はさらに優れていますが、必須ではありません)

4

6 に答える 6

15

回転の「中心」として使用するポイントによって異なります。上下の点をpointA、右下の点をpointBとしましょう。点 A を中心に回転させて、点 B を点 A に合わせたい場合、ラジアンで回転角度を計算すると、次のようになります。

double angle = Math.Atan2(pointB.Y - pointA.Y, pointB.X - pointA.X);

画像をどのように処理しているかはわかりません。したがって、以下は System.Drawing.Graphics を使用している場合にのみ適用されます。

myImage.TranslateTransform(-pointA.X, -pointA.Y);
myImage.RotateTransform((float) angle, MatrixOrder.Append);
myImage.TranslateTransform(pointA.X, pointA.Y, MatrixOrder.Append);

それが役に立てば幸い。

于 2009-01-23T10:30:19.733 に答える
5

コードはありません。申し訳ありませんが、戦略です。

ソース画像をサンプリングして結果画像を作成できる必要があります。回転角度がわかったので、結果から元のマップにマップするマッパー関数を作成する必要があります。

このコードは、結果画像の各行を単純にスキャンし、ピクセルを元の画像にマッピングします。簡単にできます。

for (int plotY = 0; plotY < resultHeight; plotY++)
{
   for (int plotX = 0; plotX < resultWidth; plotX++)
   {
         resultImage.PlotPixel(getOriginalPixel(plotX, plotY, angleOfRotation));
   } 
}

魔法の「getOriginalPixel」メソッドが必要なだけで、ここで数学の出番です。

画像を 0 度回転すると、plotX、plotY は元の画像の X/Y になります。しかし、それは楽しいことではありません。

pickX = x * cos(angle) - y * sin(angle)
pickY = y * cos(angle) + x * sin(angle)

ソースピクセルにマッピングされると思います。範囲外かどうかを確認し、黒か何かを返すだけです:)

于 2009-01-23T10:23:29.670 に答える
4

以下のコードは動作します

  Matrix mRotate = new Matrix();
    mRotate.Translate(Convert.ToInt32(Width.Value) / -2, Convert.ToInt32(Height.Value) / -2, MatrixOrder.Append);
    mRotate.RotateAt(theta, new Point(0, 0), MatrixOrder.Append);

    using (GraphicsPath gp = new GraphicsPath())
    {  // transform image points by rotation matrix
        gp.AddPolygon(new Point[] { new Point(0, 0), new Point(Convert.ToInt32(Width.Value), 0), new Point(0, Convert.ToInt32(Height.Value)) });
        gp.Transform(mRotate);
        PointF[] pts = gp.PathPoints;

        // create destination bitmap sized to contain rotated source image
        Rectangle bbox = boundingBox(bmpSrc, mRotate);
        Bitmap bmpDest = new Bitmap(bbox.Width, bbox.Height);


        using (Graphics gDest = Graphics.FromImage(bmpDest))
        {  // draw source into dest


            Matrix mDest = new Matrix();
            mDest.Translate(bmpDest.Width / 2, bmpDest.Height / 2, MatrixOrder.Append);
            gDest.Transform = mDest;
            gDest.DrawImage(bmpSrc, pts);
            gDest.DrawRectangle(Pens.Transparent, bbox);
            //drawAxes(gDest, Color.Red, 0, 0, 1, 100, "");
            return bmpDest;
        }
    }
于 2011-02-16T16:28:03.710 に答える
2

一般的な 2D 変換を実行するには、6 つの未知数を持つ方程式のペアを解く必要があります。

'x = xA + yB + C

'y = xD + yE + D

3 つの対応する点が与えられると、6 つの既知の点が得られ、システムを解くことができます。せん断を気にしないので、この場合は 4 つのポイントしかありませんが、他の 2 つのポイントによって形成される線に 90 度で 3 番目のポイントを導入することを想像できます。回転した画像を作成すると、(擬似コード的に)次のようになります。

for ( y = 0; y < height; y++ )
 for ( x = 0; x < width; x++ )
  {
    newx = x*A + y*B + C;
    newy = x*D + y*D + E;
    newimage(x,y ) = oldimage( newx, newy );
  }
}

パフォーマンスが重要な場合、y*B は外側の外観でのみ変化し、newx,newy は内側のループで定数 A と D によって変化することに注意することで、内側のループの乗算を最適化して取り除くことができます。

于 2009-01-23T11:22:56.807 に答える
2

最初に中心点を見つけます。

Point p = new Point((x1-x2)/2, (y1-y2)/2)

次に、三角法を使用して角度を解きます。原点を中心点にリベースしたと仮定するので、ポイントの 1 つに新しい x3 と y3 ができました。

hypotenuse = SqrRt(x3^2 + y3^2)

未知の角度を解いていますTH

Sin(TH) = opposite / hypotenuse

したがって、TH を解くには、次のものが必要です。

TH = Asin(y3 / hypotenuse)

で回転しTHます。

三角関数のリファレンスについては、ウィキペディアを参照してください

于 2009-01-23T10:25:26.483 に答える
2

幾何学的な回転行列を調べる必要があります。詳細な説明については、このサイトを参照してください

ただし、最良の結果を得るには、宛先からソースに変換してから、宛先ピクセルごとに変換を使用する必要があります。

m = rotation matrix

for each point p in destination
  p' = p.m
  get pixel p' from source
  set pixle p in destination

.net フレームワークには、これらすべてを行うメソッドがあります:System.Drawing.Graphics.RotateTransformSystem.Drawing.Graphics.TranslateTransform. 画像の回転ポイントを原点に移動する移動を設定してから、回転を適用してから別の移動を適用して元の位置に戻す必要があります。これらの関数がどのように動作するかを確認するには、これらの関数を試してみる必要があります。:-(

于 2009-01-23T10:22:25.977 に答える