寻找快速的图像畸变算法

5
我正在尝试实现一个应用程序,使用球形畸变滤波器。我正在使用这里的算法,通过使用getPixel()和setpixel()方法改变像素位置。我的问题是它对Android设备来说太慢了,并且有一些应用程序以比我更快的方式实现了同样的球形(和其他)滤波器(例如Picsay Pro应用程序)。是否有人可以分享或提供方向来查找或实现快速扭曲算法。
实际实现该算法的滤镜:
public boolean sphereFilter(Bitmap b, boolean bSmoothing)
{   
    int nWidth = b.getWidth();
    int nHeight = b.getHeight();

    Point  [][] pt = new Point[nWidth][nHeight];
    Point mid = new Point();
    mid.x = nWidth/2;
    mid.y = nHeight/2;

    double theta, radius;
    double newX, newY;

    for (int x = 0; x < nWidth; ++x)
        for (int y = 0; y < nHeight; ++y)
        {
            pt[x][y]= new Point();
        }

    for (int x = 0; x < nWidth; ++x)
        for (int y = 0; y < nHeight; ++y)
        {
            int trueX = x - mid.x;
            int trueY = y - mid.y;
            theta = Math.atan2((trueY),(trueX));

            radius = Math.sqrt(trueX*trueX + trueY*trueY);

            double newRadius = radius * radius/(Math.max(mid.x, mid.y));

            newX = mid.x + (newRadius * Math.cos(theta));

            if (newX > 0 && newX < nWidth)
            {
                pt[x][y].x = (int) newX;
            }
            else
            {
                pt[x][y].x = 0;
                pt[x][y].y = 0;
            }

            newY = mid.y + (newRadius * Math.sin(theta));

            if (newY > 0 && newY < nHeight && newX > 0 && newX < nWidth)
            {                   
                pt[x][ y].y = (int) newY;
            }
            else
            {
                pt[x][y].x = pt[x][y].y = 0;
            }
        }
    offsetFilterAbs(b, pt);
    return true;
}

替换计算像素位置的代码。
public boolean offsetFilterAbs(Bitmap b, Point[][] offset )
{
        int nWidth = b.getWidth();
        int nHeight = b.getHeight();

        int xOffset, yOffset;

        for(int y=0;y < nHeight;++y)
        {
            for(int x=0; x < nWidth; ++x )
            {   
                xOffset = offset[x][y].x;
                yOffset = offset[x][y].y;

                if (yOffset >= 0 && yOffset < nHeight && xOffset >= 0 && xOffset < nWidth)
                {
                    b.setPixel(x, y, b.getPixel(xOffset, yOffset));
                }                   
            }               
        }

    return true;
}

可能是图像变形-凸起效果算法的重复问题。 - BlueRaja - Danny Pflughoeft
是的,这几乎是一个重复的问题,但请注意,那个问题的被接受答案并不是你想要的 -- 你需要的是GLSL着色器。 - Jerry Coffin
@BlueRaja,我目前正在使用与您链接中的算法相同的算法,但对于Android设备来说仍然太慢了。 - Tony
@Tony请编辑你的问题。句子“我正在使用来自这里的算法”是不完整的...“这里”在哪里? - Dr. belisarius
@ belisarius 您是正确的,对不起。我已经添加了我从codeproject链接移植的代码。 - Tony
显示剩余2条评论
1个回答

5
我目前正在使用与您链接中的算法相同,但对于Android设备来说仍然太慢了。
从我在上面的评论中提供的链接
给定 r = Sqrt((x - 0.5)^2 + (y - 0.5)^2) a = ArcTan2(y - 0.5, x - 0.5) n = Bulge factor(默认值= 1)
设置 x' = r ^ n * Cos(a) + 0.5 y' = r ^ n * Sin(a) + 0.5
(请记住,在此方程中,xy跨越从0到1。如果您的尺寸跨越从0到w,请用w/2替换0.5
使用一点数学知识, 我们可以看到
Cos(a) = Cos(ArcTan2(y - 0.5, x - 0.5))
       = (x - 0.5)/r
Sin(a) = Sin(ArcTan2(y - 0.5, x - 0.5))
       = (y - 0.5)/r

这使得最终结果方程为:

r = (x - 0.5)^2 + (y - 0.5)^2
n = 凸度因子(默认=0)
设 x' = r^n * (x - 0.5) + 0.5 y' = r^n * (y - 0.5) + 0.5

(我删除了平方根,因为我们无论如何都将结果带到实数幂...所以真正要使它等效,我们应该使用n/2而不是n,但由于我们正在定义“凸度因子”,因此可以省略额外的除法)

仅需少量乘法和单个实数幂运算,这可能是您所能期望的最快方法。


1
+1 我不打算回答这个问题,因为我对 Android-fu 一窍不通。但是也许发帖者应该在他的代码上尝试一些基本的剖析,并查看哪些是主要的时间消耗者。或者也许消除多余的三角函数操作就足够了。 - Dr. belisarius
@ belisarius 我已经尝试过对我的代码进行分析,发现计算新的x、y位置和替换它们这两个函数每个都需要大约2000毫秒,与"Picsay Pro"相比太差了。 - Tony
1
@Tony Picsay Pro 可能使用OpenGL来实现这个功能,而且不会创建成千上万个不必要的Point对象。 - BlueRaja - Danny Pflughoeft
你说的关于Point对象的问题是正确的,在我的辩护中,我只是从原始链接移植了代码。 - Tony

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接