5 Stimmen

Suche nach schnellen Bildverzerrungsalgorithmen

Ich versuche, eine Anwendung zu implementieren, die Shpere-Verzerrungsfilter verwendet. Ich verwende einen Algorithmus aus aquí die die Pixelposition durch die Methoden getPixel() und setpixel() ändert. Mein Problem ist, es ist zu langsam für Android-Geräte und es gibt Anwendungen, die gleiche Sphäre (und andere) Filter Weg schneller als mein Ansatz implementiert. (zum Beispiel Picsay Pro app) Könnte jemand teilen oder geben Richtung zu finden oder zu implementieren schnelle Verzerrung Algorithmen.

Tatsächlicher Filter, der den Algorithmus implementiert:

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;
}

Der Code, der die Positionen der berechneten Pixel ersetzt.

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;
}

5voto

Ich verwende derzeit denselben Algorithmus wie in Ihrem Link und er ist immer noch zu langsam für Android-Geräte

Von meinem Link in den Kommentaren oben :

Given
r = Sqrt((x - 0.5)^2 + (y - 0.5)^2)
a = ArcTan2(y - 0.5, x - 0.5)
n = Bulge factor (default = 1)

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

(Denken Sie daran, dass in dieser Gleichung, x y y von 0 bis 1 reichen. Wenn Ihre Abmessungen von 0 bis w ersetzen 0.5 con w/2 )

Verwendung von ein bisschen Mathe können wir feststellen, dass

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

Daraus ergibt sich die endgültige Gleichung

r = (x - 0.5)^2 + (y - 0.5)^2
n = Bulge factor (default = 0)

Set
x' = r^n \* (x - 0.5) + 0.5
y' = r^n \* (y - 0.5) + 0.5

(Ich habe die Quadratwurzel entfernt, da wir das Ergebnis sowieso in eine reelle Potenz umwandeln... also sollten wir, um dies wirklich äquivalent zu machen, Folgendes verwenden n/2 anstelle von n aber da wir Definition "Bulge-Faktor", wir können die zusätzliche Division einfach weglassen)

Mit nur einer Handvoll Multiplikationen und einer einzigen realen Potenzierung ist dies wahrscheinlich die schnellste Lösung, die man sich erhoffen kann.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X