我正在尝试实现使用shpere失真滤波器的应用程序。我正在使用here中的算法,该算法通过getPixel()和setpixel()方法更改像素位置。我的问题是,对于Android设备而言,它太慢了,并且有些应用程序比我的方法更快地实现相同的sphere(和其他)过滤器方法。 (例如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;
}

最佳答案



从我的link in the comments above:

给定
r = Sqrt((x-0.5)^ 2 +(y-0.5)^ 2)
a = ArcTan2(y-0.5,x-0.5)
n =膨胀系数(默认= 1)


x'= r ^ n * Cos(a)+ 0.5
y'= r ^ n * Sin(a)+ 0.5

(请记住,在此等式中,xy的范围从0到1。如果尺寸范围从0到w,则将0.5替换为w/2)

使用a bit of math,我们可以看到

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,但是由于我们定义的是“膨胀因子”,所以我们可以离开除去额外的划分)

仅需少量的乘法运算和一个实数幂运算,这可能是您希望获得的最快速度。

10-08 04:17