2009-12-18 21 views
5

Sto cercando modi per creare l'effetto lente fisheye, ho esaminato le documentazioni per openCV, sembra che contenga funzioni di calibrazione della fotocamera per distorsioni radiali come il fisheye. È possibile simulare la distorsione fisheye da openCV?Come simulare l'effetto lente fisheye di openCV?

Se è possibile farlo da openCV, confrontandolo con openGL, quale genererà risultati migliori? Grazie.

risposta

13

ho creato this app utilizzando OpenCV. È questo l'effetto a cui ti stai riferendo? Io fondamentalmente codificato la formula indicata su di Wikipedia "Distorsione (ottica)" Posso mostrare il codice, se necessario

Aggiornamento: OK, così in basso è il codice vero e proprio scritto in C++ utilizzando OpenCV (non documentato quindi sentitevi liberi per chiedere spiegazioni): Il programma riceve come input il seguente parametro: | immagine ingresso | | immagine di uscita | | K che controlla la quantità di distorsione (in genere prova valori intorno a 0,001) | | coordinate x del centro di distorsione | | y coordinate del centro di distorsione |

Quindi il nodo del programma è la doppia per ciclo che itera pixel per pixel dell'immagine risultato su e cerca il pixel corrispondente dell'immagine in ingresso utilizzando la formula di distorsione radiale (questa è la deformazione dell'immagine modo è generalmente fatto - forse contro intuitivamente dalla retroproiezione dall'output all'input). Ci sono alcune sottigliezze che hanno a che fare con la scala dell'immagine di output (in questo programma l'immagine risultante ha le stesse dimensioni dell'input), e io non entrerò in essa a meno che non vogliate entrare in maggiori dettagli.

#include <cv.h> 
    #include <highgui.h> 
    #include <math.h> 
    #include <unistd.h> 
    #include <getopt.h> 
    #include <iostream> 


    void sampleImage(const IplImage* arr, float idx0, float idx1, CvScalar& res) 
    { 
     if(idx0<0 || idx1<0 || idx0>(cvGetSize(arr).height-1) || idx1>(cvGetSize(arr).width-1)){ 
     res.val[0]=0; 
     res.val[1]=0; 
     res.val[2]=0; 
     res.val[3]=0; 
     return; 
     } 
     float idx0_fl=floor(idx0); 
     float idx0_cl=ceil(idx0); 
     float idx1_fl=floor(idx1); 
     float idx1_cl=ceil(idx1); 

     CvScalar s1=cvGet2D(arr,(int)idx0_fl,(int)idx1_fl); 
     CvScalar s2=cvGet2D(arr,(int)idx0_fl,(int)idx1_cl); 
     CvScalar s3=cvGet2D(arr,(int)idx0_cl,(int)idx1_cl); 
     CvScalar s4=cvGet2D(arr,(int)idx0_cl,(int)idx1_fl); 
     float x = idx0 - idx0_fl; 
     float y = idx1 - idx1_fl; 
     res.val[0]= s1.val[0]*(1-x)*(1-y) + s2.val[0]*(1-x)*y + s3.val[0]*x*y + s4.val[0]*x*(1-y); 
     res.val[1]= s1.val[1]*(1-x)*(1-y) + s2.val[1]*(1-x)*y + s3.val[1]*x*y + s4.val[1]*x*(1-y); 
     res.val[2]= s1.val[2]*(1-x)*(1-y) + s2.val[2]*(1-x)*y + s3.val[2]*x*y + s4.val[2]*x*(1-y); 
     res.val[3]= s1.val[3]*(1-x)*(1-y) + s2.val[3]*(1-x)*y + s3.val[3]*x*y + s4.val[3]*x*(1-y); 
    } 

    float xscale; 
    float yscale; 
    float xshift; 
    float yshift; 

    float getRadialX(float x,float y,float cx,float cy,float k){ 
     x = (x*xscale+xshift); 
     y = (y*yscale+yshift); 
     float res = x+((x-cx)*k*((x-cx)*(x-cx)+(y-cy)*(y-cy))); 
     return res; 
    } 

    float getRadialY(float x,float y,float cx,float cy,float k){ 
     x = (x*xscale+xshift); 
     y = (y*yscale+yshift); 
     float res = y+((y-cy)*k*((x-cx)*(x-cx)+(y-cy)*(y-cy))); 
     return res; 
    } 

    float thresh = 1; 
    float calc_shift(float x1,float x2,float cx,float k){ 
     float x3 = x1+(x2-x1)*0.5; 
     float res1 = x1+((x1-cx)*k*((x1-cx)*(x1-cx))); 
     float res3 = x3+((x3-cx)*k*((x3-cx)*(x3-cx))); 

     // std::cerr<<"x1: "<<x1<<" - "<<res1<<" x3: "<<x3<<" - "<<res3<<std::endl; 

     if(res1>-thresh and res1 < thresh) 
     return x1; 
     if(res3<0){ 
     return calc_shift(x3,x2,cx,k); 
     } 
     else{ 
     return calc_shift(x1,x3,cx,k); 
     } 
    } 

    int main(int argc, char** argv) 
    { 
     IplImage* src = cvLoadImage(argv[1], 1); 
     IplImage* dst = cvCreateImage(cvGetSize(src),src->depth,src->nChannels); 
     IplImage* dst2 = cvCreateImage(cvGetSize(src),src->depth,src->nChannels); 
     float K=atof(argv[3]); 
     float centerX=atoi(argv[4]); 
     float centerY=atoi(argv[5]); 
     int width = cvGetSize(src).width; 
     int height = cvGetSize(src).height; 

     xshift = calc_shift(0,centerX-1,centerX,K); 
     float newcenterX = width-centerX; 
     float xshift_2 = calc_shift(0,newcenterX-1,newcenterX,K); 

     yshift = calc_shift(0,centerY-1,centerY,K); 
     float newcenterY = height-centerY; 
     float yshift_2 = calc_shift(0,newcenterY-1,newcenterY,K); 
     // scale = (centerX-xshift)/centerX; 
     xscale = (width-xshift-xshift_2)/width; 
     yscale = (height-yshift-yshift_2)/height; 

     std::cerr<<xshift<<" "<<yshift<<" "<<xscale<<" "<<yscale<<std::endl; 
     std::cerr<<cvGetSize(src).height<<std::endl; 
     std::cerr<<cvGetSize(src).width<<std::endl; 

     for(int j=0;j<cvGetSize(dst).height;j++){ 
     for(int i=0;i<cvGetSize(dst).width;i++){ 
      CvScalar s; 
      float x = getRadialX((float)i,(float)j,centerX,centerY,K); 
      float y = getRadialY((float)i,(float)j,centerX,centerY,K); 
      sampleImage(src,y,x,s); 
      cvSet2D(dst,j,i,s); 

     } 
     } 
    #if 0 
     cvNamedWindow("Source1", 1); 
     cvShowImage("Source1", dst); 
     cvWaitKey(0); 
    #endif 

     cvSaveImage(argv[2],dst,0); 

    #if 0 
     for(int j=0;j<cvGetSize(src).height;j++){ 
     for(int i=0;i<cvGetSize(src).width;i++){ 
      CvScalar s; 
      sampleImage(src,j+0.25,i+0.25,s); 
      cvSet2D(dst,j,i,s); 
     } 
     } 

     cvNamedWindow("Source1", 1); 
     cvShowImage("Source1", src); 
     cvWaitKey(0); 

    #endif 

} 
+0

Sì! La distorsione a barilotto nella pagina "Distortion (ottica)" di Wiki è esattamente quello che sto cercando! Mi piacerebbe sapere come mappare un'immagine attorno agli obiettivi fisheye con openCV. Puoi mostrare il tuo codice qui? Oppure mostrami qualche suggerimento? Grazie. Cordiali saluti – 0pcl

+0

Ho cercato di capire il codice, ma sono leggermente rallentato, con molte operazioni che non so perché si verificano. È possibile aggiungere un breve riassunto o una descrizione? –

0

Si desidera utilizzare questa distorsione su immagini sintetiche o si desidera applicare a una videocamera o qualcosa del genere?

In OpenCV si dovrebbe essere in grado di fare la calibrazione della fotocamera (usando le funzioni built-in, algoritmo di Zhang) ..

In OpenGL vedere questo.

saluti

2

Grazie a voi per quel codice. Mi aiuta molto. L'ho crittografato per Java. Forse qualcuno ha una funzione simile per simulare la distorsione tangenziale?

import java.awt.image.BufferedImage; 
import java.io.File; 
import java.io.IOException; 
import javax.imageio.ImageIO; 
import com.jhlabs.image.InterpolateFilter; 

class Filters{ 
    float xscale; 
    float yscale; 
    float xshift; 
    float yshift; 
    int [] s; 
    public Filters(){ 

    } 

    public BufferedImage barrel (BufferedImage input, float k){ 

     float centerX=input.getWidth()/2; //center of distortion 
     float centerY=input.getHeight()/2; 

     int width = input.getWidth(); //image bounds 
     int height = input.getHeight(); 

     BufferedImage dst = new BufferedImage(width, height,BufferedImage.TYPE_INT_RGB); //output pic 

      xshift = calc_shift(0,centerX-1,centerX,k); 
      float newcenterX = width-centerX; 
      float xshift_2 = calc_shift(0,newcenterX-1,newcenterX,k); 

      yshift = calc_shift(0,centerY-1,centerY,k); 
      float newcenterY = height-centerY; 
      float yshift_2 = calc_shift(0,newcenterY-1,newcenterY,k); 

      xscale = (width-xshift-xshift_2)/width; 
      yscale = (height-yshift-yshift_2)/height; 

      for(int j=0;j<dst.getHeight();j++){ 
       for(int i=0;i<dst.getWidth();i++){ 
       float x = getRadialX((float)i,(float)j,centerX,centerY,k); 
       float y = getRadialY((float)i,(float)j,centerX,centerY,k); 
       sampleImage(input,x,y); 
       int color = ((s[1]&0x0ff)<<16)|((s[2]&0x0ff)<<8)|(s[3]&0x0ff); 
    //   System.out.print(i+" "+j+" \\"); 

       dst.setRGB(i, j, color); 

       } 
      } 
     return dst; 
    } 

    void sampleImage(BufferedImage arr, float idx0, float idx1) 
    { 
     s = new int [4]; 
     if(idx0<0 || idx1<0 || idx0>(arr.getHeight()-1) || idx1>(arr.getWidth()-1)){ 
     s[0]=0; 
     s[1]=0; 
     s[2]=0; 
     s[3]=0; 
     return; 
     } 

     float idx0_fl=(float) Math.floor(idx0); 
     float idx0_cl=(float) Math.ceil(idx0); 
     float idx1_fl=(float) Math.floor(idx1); 
     float idx1_cl=(float) Math.ceil(idx1); 

     int [] s1 = getARGB(arr,(int)idx0_fl,(int)idx1_fl); 
     int [] s2 = getARGB(arr,(int)idx0_fl,(int)idx1_cl); 
     int [] s3 = getARGB(arr,(int)idx0_cl,(int)idx1_cl); 
     int [] s4 = getARGB(arr,(int)idx0_cl,(int)idx1_fl); 

     float x = idx0 - idx0_fl; 
     float y = idx1 - idx1_fl; 

     s[0]= (int) (s1[0]*(1-x)*(1-y) + s2[0]*(1-x)*y + s3[0]*x*y + s4[0]*x*(1-y)); 
     s[1]= (int) (s1[1]*(1-x)*(1-y) + s2[1]*(1-x)*y + s3[1]*x*y + s4[1]*x*(1-y)); 
     s[2]= (int) (s1[2]*(1-x)*(1-y) + s2[2]*(1-x)*y + s3[2]*x*y + s4[2]*x*(1-y)); 
     s[3]= (int) (s1[3]*(1-x)*(1-y) + s2[3]*(1-x)*y + s3[3]*x*y + s4[3]*x*(1-y)); 
    } 

    int [] getARGB(BufferedImage buf,int x, int y){ 
     int rgb = buf.getRGB(x, y); // Returns by default ARGB. 
     int [] scalar = new int[4]; 
     scalar[0] = (rgb >>> 24) & 0xFF; 
     scalar[1] = (rgb >>> 16) & 0xFF; 
     scalar[2] = (rgb >>> 8) & 0xFF; 
     scalar[3] = (rgb >>> 0) & 0xFF; 
     return scalar; 
    } 

    float getRadialX(float x,float y,float cx,float cy,float k){ 
     x = (x*xscale+xshift); 
     y = (y*yscale+yshift); 
     float res = x+((x-cx)*k*((x-cx)*(x-cx)+(y-cy)*(y-cy))); 
     return res; 
    } 

    float getRadialY(float x,float y,float cx,float cy,float k){ 
     x = (x*xscale+xshift); 
     y = (y*yscale+yshift); 
     float res = y+((y-cy)*k*((x-cx)*(x-cx)+(y-cy)*(y-cy))); 
     return res; 
    } 

    float thresh = 1; 

    float calc_shift(float x1,float x2,float cx,float k){ 
     float x3 = (float)(x1+(x2-x1)*0.5); 
     float res1 = x1+((x1-cx)*k*((x1-cx)*(x1-cx))); 
     float res3 = x3+((x3-cx)*k*((x3-cx)*(x3-cx))); 

     if(res1>-thresh && res1 < thresh) 
     return x1; 
     if(res3<0){ 
     return calc_shift(x3,x2,cx,k); 
     } 
     else{ 
     return calc_shift(x1,x3,cx,k); 
     } 
    } 
} 
+0

ciao, questo codice java è esattamente quello di cui ho bisogno. sto provando a creare lo stesso efect su Android ma non posso usare bufferedimage, dato che Android non lo supporta. c'è un modo per ottenere questo codice in esecuzione su Android? ogni aiuto sarebbe apprezzato, grazie matt – turtleboy

5

Grazie al 2 sopra per questo codice. Ho modificato il codice trascritto sopra in Java per usare Bitmap invece di BufferedImage. Ciò consente al codice di funzionare su Android (che non supporta AWT). Ho anche reso l'effetto semplicemente manipolare i pixel in un cerchio piuttosto che l'intera bitmap, questo dà un effetto "lente" fisheye. Spero che questo aiuti gli sviluppatori Android.

import android.graphics.Bitmap; 
import android.util.Log; 

class Filters{ 
    float xscale; 
    float yscale; 
    float xshift; 
    float yshift; 
    int [] s; 
    private String TAG = "Filters"; 
    public Filters(){ 

     Log.e(TAG, "***********inside constructor"); 
    } 

    public Bitmap barrel (Bitmap input, float k){ 
     Log.e(TAG, "***********inside barrel method "); 
     float centerX=input.getWidth()/2; //center of distortion 
     float centerY=input.getHeight()/2; 

     int width = input.getWidth(); //image bounds 
     int height = input.getHeight(); 

     Bitmap dst = Bitmap.createBitmap(width, height,input.getConfig()); //output pic 
     Log.e(TAG, "***********dst bitmap created "); 
      xshift = calc_shift(0,centerX-1,centerX,k); 
      float newcenterX = width-centerX; 
      float xshift_2 = calc_shift(0,newcenterX-1,newcenterX,k); 

      yshift = calc_shift(0,centerY-1,centerY,k); 
      float newcenterY = height-centerY; 
      float yshift_2 = calc_shift(0,newcenterY-1,newcenterY,k); 

      xscale = (width-xshift-xshift_2)/width; 
      yscale = (height-yshift-yshift_2)/height; 
      Log.e(TAG, "***********about to loop through bm"); 
      /*for(int j=0;j<dst.getHeight();j++){ 
       for(int i=0;i<dst.getWidth();i++){ 
       float x = getRadialX((float)i,(float)j,centerX,centerY,k); 
       float y = getRadialY((float)i,(float)j,centerX,centerY,k); 
       sampleImage(input,x,y); 
       int color = ((s[1]&0x0ff)<<16)|((s[2]&0x0ff)<<8)|(s[3]&0x0ff); 
    //   System.out.print(i+" "+j+" \\"); 

       dst.setPixel(i, j, color); 

       } 
      }*/ 

      int origPixel; // the pixel in orig image 

      for(int j=0;j<dst.getHeight();j++){ 
       for(int i=0;i<dst.getWidth();i++){ 
       origPixel= input.getPixel(i,j); 
       float x = getRadialX((float)i,(float)j,centerX,centerY,k); 
       float y = getRadialY((float)i,(float)j,centerX,centerY,k); 
       sampleImage(input,x,y); 
       int color = ((s[1]&0x0ff)<<16)|((s[2]&0x0ff)<<8)|(s[3]&0x0ff); 
    //   System.out.print(i+" "+j+" \\"); 


// check whether a pixel is within the circle bounds of 150 

       if(Math.sqrt(Math.pow(i - centerX, 2) + (Math.pow(j - centerY, 2))) <= 150){ 
       dst.setPixel(i, j, color); 
       }else{ 
        dst.setPixel(i,j,origPixel); 
       } 
       } 
      } 
     return dst; 
    } 

    void sampleImage(Bitmap arr, float idx0, float idx1) 
    { 
     s = new int [4]; 
     if(idx0<0 || idx1<0 || idx0>(arr.getHeight()-1) || idx1>(arr.getWidth()-1)){ 
     s[0]=0; 
     s[1]=0; 
     s[2]=0; 
     s[3]=0; 
     return; 
     } 

     float idx0_fl=(float) Math.floor(idx0); 
     float idx0_cl=(float) Math.ceil(idx0); 
     float idx1_fl=(float) Math.floor(idx1); 
     float idx1_cl=(float) Math.ceil(idx1); 

     int [] s1 = getARGB(arr,(int)idx0_fl,(int)idx1_fl); 
     int [] s2 = getARGB(arr,(int)idx0_fl,(int)idx1_cl); 
     int [] s3 = getARGB(arr,(int)idx0_cl,(int)idx1_cl); 
     int [] s4 = getARGB(arr,(int)idx0_cl,(int)idx1_fl); 

     float x = idx0 - idx0_fl; 
     float y = idx1 - idx1_fl; 

     s[0]= (int) (s1[0]*(1-x)*(1-y) + s2[0]*(1-x)*y + s3[0]*x*y + s4[0]*x*(1-y)); 
     s[1]= (int) (s1[1]*(1-x)*(1-y) + s2[1]*(1-x)*y + s3[1]*x*y + s4[1]*x*(1-y)); 
     s[2]= (int) (s1[2]*(1-x)*(1-y) + s2[2]*(1-x)*y + s3[2]*x*y + s4[2]*x*(1-y)); 
     s[3]= (int) (s1[3]*(1-x)*(1-y) + s2[3]*(1-x)*y + s3[3]*x*y + s4[3]*x*(1-y)); 
    } 

    int [] getARGB(Bitmap buf,int x, int y){ 
     int rgb = buf.getPixel(y, x); // Returns by default ARGB. 
     int [] scalar = new int[4]; 
     scalar[0] = (rgb >>> 24) & 0xFF; 
     scalar[1] = (rgb >>> 16) & 0xFF; 
     scalar[2] = (rgb >>> 8) & 0xFF; 
     scalar[3] = (rgb >>> 0) & 0xFF; 
     return scalar; 
    } 

    float getRadialX(float x,float y,float cx,float cy,float k){ 
     x = (x*xscale+xshift); 
     y = (y*yscale+yshift); 
     float res = x+((x-cx)*k*((x-cx)*(x-cx)+(y-cy)*(y-cy))); 
     return res; 
    } 

    float getRadialY(float x,float y,float cx,float cy,float k){ 
     x = (x*xscale+xshift); 
     y = (y*yscale+yshift); 
     float res = y+((y-cy)*k*((x-cx)*(x-cx)+(y-cy)*(y-cy))); 
     return res; 
    } 

    float thresh = 1; 

    float calc_shift(float x1,float x2,float cx,float k){ 
     float x3 = (float)(x1+(x2-x1)*0.5); 
     float res1 = x1+((x1-cx)*k*((x1-cx)*(x1-cx))); 
     float res3 = x3+((x3-cx)*k*((x3-cx)*(x3-cx))); 

     if(res1>-thresh && res1 < thresh) 
     return x1; 
     if(res3<0){ 
     return calc_shift(x3,x2,cx,k); 
     } 
     else{ 
     return calc_shift(x1,x3,cx,k); 
     } 
    } 
} 

.

import java.util.concurrent.Callable; 
import java.util.concurrent.ExecutorService; 
import java.util.concurrent.Executors; 
import java.util.concurrent.FutureTask; 

import android.graphics.Bitmap; 
import android.graphics.drawable.BitmapDrawable; 
import android.os.Debug; 
import android.util.Log; 

public class MultiRuntimeProcessorFilter { 



    private static final String TAG = "mrpf"; 
    private int x = 0; 
    private Bitmap input = null; 
    private int radius; 


    public void createBitmapSections(int nOp, int[] sections){ 

     int processors = nOp; 
     int jMax = input.getHeight(); 
     int aSectionSize = (int) Math.ceil(jMax/processors); 
     Log.e(TAG, "++++++++++ sections size = "+aSectionSize); 


     int k = 0; 
     for(int h=0; h<processors+1; h++){ 

       sections[h] = k; 
       k+= aSectionSize; 



     } 
    }// end of createBitmapSections() 



    @SuppressWarnings("unchecked") 
    public Bitmap barrel (Bitmap input, float k, int r){ 
      this.radius = r; 
      this.input = input; 
      int []arr = new int[input.getWidth()*input.getHeight()]; 


      Log.e(TAG, "bitmap height = "+input.getHeight()); 




      int nrOfProcessors = Runtime.getRuntime().availableProcessors(); 
      Log.e(TAG, "no of processors = "+nrOfProcessors); 

      int[] sections = new int[nrOfProcessors+1]; 


      createBitmapSections(nrOfProcessors,sections); 
      ExecutorService threadPool = Executors.newFixedThreadPool(nrOfProcessors); 

      for(int g=0; g<sections.length;g++){ 
       Log.e(TAG, "++++++++++ sections= "+sections[g]); 
      } 

     // ExecutorService threadPool = Executors.newFixedThreadPool(nrOfProcessors); 

      Object[] task = new Object[nrOfProcessors]; 

      for(int z = 0; z < nrOfProcessors; z++){ 
      task[z] = (FutureTask<PartialResult>) threadPool.submit(new PartialProcessing(sections[z], sections[z+1] - 1, input, k)); 
      Log.e(TAG, "++++++++++ task"+z+"= "+task[z].toString()); 
      } 

     PartialResult[] results = new PartialResult[nrOfProcessors]; 

     try{ 
       for(int t = 0; t < nrOfProcessors; t++){ 

        results[t] = ((FutureTask<PartialResult>) task[t]).get(); 

        results[t].fill(arr); 
       } 

      }catch(Exception e){ 
       e.printStackTrace(); 
      } 

      Bitmap dst2 = Bitmap.createBitmap(arr,input.getWidth(),input.getHeight(),input.getConfig()); 


     return dst2; 


     }//end of barrel() 




    public class PartialResult { 
      int startP; 
      int endP; 
      int[] storedValues; 

      public PartialResult(int startp, int endp, Bitmap input){ 

       this.startP = startp; 
       this.endP = endp; 
       this.storedValues = new int[input.getWidth()*input.getHeight()]; 


      } 

      public void addValue(int p, int result) { 
       storedValues[p] = result; 

      } 

      public void fill(int[] arr) { 



       for (int p = startP; p < endP; p++){ 
        for(int b=0;b<radius;b++,x++) 
       arr[x] = storedValues[x]; 

       } 
       Log.e(TAG, "++++++++++ x ="+x); 
       } 

      }//end of partialResult 




    public class PartialProcessing implements Callable<PartialResult> { 
     int startJ; 
     int endJ; 


     private int[] scalar; 
     private float xscale; 
     private float yscale; 
     private float xshift; 
     private float yshift; 
     private float thresh = 1; 
     private int [] s1; 
     private int [] s2; 
     private int [] s3; 
     private int [] s4; 
     private int [] s; 
     private Bitmap input; 
     private float k; 



     public PartialProcessing(int startj, int endj, Bitmap input, float k) { 

      this.startJ = startj; 
      this.endJ = endj; 
      this.input = input; 
      this.k = k; 

      s = new int[4]; 
      scalar = new int[4]; 
      s1 = new int[4]; 
      s2 = new int[4]; 
      s3 = new int[4]; 
      s4 = new int[4]; 

     } 

     int [] getARGB(Bitmap buf,int x, int y){ 

      int rgb = buf.getPixel(y, x); // Returns by default ARGB. 
      // int [] scalar = new int[4]; 
      // scalar[0] = (rgb >>> 24) & 0xFF; 
      scalar[1] = (rgb >>> 16) & 0xFF; 
      scalar[2] = (rgb >>> 8) & 0xFF; 
      scalar[3] = (rgb >>> 0) & 0xFF; 
      return scalar; 

     } 



     float getRadialX(float x,float y,float cx,float cy,float k){ 

      x = (x*xscale+xshift); 
      y = (y*yscale+yshift); 
      float res = x+((x-cx)*k*((x-cx)*(x-cx)+(y-cy)*(y-cy))); 
      return res; 
      } 

      float getRadialY(float x,float y,float cx,float cy,float k){ 

      x = (x*xscale+xshift); 
      y = (y*yscale+yshift); 
      float res = y+((y-cy)*k*((x-cx)*(x-cx)+(y-cy)*(y-cy))); 
      return res; 
      } 



      float calc_shift(float x1,float x2,float cx,float k){ 

      float x3 = (float)(x1+(x2-x1)*0.5); 
      float res1 = x1+((x1-cx)*k*((x1-cx)*(x1-cx))); 
      float res3 = x3+((x3-cx)*k*((x3-cx)*(x3-cx))); 

      if(res1>-thresh && res1 < thresh) 
       return x1; 
      if(res3<0){ 
       return calc_shift(x3,x2,cx,k); 
      } 
      else{ 
       return calc_shift(x1,x3,cx,k); 
      } 
      } 


      void sampleImage(Bitmap arr, float idx0, float idx1) 
      { 

      // s = new int [4]; 
      if(idx0<0 || idx1<0 || idx0>(arr.getHeight()-1) || idx1>(arr.getWidth()-1)){ 
       s[0]=0; 
       s[1]=0; 
       s[2]=0; 
       s[3]=0; 
       return; 
      } 

      float idx0_fl=(float) Math.floor(idx0); 
      float idx0_cl=(float) Math.ceil(idx0); 
      float idx1_fl=(float) Math.floor(idx1); 
      float idx1_cl=(float) Math.ceil(idx1); 



      s1 = getARGB(arr,(int)idx0_fl,(int)idx1_fl); 
      s2 = getARGB(arr,(int)idx0_fl,(int)idx1_cl); 
      s3 = getARGB(arr,(int)idx0_cl,(int)idx1_cl); 
      s4 = getARGB(arr,(int)idx0_cl,(int)idx1_fl); 

      float x = idx0 - idx0_fl; 
      float y = idx1 - idx1_fl; 

      // s[0]= (int) (s1[0]*(1-x)*(1-y) + s2[0]*(1-x)*y + s3[0]*x*y + s4[0]*x*(1-y)); 
      s[1]= (int) (s1[1]*(1-x)*(1-y) + s2[1]*(1-x)*y + s3[1]*x*y + s4[1]*x*(1-y)); 
      s[2]= (int) (s1[2]*(1-x)*(1-y) + s2[2]*(1-x)*y + s3[2]*x*y + s4[2]*x*(1-y)); 
      s[3]= (int) (s1[3]*(1-x)*(1-y) + s2[3]*(1-x)*y + s3[3]*x*y + s4[3]*x*(1-y)); 


      } 



     @Override public PartialResult call() { 

      PartialResult partialResult = new PartialResult(startJ, endJ,input); 

      float centerX=input.getWidth()/2; //center of distortion 
      float centerY=input.getHeight()/2; 



      int width = input.getWidth(); //image bounds 
      int height = input.getHeight(); 



       xshift = calc_shift(0,centerX-1,centerX,k); 

       float newcenterX = width-centerX; 
       float xshift_2 = calc_shift(0,newcenterX-1,newcenterX,k); 

       yshift = calc_shift(0,centerY-1,centerY,k); 

       float newcenterY = height-centerY; 
       float yshift_2 = calc_shift(0,newcenterY-1,newcenterY,k); 

       xscale = (width-xshift-xshift_2)/width; 

       yscale = (height-yshift-yshift_2)/height; 


      int p = startJ*radius; 
      int origPixel = 0; 
      int color = 0; 
      int i; 

      for (int j = startJ; j < endJ; j++){ 

       for (i = 0; i < width; i++, p++){ 


      origPixel = input.getPixel(i,j); 

      float x = getRadialX((float)j,(float)i,centerX,centerY,k); 


      float y = getRadialY((float)j,(float)i,centerX,centerY,k); 

      sampleImage(input,x,y); 

      color = ((s[1]&0x0ff)<<16)|((s[2]&0x0ff)<<8)|(s[3]&0x0ff); 
      //Log.e(TAG, "radius = "+radius); 

      if(((i-centerX)*(i-centerX) + (j-centerY)*(j-centerY)) <= radius*(radius/4)){ 

           partialResult.addValue(p, color); 


      }else{ 


       partialResult.addValue(p, origPixel); 



      } 

       }//end of inner for 

     }//end of outer for 

      return partialResult; 
    }//end of call 


}// end of partialprocessing 

}//end of MultiProcesorFilter 

@And_Dev come promesso

Di seguito è la vista che ottiene gli utenti toccano co-ords e quindi chiama il filtro su un'area selezionata.l'area selezionata è il cavo, ad esempio il centro del cerchio più un raggio (un cerchio). il codice lo fa due volte come app per un'app di aumento del seno :) Commenta semplicemente il codice HorizontalSlider in quanto non ti serve.

import java.io.BufferedInputStream; 
import java.io.DataInputStream; 
import java.io.File; 
import java.io.FileInputStream; 
import java.io.InputStream; 

import android.content.Context; 
import android.graphics.Bitmap; 
import android.graphics.BitmapFactory; 
import android.graphics.Canvas; 
import android.graphics.Color; 
import android.graphics.Paint; 
import android.graphics.PorterDuff.Mode; 
import android.graphics.PorterDuffXfermode; 
import android.os.Environment; 
import android.util.AttributeSet; 
import android.util.Log; 
import android.view.MotionEvent; 
import android.view.View; 

import com.tecmark.HorizontalSlider.OnProgressChangeListener; 

public class TouchView extends View{ 


    private File tempFile; 
    private byte[] imageArray; 
    private Bitmap bgr; 

    private Bitmap crop; 
    private Bitmap crop2; 
    private Bitmap overLay; 
    private Bitmap overLay2; 


    private float centreX; 
    private float centreY; 
    private float centreA = 200; 
    private float centreB = 200; 
    private Boolean xyFound = false; 
    private int Progress = 1; 
    private static final String TAG = "*********TouchView"; 
    private Filters f = null; 
    private boolean bothCirclesInPlace = false; 
    private MultiProcessorFilter mpf; 
    private MultiProcessorFilter mpf2; 
    private MultiRuntimeProcessorFilter mrpf; 
    private MultiRuntimeProcessorFilter mrpf2; 





    public TouchView(Context context) { 
     super(context); 

    } 




    public TouchView(Context context, AttributeSet attr) { 
     super(context,attr); 
     Log.e(TAG, "++++++++++ inside touchview constructor"); 



     tempFile = new File(Environment.getExternalStorageDirectory(). 
       getAbsolutePath() + "/"+"image.jpg"); 

     imageArray = new byte[(int)tempFile.length()]; 


    try{ 

      InputStream is = new FileInputStream(tempFile); 
      BufferedInputStream bis = new BufferedInputStream(is); 
      DataInputStream dis = new DataInputStream(bis); 


      int i = 0; 

      while (dis.available() > 0) { 
      imageArray[i] = dis.readByte(); 
      i++; 
      } 

      dis.close(); 

     } catch (Exception e) { 

       e.printStackTrace(); 
      } 


     Bitmap bm = BitmapFactory.decodeByteArray(imageArray, 0, imageArray.length); 




     bgr = bm.copy(bm.getConfig(), true);; 

     overLay = null; 
     overLay2 = null; 



     bm.recycle(); 

    }// end of touchView constructor 




    public void findCirclePixels(){ 

     // f = new Filters(); 
     // mpf = new MultiProcessorFilter(); 
     // mpf2 = new MultiProcessorFilter(); 
     mrpf = new MultiRuntimeProcessorFilter(); 
     mrpf2 = new MultiRuntimeProcessorFilter(); 

     crop = Bitmap.createBitmap(bgr,Math.max((int)centreX-75,0),Math.max((int)centreY-75,0),150,150); 
     crop2 = Bitmap.createBitmap(bgr,Math.max((int)centreA-75,0),Math.max((int)centreB-75,0),150,150); 

       new Thread(new Runnable() { 
       public void run() { 
        float prog = (float)Progress/150001; 

       // final Bitmap bgr3 = f.barrel(crop,prog); 
       // final Bitmap bgr4 = f.barrel(crop2,prog); 

       // final Bitmap bgr3 = mpf.barrel(crop,prog); 
       // final Bitmap bgr4 = mpf2.barrel(crop2,prog); 

        final Bitmap bgr3 = mrpf.barrel(crop,prog); 
        final Bitmap bgr4 = mrpf2.barrel(crop2,prog); 

        TouchView.this.post(new Runnable() { 
        public void run() { 


         TouchView.this.overLay = bgr3; 
         TouchView.this.overLay2 = bgr4; 

         TouchView.this.invalidate(); 

        } 
        }); 
       } 
       }).start(); 


     }// end of changePixel() 






    @Override 
    public boolean onTouchEvent(MotionEvent ev) { 

     switch (ev.getAction()) { 

      case MotionEvent.ACTION_DOWN: { 

       if(xyFound == false){ 
       centreX = (int) ev.getX(); 
       centreY = (int) ev.getY(); 
       xyFound = true; 
       }else{ 
       centreA = (int) ev.getX(); 
       centreB = (int) ev.getY(); 
       bothCirclesInPlace = true; 
       } 


       break; 
      } 

      /* case MotionEvent.ACTION_MOVE: { 

       if(xyFound == false){ 
        centreX = (int) ev.getX(); 
        centreY = (int) ev.getY(); 
        xyFound = true; 
       }else{ 
        centreA = (int) ev.getX(); 
        centreB = (int) ev.getY(); 
        bothCirclesInPlace = true; 
        } 

        findCirclePixels(); 
       // TouchView.this.invalidate(); 
        break; 

      }*/   

      case MotionEvent.ACTION_UP: 

       break; 

     } 
     return true; 
    }//end of onTouchEvent 





    public void initSlider(final HorizontalSlider slider) 
    { 

     slider.setOnProgressChangeListener(changeListener); 


    } 



    private OnProgressChangeListener changeListener = new OnProgressChangeListener() { 


     @Override 
     public void onProgressChanged(View v, int progress) { 



       setProgress(progress); 



     } 
    }; 




    @Override 
    public void onDraw(Canvas canvas){ 
     super.onDraw(canvas); 

     Log.e(TAG, "******about to draw bgr "); 
     canvas.drawBitmap(bgr, 0, 0, null); 

     if(bothCirclesInPlace == true){ 

       if(overLay != null){ 
        Log.e(TAG, "******about to draw overlay1 "); 
     canvas.drawBitmap(overLay, centreX-75, centreY-75, null); 
       } 
      if(overLay2 != null){ 
       Log.e(TAG, "******about to draw overlay2 "); 
     canvas.drawBitmap(overLay2, centreA-75, centreB-75, null); 
      } 

     } 

    }//end of onDraw 




    protected void setProgress(int progress2) { 
     Log.e(TAG, "***********in SETPROGRESS"); 
     this.Progress = progress2; 



     findCirclePixels(); 


    } 




} 

.

L'attività di chiamata.

import android.app.Activity; 
import android.os.AsyncTask; 
import android.os.Bundle; 
import android.util.Log; 
import android.view.View; 
import android.view.Window; 
import android.view.WindowManager; 
import android.view.View.OnClickListener; 
import android.widget.Button; 

public class Jjilapp extends Activity { 




    private static final String TAG = "*********jjil"; 


    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 

     requestWindowFeature(Window.FEATURE_NO_TITLE); 
     getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, 
       WindowManager.LayoutParams.FLAG_FULLSCREEN); 

     setContentView(R.layout.touchview); 
     final TouchView touchView = (TouchView)findViewById(R.id.touchview); 
     final HorizontalSlider slider = (HorizontalSlider)findViewById(R.id.slider); 

     touchView.initSlider(slider); 




    }//end of oncreate 




} 

Se avete bisogno di aiuto, basta chiedere. spero che questo aiuti

+0

Ho provato il tuo codice in Android ma la sfera è ancora nera. Ho anche provato questo su OpenCV e funziona bene, ma ho bisogno di questa funzionalità in app Android. Potresti per favore guidarmi su questo. Grazie –

+0

@Challenger quale versione di Android stai eseguendo? – turtleboy

+0

Ho eseguito il debug e trovato il problema che il valore alfa del pixel non è impostato nella regione della sfera per cui diventa nero. l'impostazione dell'alfa del pixel risolve il problema. Grazie per il tuo tempo –

1

Ho eseguito il debug dei file java e funziona correttamente sui miei telefoni (superiore a 4.0). Consiste di 3 file java e 1 file xml. Devi inserire il file checkerboardback.jpg sotto la directory drawaable. Come qualcuno ha detto, mancava il valore alfa e gli ho dato "0x0ff". Inoltre, il limite superiore di alcuni Looping era errato.

// 1. MultiRuntimeProcessorFilter.java

public class MultiRuntimeProcessorFilter { 



private static final String TAG = "mrpf"; 
private int x = 0; 
private Bitmap input = null; 
private int radius; 
private int mHeight; 


public void createBitmapSections(int nOp, int[] sections){ 

    int processors = nOp; 
    int jMax = input.getHeight(); 
    int aSectionSize = (int) Math.ceil(jMax/processors); 
    Log.e("yoSIZECHK", "++++++++++ sections size = "+aSectionSize); 

    int k = 0; 
    for(int h=0; h<processors+1; h++){ 

      sections[h] = k; 
      k+= aSectionSize; 
      if(h==processors){ 
       sections[h] = mHeight;//Last must cover ceiling 
      } 
     Log.v("yoSEC","sections = "+h+" "+sections[h]); 

    } 
}// end of createBitmapSections() 


//@SuppressWarnings("unchecked") 
public Bitmap barrel (Bitmap input, float k, int r){ 
     this.radius = r; 
     this.input = input; 
     int []mArray = new int[input.getWidth()*input.getHeight()]; 

     mHeight = input.getHeight(); 
     Log.e(TAG, "bitmap height x width = "+mHeight+" "+input.getWidth()); 
    //Log.v("yoRESULT", "height width = "+ input.getWidth()+" "+input.getHeight()); 




     int nrOfProcessors = Runtime.getRuntime().availableProcessors(); 
     Log.e(TAG, "no of processors = "+nrOfProcessors); 


     int[] sections = new int[nrOfProcessors+1]; 


     createBitmapSections(nrOfProcessors,sections); 
     ExecutorService threadPool = Executors.newFixedThreadPool(nrOfProcessors); 

     for(int g=0; g<sections.length;g++){ 
      Log.e(TAG, "++++++++++ sections= "+sections[g]); 
     } 

    // ExecutorService threadPool = Executors.newFixedThreadPool(nrOfProcessors); 

     Object[] task = new Object[nrOfProcessors]; 

     for(int z = 0; z < nrOfProcessors; z++){ 
     task[z] = (FutureTask<PartialResult>) threadPool.submit(new PartialProcessing(sections[z], sections[z+1] - 1, input, k, z)); 
     Log.e(TAG, "++++++++++ task"+z+"= "+task[z].toString()); 
     } 

    PartialResult[] results = new PartialResult[nrOfProcessors]; 

    try{ 
      for(int t = 0; t < nrOfProcessors; t++){ 

       results[t] = ((FutureTask<PartialResult>) task[t]).get(); 

       results[t].fill(mArray); 
      } 

     }catch(Exception e){ 
      e.printStackTrace(); 
     } 

Log.v("yoRESULT", "height width = "+ input.getHeight()+" "+input.getWidth()); 
     Bitmap dst2 = Bitmap.createBitmap(mArray,input.getWidth(),input.getHeight(),input.getConfig()); 

    return dst2; 


    }//end of barrel() 




public class PartialResult { 
     int startP; 
     int endP; 
     int[] storedValues; 

     public PartialResult(int startp, int endp, Bitmap input){ 

      this.startP = startp; 
      this.endP = endp; 
      this.storedValues = new int[input.getWidth()*input.getHeight()]; 


     } 

     public void addValue(int p, int result) { 
      storedValues[p] = result; 

     } 

     public void fill(int[] mArray) { 

      Log.v("yo09", startP + " " + endP + " " + input.getWidth()); 
      //yoko for (int p = startP; p < endP; p++){ 
     for (int p = startP; p < endP+1; p++){ 
       //for(int b=0;b<radius;b++,x++) 
       for(int b=0;b<input.getWidth();b++,x++) { 
        mArray[x] = storedValues[x]; 
        if (b == 0) Log.v("yoyoyo", p+" + " + storedValues[x]); 
       } 
      } 
      Log.e("yoFill", " ++++++++++ radius x = "+radius+" "+x); 
    } 

     }//end of partialResult 




public class PartialProcessing implements Callable<PartialResult> { 
    int startJ; 
    int endJ; 
    int mID; 


    private int[] scalar; 
    private float xscale; 
    private float yscale; 
    private float xshift; 
    private float yshift; 
    private float thresh = 1; 
    private int [] s1; 
    private int [] s2; 
    private int [] s3; 
    private int [] s4; 
    private int [] s; 
    private Bitmap input; 
    private float k; 



    public PartialProcessing(int startj, int endj, Bitmap input, float k, int mID) { 

     this.startJ = startj; 
     this.endJ = endj; 
     this.input = input; 
     this.k = k; 
     this.mID = mID; 

     s = new int[4]; 
     scalar = new int[4]; 
     s1 = new int[4]; 
     s2 = new int[4]; 
     s3 = new int[4]; 
     s4 = new int[4]; 

    } 

    int [] getARGB(Bitmap buf,int x, int y){ 

     int rgb = buf.getPixel(y, x); // Returns by default ARGB. 
     // int [] scalar = new int[4]; 
     // scalar[0] = (rgb >>> 24) & 0xFF; 
     scalar[1] = (rgb >>> 16) & 0xFF; 
     scalar[2] = (rgb >>> 8) & 0xFF; 
     scalar[3] = (rgb >>> 0) & 0xFF; 
     return scalar; 

    } 



    float getRadialX(float x,float y,float cx,float cy,float k){ 

     x = (x*xscale+xshift); 
     y = (y*yscale+yshift); 
     float res = x+((x-cx)*k*((x-cx)*(x-cx)+(y-cy)*(y-cy))); 
     return res; 
     } 

     float getRadialY(float x,float y,float cx,float cy,float k){ 

     x = (x*xscale+xshift); 
     y = (y*yscale+yshift); 
     float res = y+((y-cy)*k*((x-cx)*(x-cx)+(y-cy)*(y-cy))); 
     return res; 
     } 



     float calc_shift(float x1,float x2,float cx,float k){ 

     float x3 = (float)(x1+(x2-x1)*0.5); 
     float res1 = x1+((x1-cx)*k*((x1-cx)*(x1-cx))); 
     float res3 = x3+((x3-cx)*k*((x3-cx)*(x3-cx))); 

     if(res1>-thresh && res1 < thresh) 
      return x1; 
     if(res3<0){ 
      return calc_shift(x3,x2,cx,k); 
     } 
     else{ 
      return calc_shift(x1,x3,cx,k); 
     } 
     } 


     //void sampleImage(Bitmap mArray, float idx0, float idx1) 
    int [] sampleImage(Bitmap mArray2, float idx0, float idx1) 
     { 

     // s = new int [4]; 
     if(idx0<0 || idx1<0 || idx0>(mArray2.getHeight()-1) || idx1>(mArray2.getWidth()-1)){ 
      s[0]=0; 
      s[1]=0; 
      s[2]=0; 
      s[3]=0; 
      return s;// yoko 
     } 

     float idx0_fl=(float) Math.floor(idx0); 
     float idx0_cl=(float) Math.ceil(idx0); 
     float idx1_fl=(float) Math.floor(idx1); 
     float idx1_cl=(float) Math.ceil(idx1); 



    s1 = getARGB(mArray2,(int)idx0_fl,(int)idx1_fl); 
    s2 = getARGB(mArray2,(int)idx0_fl,(int)idx1_cl); 
    s3 = getARGB(mArray2,(int)idx0_cl,(int)idx1_cl); 
    s4 = getARGB(mArray2,(int)idx0_cl,(int)idx1_fl); 

     float x = idx0 - idx0_fl; 
     float y = idx1 - idx1_fl; 

     // s[0]= (int) (s1[0]*(1-x)*(1-y) + s2[0]*(1-x)*y + s3[0]*x*y + s4[0]*x*(1-y)); 
     s[1]= (int) (s1[1]*(1-x)*(1-y) + s2[1]*(1-x)*y + s3[1]*x*y + s4[1]*x*(1-y)); 
     s[2]= (int) (s1[2]*(1-x)*(1-y) + s2[2]*(1-x)*y + s3[2]*x*y + s4[2]*x*(1-y)); 
     s[3]= (int) (s1[3]*(1-x)*(1-y) + s2[3]*(1-x)*y + s3[3]*x*y + s4[3]*x*(1-y)); 

      return s; 

     } 



    @Override 
    public PartialResult call() { 

     PartialResult partialResult = new PartialResult(startJ, endJ,input); 

     float centerX=input.getWidth()/2; //center of distortion 
     float centerY=input.getHeight()/2; 



     int width = input.getWidth(); //image bounds 
     int height = input.getHeight(); 



      xshift = calc_shift(0,centerX-1,centerX,k); 

      float newcenterX = width-centerX; 
      float xshift_2 = calc_shift(0,newcenterX-1,newcenterX,k); 

      yshift = calc_shift(0,centerY-1,centerY,k); 

      float newcenterY = height-centerY; 
      float yshift_2 = calc_shift(0,newcenterY-1,newcenterY,k); 

      xscale = (width-xshift-xshift_2)/width; 

      yscale = (height-yshift-yshift_2)/height; 


     // yoko int p = startJ*radius; 
     int p = startJ*width;//yoko 
     int origPixel = 0; 
     int color = 0; 
     int i; 

    Log.v("yokoIJ","PartialResult startJ endJ "+startJ+" "+endJ); 
     //yoko for (int j = startJ; j < endJ; j++){ 
     for (int j = startJ; j < endJ+1; j++){ 
      for (i = 0; i < width; i++, p++){ 
    s = new int [4];//yoko added 

    origPixel = input.getPixel(i,j); 

    float x = getRadialX((float)j,(float)i,centerX,centerY,k); 
    float y = getRadialY((float)j,(float)i,centerX,centerY,k); 
    //sampleImage(input,x,y); //yoko 
    s= sampleImage(input,x,y); 

    color = (0xff<<24)|((s[1]&0x0ff)<<16)|((s[2]&0x0ff)<<8)|(s[3]&0x0ff); 
    //Log.e(TAG, "radius = "+radius); 

    //Not understand why it is not radius but radius/2 
     //yoko if(((i-centerX)*(i-centerX) + (j-centerY)*(j-centerY)) <= radius*(radius/4)){ 
    if(((i-centerX)*(i-centerX) + (j-centerY)*(j-centerY)) <= radius*radius){ 
       //yo if(j%10 == 1 && i%10 == 1) 
        //yo Log.v("yoJI", mID+" "+j + " " + i); 
     partialResult.addValue(p, color); 
    }else{ 
     partialResult.addValue(p, origPixel); 
     } 

      }//end of inner for 

    }//end of outer for 

     return partialResult; 
}//end of call 
}// end of partialprocessing 
}//end of MultiProcesorFilter 

// 2. Filters.java:

class Filters{ 
float xscale; 
float yscale; 
float xshift; 
float yshift; 
int [] s; 
private static String TAG = "Filters"; 
public Filters(){ 
    Log.e(TAG, "***********inside constructor"); 
} 

public Bitmap barrel (Bitmap input, float k, boolean check, int Range){ 
    Log.e(TAG, "***********inside barrel method : hasAlpha = "); 
    float centerX=input.getWidth()/2; //center of distortion 
    float centerY=input.getHeight()/2; 

    int width = input.getWidth(); //image bounds 
    int height = input.getHeight(); 

//yoko  Log.v("yoQQ", width+" "+height+" "+centerX+" "+centerY); 
    if(check)return input; 

    Bitmap dst = Bitmap.createBitmap(width, height,input.getConfig()); //output pic 
    Log.e(TAG, "***********dst bitmap created "); 
     xshift = calc_shift(0,centerX-1,centerX,k); 
     float newcenterX = width-centerX; 

    float xshift_2 = calc_shift(0,newcenterX-1,newcenterX,k); 
     yshift = calc_shift(0,centerY-1,centerY,k); 
     float newcenterY = height-centerY; 
     float yshift_2 = calc_shift(0,newcenterY-1,newcenterY,k); 

     xscale = (width-xshift-xshift_2)/width; 
     yscale = (height-yshift-yshift_2)/height; 
     Log.e(TAG, "***********about to loop through bm"); 
    Log.v("yoQQ2", xscale + " " + yscale); 
    //if(check==1)return input;//yoko 
     /*for(int j=0;j<dst.getHeight();j++){ 
      for(int i=0;i<dst.getWidth();i++){ 
      float x = getRadialX((float)i,(float)j,centerX,centerY,k); 
      float y = getRadialY((float)i,(float)j,centerX,centerY,k); 
      sampleImage(input,x,y); 
      int color = ((s[1]&0x0ff)<<16)|((s[2]&0x0ff)<<8)|(s[3]&0x0ff); 
//   System.out.print(i+" "+j+" \\"); 

      dst.setPixel(i, j, color); 

      } 
     }*/ 

     int origPixel; // the pixel in orig image 
     int i=0,j=0; 
     for(j=0;j<dst.getHeight();j++){ 
      for(i=0;i<dst.getWidth();i++){ 
      s = new int [4];//yoko added 
      origPixel= input.getPixel(i,j); 
      float x = getRadialX((float)i,(float)j,centerX,centerY,k); 
      float y = getRadialY((float)i,(float)j,centerX,centerY,k); 
      //yoko sampleImage(input,x,y); 
      s = sampleImage(input,x,y); 
      //yoko int color = ((s[1]&0x0ff)<<16)|((s[2]&0x0ff)<<8)|(s[3]&0x0ff); 
      int color = (0xff<<24)|((s[1]&0xff)<<16)|((s[2]&0xff)<<8)|(s[3]&0xff); 
      //Log.v("yoQQ3", j + " " + i + " : "+dst.getHeight()+" "+dst.getWidth()); 


    // check whether a pixel is within the circle bounds of 150 

      if(Math.sqrt(Math.pow(i - centerX, 2) + (Math.pow(j - centerY, 2))) <= Range){ 
     dst.setPixel(i, j, color); 
       //if(j%10 == 1 && i%10 == 1) 
       // Log.v("yoJI", j + " " + i); 
      }else{ 
       dst.setPixel(i,j,origPixel); 
      } 
      } 
     } 
    Log.v("yoDONE", "======== Loop End ======== "+j+" "+i+" : " + dst.getHeight()+" "+dst.getWidth()); 
    return dst; 
}//barrel 

// void sampleImage(Bitmap arr, float idx0, float idx1) // yoko 
int[] sampleImage(Bitmap arr, float idx0, float idx1) 
{ 
    s = new int [4]; 
    if(idx0<0 || idx1<0 || idx0>(arr.getHeight()-1) || idx1>(arr.getWidth()-1)){ 
    s[0]=0; 
    s[1]=0; 
    s[2]=0; 
    s[3]=0; 
    return s; 
    } 

    float idx0_fl=(float) Math.floor(idx0); 
    float idx0_cl=(float) Math.ceil(idx0); 
    float idx1_fl=(float) Math.floor(idx1); 
    float idx1_cl=(float) Math.ceil(idx1); 

    int [] s1 = getARGB(arr,(int)idx0_fl,(int)idx1_fl); 
    int [] s2 = getARGB(arr,(int)idx0_fl,(int)idx1_cl); 
    int [] s3 = getARGB(arr,(int)idx0_cl,(int)idx1_cl); 
    int [] s4 = getARGB(arr,(int)idx0_cl,(int)idx1_fl); 

    float x = idx0 - idx0_fl; 
    float y = idx1 - idx1_fl; 

    s[0]= (int) (s1[0]*(1-x)*(1-y) + s2[0]*(1-x)*y + s3[0]*x*y + s4[0]*x*(1-y)); 
    s[1]= (int) (s1[1]*(1-x)*(1-y) + s2[1]*(1-x)*y + s3[1]*x*y + s4[1]*x*(1-y)); 
    s[2]= (int) (s1[2]*(1-x)*(1-y) + s2[2]*(1-x)*y + s3[2]*x*y + s4[2]*x*(1-y)); 
    s[3]= (int) (s1[3]*(1-x)*(1-y) + s2[3]*(1-x)*y + s3[3]*x*y + s4[3]*x*(1-y)); 
    return s;///yoko added to make return the result value 
}//sampleImage 

int [] getARGB(Bitmap buf,int x, int y){ 
    int rgb = buf.getPixel(y, x); // Returns by default ARGB. 
    int [] scalar = new int[4]; 
    scalar[0] = (rgb >>> 24) & 0xFF; 
    scalar[1] = (rgb >>> 16) & 0xFF; 
    scalar[2] = (rgb >>> 8) & 0xFF; 
    scalar[3] = (rgb >>> 0) & 0xFF; 
    return scalar; 
}//getARGB 

float getRadialX(float x,float y,float cx,float cy,float k){ 
    x = (x*xscale+xshift); 
    y = (y*yscale+yshift); 
    float res = x+((x-cx)*k*((x-cx)*(x-cx)+(y-cy)*(y-cy))); 
    return res; 
}//getRadial1X 

float getRadialY(float x,float y,float cx,float cy,float k){ 
    x = (x*xscale+xshift); 
    y = (y*yscale+yshift); 
    float res = y+((y-cy)*k*((x-cx)*(x-cx)+(y-cy)*(y-cy))); 
    return res; 
}//getRadialY 

float thresh = 1; 

float calc_shift(float x1,float x2,float cx,float k){ 
    float x3 = (float)(x1+(x2-x1)*0.5); 
    float res1 = x1+((x1-cx)*k*((x1-cx)*(x1-cx))); 
    float res3 = x3+((x3-cx)*k*((x3-cx)*(x3-cx))); 

    if(res1>-thresh && res1 < thresh) 
    return x1; 
    if(res3<0){ 
    return calc_shift(x3,x2,cx,k); 
    } 
    else{ 
    return calc_shift(x1,x3,cx,k); 
    } 
}//calc_shift 
} 

E // 3 MainActivity.java, classe di primo livello.

public class MainActivity extends Activity { 

ImageView iv1=null; 
ImageView iv2=null; 
Button bT, bB, b0; 
Bitmap bitmap1, bitmap2, bitmapSP; 
Boolean view1 = true; 
private static final String TAG = "*********jjil"; 
public static int mH,mW,RADIUS; 

@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 

    requestWindowFeature(Window.FEATURE_NO_TITLE); 
    getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, 
      WindowManager.LayoutParams.FLAG_FULLSCREEN); 

    setContentView(R.layout.activity_main); 

    Resources res = this.getResources(); 
    //bitmap1 = BitmapFactory.decodeResource(res, R.drawable.checkerboard); 
    bitmap1 = BitmapFactory.decodeResource(res, R.drawable.checkerboardback); 
    mH=bitmap1.getHeight(); 
    mW=bitmap1.getWidth(); 
    RADIUS = mH/3; 

    bT = (Button)findViewById(R.id.buttontoggle); 
    bT.setOnClickListener(onClickToggleView); 
    bB = (Button)findViewById(R.id.buttonbarrel); 
    bB.setOnClickListener(onClickToggleView); 
    b0 = (Button)findViewById(R.id.button0); 
    b0.setOnClickListener(onClickToggleView); 

    iv1=(ImageView)findViewById(R.id.touchview1); 
    iv1.setImageBitmap(bitmap1); 
    iv1.setVisibility(View.VISIBLE); 


}//end of oncreate 

public View.OnClickListener onClickToggleView = new View.OnClickListener() { 
    public void onClick(View v) { 
     if (v == bT) { 

    /// fromhere 
      new AsyncTask<Void, Void, String>() { 
       com.example.owner.opengl2.Filters mFilers = new com.example.owner.opengl2.Filters(); 
       TextView tx = (TextView)findViewById(R.id.mStatus); 
       Bitmap bitmapSP;long start,end; 

       protected void onPreExecute() { 
        start = System.nanoTime(); 
        iv1.setImageBitmap(bitmap1); 
        tx.setText("- Running -"); 
       } 

       protected String doInBackground(Void... params) { 
        bitmapSP = mFilers.barrel(bitmap1,(float)0.00005,false,RADIUS); 
        return "message"; 
       } 

       protected void onPostExecute(String msg) { 
        end = System.nanoTime(); 
        long elapsedTime = end - start; 
        long seconds = elapsedTime/1000000; 

        iv1.setImageBitmap(bitmapSP); 
        tx.setText("- READY : ElapsedTime(ms) = "+seconds); 
        // Post Code 
        // Use `msg` in code 
       } 
      }.execute(); 
    ///upto here 



     } else if (v == bB){ 

    /// fromhere 
      new AsyncTask<Void, Void, String>() { 
       com.example.owner.opengl2.MultiRuntimeProcessorFilter mFilers = new com.example.owner.opengl2.MultiRuntimeProcessorFilter(); 
       TextView tx = (TextView)findViewById(R.id.mStatus); 
       Bitmap bitmapSP;long start,end; 

       protected void onPreExecute() { 
        start = System.nanoTime(); 
        iv1.setImageBitmap(bitmap1); 
        tx.setText("- Running -"); 
       } 

       protected String doInBackground(Void... params) { 
        bitmapSP = mFilers.barrel(bitmap1,(float)0.00005,RADIUS); 
        return "message"; 
       } 

       protected void onPostExecute(String msg) { 
        end = System.nanoTime(); 
        long elapsedTime = end - start; 
        //double seconds = (double)elapsedTime/1000000000.0; 
        long seconds = elapsedTime/1000000; 
        iv1.setImageBitmap(bitmapSP); 
        tx.setText("- READY : ElapsedTime(ms) = "+seconds); 
        // Post Code 
        // Use `msg` in code 
       } 
      }.execute(); 


     } else if (v == b0){ 
      new AsyncTask<Void, Void, String>() { 
       protected String doInBackground(Void... Unused) { 
        return "OK"; 
       } 
       protected void onPostExecute(String message) { 
        Log.v("YO", "---------------------------------"); 
        Log.v("YO", "----------ORIGINAL SHAPE-------- "+message); 
        Log.v("YO", "---------------------------------"); 
        iv1.setImageBitmap(bitmap1); 

        TextView tx = (TextView)findViewById(R.id.mStatus); 
        tx.setText("- READY : w h RADIUS = "+mW+" "+mH+" "+RADIUS); 
       } 
      }.execute(); 

     } 
     ///upto here 

    } 
}; 

}

Ecco file XML // 4 activity_main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" 
android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin" 
android:paddingRight="@dimen/activity_horizontal_margin" 
android:paddingTop="@dimen/activity_vertical_margin" 
android:orientation="vertical" 
android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity"> 

<LinearLayout 
    android:id="@+id/buttons" 
    android:layout_centerHorizontal="true" 
    android:layout_alignParentTop="true" 
    android:orientation="horizontal" 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content"> 

    <Button 
     android:id="@+id/buttontoggle" 
     android:text="Barrel 1P" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" /> 

    <Button 
    android:id="@+id/buttonbarrel" 
    android:text="Barrele NP" 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" /> 

    <Button 
     android:id="@+id/button0" 
     android:text="ORIGINAL" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" /> 


</LinearLayout> 
<TextView 
    android:id="@+id/mStatus" 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" 
    android:text=" - Ready - " 
    android:textAppearance="?android:attr/textAppearanceSmall" 
    android:layout_below="@+id/buttons" 
    android:layout_centerHorizontal="true" 
    /> 

<ImageView 
    android:id="@+id/touchview1" 
    android:layout_below="@+id/mStatus" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:layout_centerHorizontal="true" 
    /> 

<!--ImageView 
    android:id="@+id/touchview2" 
    android:layout_below="@+id/touchview1" 
    android:layout_alignParentBottom="true" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:layout_centerHorizontal="true" /-->