簡體   English   中英

正確實現盒式重采樣算法

[英]Correctly implementing a box resampling algorithm

我實現了一個重采樣算法,該算法可以與除盒形(最近鄰域)實現之外的所有其他方法配合使用,並且我一生無法弄清楚自己做錯了什么。 我有許多可行的示例(bicubic,lanczos,hermite,triangle等),因此我確定問題在特定實現中很簡單。

誰能看到我做錯了嗎?

可在此處找到我的重采樣器的完整源代碼以進行調試

這是我用於所有算法的大小調整方法:

protected override void Apply(ImageBase target, ImageBase source, Rectangle targetRectangle, Rectangle sourceRectangle, int startY, int endY)
{
    int sourceWidth = source.Width;
    int sourceHeight = source.Height;

    int width = target.Width;
    int height = target.Height;

    int targetY = targetRectangle.Y;
    int startX = targetRectangle.X;
    int endX = targetRectangle.Right;
    int right = (int)(this.Sampler.Radius + .5);
    int left = -right;

    // Scaling factors
    double widthFactor = sourceWidth / (double)targetRectangle.Width;
    double heightFactor = sourceHeight / (double)targetRectangle.Height;

    // Width and height decreased by 1
    int maxHeight = sourceHeight - 1;
    int maxWidth = sourceWidth - 1;

    for (int y = startY; y < endY; y++)
    {
        if (y >= 0 && y < height)
        {
            // Y coordinates of source points.
            double originY = ((y - targetY) * heightFactor) - 0.5;
            int originY1 = (int)originY;
            double dy = originY - originY1;

            // For each row.
            for (int x = startX; x < endX; x++)
            {
                if (x >= 0 && x < width)
                {
                    // X coordinates of source points.
                    double originX = ((x - startX) * widthFactor) - 0.5f;
                    int originX1 = (int)originX;
                    double dx = originX - originX1;

                    // Destination color components
                    double r = 0;
                    double g = 0;
                    double b = 0;
                    double a = 0;

                    for (int yy = left; yy <= right; yy++)
                    {
                        // Get Y cooefficient
                        double kernel1 = this.Sampler.GetValue(dy - yy);

                        if (Math.Abs(kernel1) < Epsilon)
                        {
                            continue;
                        }

                        int originY2 = originY1 + yy;
                        if (originY2 < 0)
                        {
                            originY2 = 0;
                        }

                        if (originY2 > maxHeight)
                        {
                            originY2 = maxHeight;
                        }

                        for (int xx = left; xx <= right; xx++)
                        {
                            // Get X cooefficient
                            double kernel2 = kernel1 * this.Sampler.GetValue(xx - dx);

                            if (Math.Abs(kernel2) < Epsilon)
                            {
                                continue;
                            }

                            int originX2 = originX1 + xx;
                            if (originX2 < 0)
                            {
                                originX2 = 0;
                            }

                            if (originX2 > maxWidth)
                            {
                                originX2 = maxWidth;
                            }

                            Bgra sourceColor = source[originX2, originY2];

                            r += kernel2 * sourceColor.R;
                            g += kernel2 * sourceColor.G;
                            b += kernel2 * sourceColor.B;
                            a += kernel2 * sourceColor.A;
                        }
                    }

                    Bgra destinationColor = new Bgra(b.ToByte(), g.ToByte(), r.ToByte(), a.ToByte());
                    target[x, y] = destinationColor;
                }
            }
        }
    }
}

這是可行的雙三次算法的實現,而無效的盒算法的實現。

雙三次

public class BicubicResampler : IResampler
{
    /// <inheritdoc/>
    public double Radius => 2;

    /// <inheritdoc/>
    public double GetValue(double x)
    {
        // The coefficient.
        double a = -0.5;

        if (x < 0)
        {
            x = -x;
        }

        double result = 0;

        if (x <= 1)
        {
            result = (((1.5 * x) - 2.5) * x * x) + 1;
        }
        else if (x < 2)
        {
            result = (((((a * x) + 2.5) * x) - 4) * x) + 2;
        }

        return result;
    }
}

public class BoxResampler : IResampler
{
    /// <inheritdoc/>
    public double Radius => 0.5;

    /// <inheritdoc/>
    public double GetValue(double x)
    {
        if (x < 0)
        {
            x = -x;
        }

        if (x <= 0.5)
        {
            return 1;
        }

        return 0;
    }
}

雙三次輸出良好。

雙三次采樣器輸出

盒子少一點...

在此處輸入圖片說明

替換您的函數,該函數解析為return (x >= -0.5) && (x <= 0.5) ? 1 : 0 return (x >= -0.5) && (x <= 0.5) ? 1 : 0 return (x >= -0.5) && (x < 0.5) ? 1 : 0 return (x >= -0.5) && (x < 0.5) ? 1 : 0可行嗎?

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM