2

経度 360 度、緯度 120 度の正距円筒パノラマ ソース画像があります。

ビューポートの幅と高さ、および経度の回転を指定して、これをレンダリングできる関数を書きたいと思います。高さが完全に120度になるように、出力画像を作成したいと思います。

誰かがポインタを持っていますか?ターゲット座標からソースに変換する方法について、数学に頭を悩ませることはできません。

ありがとう

スリップ

これまでの私のコードは次のとおりです:- (ac# 2.0 コンソール アプリを作成し、system.drawing に ref を追加します)

static void Main(string[] args)
    {

        Bitmap src = new Bitmap(@"C:\Users\jon\slippyr4\pt\grid2.jpg");

        // constant stuff
        double view_width_angle = d2r(150);
        double view_height_angle = d2r(120);
        double rads_per_pixel = 2.0 * Math.PI / src.Width;

        // scale everything off the height
        int output_image_height = src.Width;

        // compute radius (from chord trig - my output image forms a chord of a circle with angle view_height_angle)
        double radius = output_image_height / (2.0 * Math.Sin(view_height_angle / 2.0));

        // work out the image width with that radius.
        int output_image_width = (int)(radius * 2.0 * Math.Sin(view_width_angle / 2.0));

        // source centres for later
        int source_centre_x = src.Width / 2;
        int source_centre_y = src.Height / 2;

        // work out adjacent length
        double adj = radius * Math.Cos(view_width_angle / 2.0);

        // create output bmp
        Bitmap dst = new Bitmap(output_image_width, output_image_height);

        // x & y are output pixels offset from output centre
        for (int x = output_image_width / -2; x < output_image_width / 2; x++)
        {
            // map this x to an angle & then a pixel
            double x_angle = Math.Atan(x / adj);
            double src_x = (x_angle / rads_per_pixel) + source_centre_x;

            // work out the hypotenuse of that triangle
            double x_hyp = adj / Math.Cos(x_angle);

            for (int y = output_image_height / -2; y < output_image_height / 2; y++)
            {
                // compute the y angle and then it's pixel
                double y_angle = Math.Atan(y / x_hyp);
                double src_y = (y_angle / rads_per_pixel) + source_centre_y;

                Color c = Color.Magenta;
                // this handles out of range source pixels. these will end up magenta in the target
                if (src_x >= 0 && src_x < src.Width && src_y >= 0 && src_y < src.Height)
                {
                    c = src.GetPixel((int)src_x, (int)src_y);
                }


                dst.SetPixel(x + (output_image_width / 2), y + (output_image_height / 2), c);
            }
        }

        dst.Save(@"C:\Users\slippyr4\Desktop\pana.jpg");

    }

    static double d2r(double degrees)
    {
        return degrees * Math.PI / 180.0;
    }

私が使用しているソース画像

このコードを使用すると、ターゲット イメージの幅を 120 度に設定したときに期待どおりの結果が得られます。以下のように、水平線などの正しい曲率が表示されます。実際の正距円筒図法で試してみると、商用ビューアーがレンダリングしたように見えます。 120度×120度の正しい出力

しかし、出力画像を広くすると、すべてうまくいきません。幅 150 度、高さ 120 度の画像で示されているように、中央の上部と下部に無効なピクセルが見られます。

ここに画像の説明を入力

コマーシャルの視聴者が行うように見えるのは、一種のズームインです。つまり、中央の画像は 120 度の高さであり、したがって、側面ではより多くが切り取られます。したがって、マゼンタはありません (つまり、無効なソース ピクセルはありません)。

しかし、私は数学でそれを行う方法について頭を悩ませることができません。

これは宿題ではなく、趣味のプロジェクトです。したがって、なぜ私は何が起こっているのかを理解していないのです!. また、コードの深刻な非効率性をご容赦ください。適切に動作するようになったら最適化します。

再度、感謝します

4

0 に答える 0