以前、連続で記載していた補間についてですが、画像しか載せていなかったのでまとめてコードを記載いたしました。
バグはあると思いますが、ご了承願います。m(_ _)m


基本構造は以下のようになります。
ループ内の(x,y)は出力先の画像の画素値を求めるために、入力の画像のどの位置の画像から取得するかを求めています。

// 角度をラジアンへ変更
double radian = ConvertRadian(degree);

// 回転に使用するsin,cosは定数値
double COS = Math.Cos(radian);
double SIN = Math.Sin(radian);

// 出力先の画像の高さ・幅を計算
int width = (int)(Math.Abs(bmp.Width * COS) + Math.Abs(bmp.Height * SIN) + 0.5);
int height = (int)(Math.Abs(bmp.Width * SIN) + Math.Abs(bmp.Height * COS) + 0.5);

// 出力先の画像を生成
Bitmap bit = new Bitmap(width, height);
FillBlack(bit);

// 中心座標
int cx = bmp.Width / 2;
int cy = bmp.Height / 2;

int cx2 = bit.Width / 2;
int cy2 = bit.Height / 2;

for (int i = 0; i < bit.Width; i++)
{
    for (int j = 0; j < bit.Height; j++)
    {
        double x = (i - cx2) * COS + (j - cy2) * SIN + cx;
        double y = -(i - cx2) * SIN + (j - cy2) * COS + cy;
        
        if (chk(x, y, bmp))
        {
            Color bmpCol = func(x, y, bmp);
            bit.SetPixel(i, j, bmpCol);
        } 
}


chk関数は入力の画像内か判断するだけですので省略します
funcの中を以下に記述していきます。

バイリニア補間

http://authorunknown408.blog.fc2.com/blog-entry-22.html

private static Color BiLinearInterpolation(double x, double y, Bitmap bmp)
{
    int x1 = (int)Math.Floor(x);
    int y1 = (int)Math.Floor(y);

    double R = 0;
    double G = 0;
    double B = 0;

    double[] Wx = new double[2];
    double[] Wy = new double[2];

    Wx[0] = 1 - (x - x1) ;
    Wx[1] = x - x1;
    Wy[0] = 1 - (y - y1);
    Wy[1] = y - y1;

    for (int i = 0; i < Wx.Length; i++)
    {
        for (int j = 0; j < Wy.Length; j++)
        {
            R += ((double)bmp.GetPixel(x1 + i, y1 + j).R * Wx[i] * Wy[j]);
            G += ((double)bmp.GetPixel(x1 + i, y1 + j).G * Wx[i] * Wy[j]);
            B += ((double)bmp.GetPixel(x1 + i, y1 + j).B * Wx[i] * Wy[j]);

        }
    }
    
    return Color.FromArgb((int)R, (int)G, (int)B);
}


バイキュービック補間

http://authorunknown408.blog.fc2.com/blog-entry-23.html

private static Color BiCubicInterpolation(double x, double y, Bitmap bmp)
{
    double[] dx = new double[4];
    double[] dy = new double[4];
    double[] Wx = new double[4];
    double[] Wy = new double[4];
    
    int x1 = (int)Math.Floor(x);
    int y1 = (int)Math.Floor(y);
    
    double R = 0;
    double G = 0;
    double B = 0;

    dx[0] = (x1 - x) - 1;
    dx[1] = (x1 - x);
    dx[2] = (Math.Ceiling(x) - x);
    dx[3] = dx[2] + 1;

    dy[0] = (y1 - y) - 1;
    dy[1] = (y1 - y);
    dy[2] = (Math.Ceiling(y) - y);
    dy[3] = dy[2] + 1;

    for (int i = 0; i < dx.Length; i++)
    {
        Wx[i] = BiCubicWeight(dx[i]);
        Wy[i] = BiCubicWeight(dy[i]);
    }

    double temp = 0;
    for (int i = 0; i < Wx.Length; i++)
    {
        for (int j = 0; j < Wy.Length; j++)
        {
            R += ((double)bmp.GetPixel(x1 - 2 + i, y1 - 2 + j).R * Wx[i] * Wy[j]);
            G += ((double)bmp.GetPixel(x1 - 2 + i, y1 - 2 + j).G * Wx[i] * Wy[j]);
            B += ((double)bmp.GetPixel(x1 - 2 + i, y1 - 2 + j).B * Wx[i] * Wy[j]);

            temp += Wx[i] * Wy[j];
        }
    }
    
    R = ColorCheck(R / temp);
    G = ColorCheck(G / temp);
    B = ColorCheck(B / temp);
    
    return Color.FromArgb((int)R, (int)G, (int)B);
}

private static double BiCubicWeight(double x)
{
    double a = -1;
    double h = 0;
    double t = Math.Abs(x);

    if (0 <= t && t <= 1)
    {
        h = (a + 2) * Math.Pow(t, 3) - (a + 3) * Math.Pow(t, 2) + 1;
    }
    else if (1 <= t && t <= 2)
    {
        h = a * Math.Pow(t, 3) - 5 * a * Math.Pow(t, 2) + 8 * a * t - 4 * a;
    }
    else
    {
        h = 0;
    }
    return h;
}


Lanczos補間

http://authorunknown408.blog.fc2.com/blog-entry-24.html

public static Color Lanczos2Interpolation(double x, double y, Bitmap bmp)
{
    double[] dx = new double[4];
    double[] dy = new double[4];
    double[] Wx = new double[4];
    double[] Wy = new double[4];

    int x1 = (int)Math.Floor(x);
    int y1 = (int)Math.Floor(y);

    double R = 0;
    double G = 0;
    double B = 0;

    dx[0] = (x1 - x) - 1;
    dx[1] = (x1 - x);
    dx[2] = (Math.Ceiling(x) - x);
    dx[3] = dx[2] + 1;

    dy[0] = (y1 - y) - 1;
    dy[1] = (y1 - y);
    dy[2] = (Math.Ceiling(y) - y);
    dy[3] = dy[2] + 1;

    for (int i = 0; i < dx.Length; i++)
    {
        Wx[i] = LanczosWeight(dx[i], 2);
        Wy[i] = LanczosWeight(dy[i], 2);
    }

    double temp = 0;
    for (int i = 0; i < Wx.Length; i++)
    {
        for (int j = 0; j < Wy.Length; j++)
        {
            R += ((double)bmp.GetPixel(x1 - 2 + i, y1 - 2 + j).R * Wx[i] * Wy[j]);
            G += ((double)bmp.GetPixel(x1 - 2 + i, y1 - 2 + j).G * Wx[i] * Wy[j]);
            B += ((double)bmp.GetPixel(x1 - 2 + i, y1 - 2 + j).B * Wx[i] * Wy[j]);

            temp += Wx[i] * Wy[j];
        }
    }
    
    R = ColorCheck(R / temp);
    G = ColorCheck(G / temp);
    B = ColorCheck(B / temp);


    return Color.FromArgb((int)R, (int)G, (int)B);
}
public static Color Lanczos3Interpolation(double x, double y, Bitmap bmp)
{
    double[] dx = new double[6];
    double[] dy = new double[6];
    double[] Wx = new double[6];
    double[] Wy = new double[6];

    int x1 = (int)Math.Floor(x);
    int y1 = (int)Math.Floor(y);

    double R = 0;
    double G = 0;
    double B = 0;

    dx[0] = (x1 - x) - 2;
    dx[1] = (x1 - x) - 1;
    dx[2] = (x1 - x);
    dx[3] = (Math.Ceiling(x) - x);
    dx[4] = dx[3] + 1;
    dx[5] = dx[4] + 1;

    dy[0] = (y1 - y) - 2;
    dy[1] = (y1 - y) - 1;
    dy[2] = (y1 - y);
    dy[3] = (Math.Ceiling(y) - y);
    dy[4] = dy[3] + 1;
    dy[5] = dy[4] + 1;

    for (int i = 0; i < dx.Length; i++)
    {
        Wx[i] = LanczosWeight(dx[i], 3);
        Wy[i] = LanczosWeight(dy[i], 3);
    }

    double temp = 0;
    for (int i = 0; i < Wx.Length; i++)
    {
        for (int j = 0; j < Wy.Length; j++)
        {
            R += ((double)bmp.GetPixel(x1 - 2 + i, y1 - 2 + j).R * Wx[i] * Wy[j]);
            G += ((double)bmp.GetPixel(x1 - 2 + i, y1 - 2 + j).G * Wx[i] * Wy[j]);
            B += ((double)bmp.GetPixel(x1 - 2 + i, y1 - 2 + j).B * Wx[i] * Wy[j]);

            temp += Wx[i] * Wy[j];
        }
    }

    R = ColorCheck(R / temp);
    G = ColorCheck(G / temp);
    B = ColorCheck(B / temp);

    return Color.FromArgb((int)R, (int)G, (int)B);
}

private static double Sinc(double x)
{
    double X = Math.PI * x;
    if (X == 0)
    {
        return 1;
    }
    else
    {
        return Math.Sin(X) / X;
    }
}

private static double ColorCheck(double x)
{
    if(x > 255.0)
    {
        x = 255;
    }
    else if (x < 0)
    {
        x = 0.0;
    }
    else
    {
        // do nothing
    }

    return x;
}

private static double LanczosWeight(double x, int n)
{            
    double t = Math.Abs(x);
    double h = 0;

    if (t <= n)
    {
        h = Sinc(t) * Sinc(t / n);
    }
    else
    {
        h = 0;
    }
    return h;
}




ちょっとわかりずらいかもしれませんが、残しておきます。

Related Entries
Comments
Post a comment
Contributor
Comment
Trackbacks URL
URL
Permalink
Trackbacks
FC2カウンター
プロフィール

詠み人知らず

Author:詠み人知らず
プログラム好きな名もなき凡人がお送りしています。(得意とは言っていない
最近の興味はPython、C#、Matlab(Octave)、画像処理、AR(拡張現実)、統計などなど・・・

気分で思いついたことを書くため話題に一貫性がないかもしれません。

カレンダー
03 | 2017/04 | 05
- - - - - - 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 - - - - - -
最新記事
タグクラウドとサーチ

カテゴリ
最新コメント
最新トラックバック
月別アーカイブ