¿Cómo simular el efecto de lente ojo de pez por openCV?

Estoy buscando maneras de crear efecto de lente ojo de pez, miré documentaciones para openCV, parece que contiene funciones de calibración de cámara para distorsiones radiales como ojo de pez. ¿Es posible simular la distorsión de ojo de pez por openCV?

Si es posible hacerlo mediante openCV, comparando con OpenGL, ¿cuál generará mejores resultados? Gracias.

Creé esta aplicación usando opencv. ¿Es este el efecto al que te refieres? Básicamente codifiqué la fórmula que se muestra en la wikipedia “Distorsión (óptica)”. Puedo mostrar el código si es necesario.

Actualización : OK, a continuación se muestra el código escrito en c ++ usando opencv (no documentado, así que no dude en pedir explicaciones): El progtwig recibe como entrada el siguiente parámetro: | imagen de entrada | | imagen de salida | | K, que controla la cantidad de distorsión (por lo general, prueba con valores de alrededor de 0.001) | | x coordenada del centro de distorsión | | y coordenada del centro de distorsión |

Entonces, el quid del progtwig es el bucle doble que itera píxel por píxel en la imagen resultante y busca el píxel coincidente en la imagen de entrada usando la fórmula de distorsión radial (esta es la forma en que generalmente se hace la deformación de la imagen, tal vez contra intuitivamente por retroproyección de salida a entrada). Hay algunas sutilezas que tienen que ver con la escala de la imagen de salida (en este progtwig, la imagen resultante es del mismo tamaño que la entrada), y no entraré en ella a menos que desee entrar en más detalles. Disfrute.

#include  #include  #include  #include  #include  #include  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: "<-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< 

Gracias a los 2 anteriores para este código. Modifiqué el código transcrito anterior en Java para usar mapas de bits en lugar de BufferedImage. Esto permite que el código se ejecute en Android (que no admite AWT). También hice que el efecto solo manipulara los píxeles en un círculo en lugar de todo el bitmap, esto le da un efecto ojo de pez. Espera que esto ayude a cualquier desarrollador de 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(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 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(); } } 

.

La actividad de llamada.

 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 } 

Si necesitas ayuda, solo pregunta. espero que esto ayude

Gracias a ti por ese código. Me ayuda mucho. Lo transcribí para Java. ¿Tal vez alguien tiene una función similar para simular la distorsión tangencial?

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

Depuré los archivos java y funciona bien en mis teléfonos (superior a 4.0). Consiste en 3 archivos java y 1 archivo xml. Tienes que colocar el archivo checkerboardback.jpg en el directorio draailable. Como alguien dijo, faltaba el valor alfa y le di “0x0ff”. Además, el límite superior de algunos Looping estaba mal.

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

And //3 MainActivity.java, toplevel class.

 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() { 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() { 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() { 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 : wh RADIUS = "+mW+" "+mH+" "+RADIUS); } }.execute(); } ///upto here } }; 

}

Here is XML file //4 activity_main.xml

          

Do you want to use this distortion on sintetic images, or do you want to apply to a video camera or something ?

In OpenCv you should be able to do camera calibration (using the built-in functions, Zhang’s algorithm) ..

In OpenGL see this.

Saludos

Intereting Posts