5

Sto cercando di implementare un'applicazione che utilizza il filtro di distorsione shpere. Sto usando un algoritmo da here che cambia la posizione dei pixel con i metodi getPixel() e setpixel(). Il mio problema è che è troppo lento per i dispositivi Android e ci sono applicazioni che implementano la stessa sfera (e altre) in modo più veloce del mio approccio. (ad esempio l'app Picsay Pro) Qualcuno potrebbe condividere o dare indicazioni per trovare o implementare algoritmi di distorsione veloce.Alla ricerca di algoritmi di distorsione dell'immagine veloce

filtro effettivo che implementa l'algoritmo:

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

Il codice che sostituisce le posizioni dei pixel calcolate.

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

possibile duplicato di [Image Warping - Bulge Effect Algorithm] (http://stackoverflow.com/questions/5055625/image-warping-bulge-effect-algorithm) –

+0

Sì, è praticamente un duplicato, ma si noti che il risposta accettata a questa domanda è * non * proprio quella che vuoi qui - quello che vuoi è lo shader GLSL. –

+0

@BlueRaja, attualmente sto usando lo stesso algoritmo con quello sul tuo link ed è ancora troppo lento per i dispositivi Android – Tony

risposta

5

Attualmente sto usando lo stesso algoritmo con quella sul tuo link già ed è ancora troppo lento per dispositivi Android

Dal mio link in the comments above:

 
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 

(Ricorda che, in questa equazione, x e intervallo da 0 a 1. Se le tue dimensioni spaziano da 0 a w, sostituire 0.5 con w/2)

Usando a bit of math, possiamo vedere che

 
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 

Questo rende l'equazione risultante finale

 
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 

(ho rimosso la radice quadrata quanto prendiamo il risultato per una vera potenza comunque ... quindi davvero per rendere questo equivalente dovremmo usare n/2 invece di n, ma si nce stiamo definendo "bulge-factor", siamo in grado di lasciare la divisione in più)

Con solo una manciata di moltiplicazioni e una sola reale elevamento a potenza, questo è probabilmente il più veloce si può sperare di ottenere.

+1

+1 Non ho intenzione di rispondere a questo perché il mio Android-fu è nullo. Ma forse l'OP dovrebbe provare alcuni profili di base sul suo codice e vedere quali sono i consumatori dominanti del tempo. O forse è sufficiente l'eliminazione delle superflue operazioni. –

+0

@ belisarius ho provato a profilare il mio codice ed entrambe le funzioni (calcolando le nuove posizioni x, y e sostituendole) impiegano circa 2000ms per ciascuna che è troppo povera rispetto a "Picsay Pro". – Tony

+1

@Tony * Picsay Pro * probabilmente lo fa usando OpenGL ... e senza creare migliaia di inutili oggetti Point. –