8

我正在寻找创建鱼眼镜头效果的方法,查看了 openCV 的文档,看起来它包含用于鱼眼等径向失真的相机校准功能。是否可以通过openCV模拟鱼眼失真?

如果可以通过openCV做到这一点,与openGL相比,哪一个会产生更好的结果?谢谢。

4

5 回答 5

15

我使用 opencv创建了这个应用程序。这就是你说的效果吗?我基本上编写了维基百科“失真(光学)”中显示的公式,如果需要,我可以显示代码

更新:好的,下面是使用 opencv 用 c++ 编写的实际代码(未记录,请随时寻求解释):程序接收以下参数作为输入:| 输入图像| | 输出图像| | 控制失真量的 K(通常尝试 0.001 左右的值) | | 变形中心的 x 坐标| | y 畸变中心坐标|

所以程序的关键是双for循环,它在结果图像上逐像素迭代,并使用径向失真公式在输入图像中查找匹配像素(这是图像扭曲通常完成的方式 - 也许直观地反通过从输出到输入的反投影)。有一些细节与输出图像的比例有关(在这个程序中,生成的图像与输入的大小相同),除非你想了解更多细节,否则我不会深入探讨。享受吧。

    #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  

}
于 2009-12-19T21:05:34.623 回答
4

感谢上面 2 的代码。我已经用 Java 修改了上面的转录代码以使用 Bitmaps 而不是 BufferedImage。这使代码能够在 Android(不支持 AWT)上运行。我还制作了效果只是操纵圆圈中的像素而不是整个位图,这会产生鱼眼“镜头”效果。希望这可以帮助任何 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 正如承诺的那样

下面是让用户触摸坐标然后在选定区域调用过滤器的视图。所选区域是绳索,例如圆心加上半径(圆)。该代码对隆胸应用程序执行此操作的两倍:)只需注释掉 Horizo​​ntalSlider 代码,因为您不需要它。

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();


    }




}

.

调用活动。

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




}

如果您需要任何帮助,请询问。希望这可以帮助

于 2011-06-08T15:05:57.620 回答
2

感谢您提供的代码。它对我有很大帮助。我为Java对其进行了转码。也许有人有类似的功能来模拟切向失真?

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);
      }
    }
}
于 2011-04-26T13:48:20.217 回答
1

我调试了 java 文件,它在我的手机上运行良好(高于 4.0)。它由3个java文件和1个xml文件组成。您必须将 checkerboardback.jpg 文件放在 drawaable 目录下。正如有人所说,缺少 alpha 值,我给它“0x0ff”。另外,有些Looping的upperbound是错误的。

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

和 //3 MainActivity.java,顶级类。

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

    }
};

}

这是 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" /-->

于 2015-08-21T06:01:34.163 回答
0

你想在sintetic图像上使用这种失真,还是想应用于摄像机或其他东西?

在 OpenCv 中,您应该能够进行相机校准(使用内置函数,张氏算法)..

OpenGL中看到这个。

问候

于 2009-12-18T10:04:16.917 回答