4

双一次補間関数を実装しようとしていますが、何らかの理由で出力が悪くなります。何が問題なのかわかりません。正しい軌道に乗るための助けをいただければ幸いです。

double lerp(double c1, double c2, double v1, double v2, double x)
{
if( (v1==v2) ) return c1;
double inc = ((c2-c1)/(v2 - v1)) * (x - v1);
double val = c1 + inc;
return val;
};

void bilinearInterpolate(int width, int height)
{
// if the current size is the same, do nothing
if(width == GetWidth() && height == GetHeight())
    return;

//Create a new image
std::unique_ptr<Image2D> image(new Image2D(width, height));

// x and y ratios
double rx = (double)(GetWidth()) / (double)(image->GetWidth()); // oldWidth / newWidth
double ry = (double)(GetHeight()) / (double)(image->GetHeight());   // oldWidth / newWidth


// loop through destination image
for(int y=0; y<height; ++y)
{
    for(int x=0; x<width; ++x)
    {
        double sx = x * rx;
        double sy = y * ry;

        uint xl = std::floor(sx);
        uint xr = std::floor(sx + 1);
        uint yt = std::floor(sy);
        uint yb = std::floor(sy + 1);

        for (uint d = 0; d < image->GetDepth(); ++d)
        {
            uchar tl    = GetData(xl, yt, d);
            uchar tr    = GetData(xr, yt, d);
            uchar bl    = GetData(xl, yb, d);
            uchar br    = GetData(xr, yb, d);
            double t    = lerp(tl, tr, xl, xr, sx);
            double b    = lerp(bl, br, xl, xr, sx);
            double m    = lerp(t, b, yt, yb, sy);
            uchar val   = std::floor(m + 0.5);
            image->SetData(x,y,d,val);
        }
    }
}

//Cleanup
mWidth = width; mHeight = height;
std::swap(image->mData, mData);
}

入力画像 (幅と高さ 4 ピクセル)

入力画像 (幅と高さ 4 ピクセル)

私の出力

私の出力

期待される出力 (Photoshop の双一次補間)

期待される出力 (Photoshop の双一次補間)

4

1 に答える 1

9

Photoshop のアルゴリズムは、各ソース ピクセルの色がピクセルの中心にあると想定していますが、アルゴリズムは色が左上にあると想定しています。これにより、Photoshop と比較して、結果が 0.5 ピクセル上および左にシフトされます。

それを見る別の方法は、アルゴリズムが x 座標範囲(0, srcWidth)をにマッピングし、 (0, dstWidth)Photoshop が にマッピング(-0.5, srcWidth-0.5)(-0.5, dstWidth-0.5)、y 座標で同じ範囲をマッピングすることです。

それ以外の:

double sx = x * rx;
double sy = y * ry;

以下を使用できます。

double sx = (x + 0.5) * rx - 0.5;
double sy = (y + 0.5) * ry - 0.5;

同様の結果が得られます。sxこれにより、とが負の値になる可能性があることに注意してくださいsy

于 2012-05-23T13:19:01.117 に答える