如何通过openCV模拟鱼眼镜头效果?
Posted
技术标签:
【中文标题】如何通过openCV模拟鱼眼镜头效果?【英文标题】:How to simulate fisheye lens effect by openCV? 【发布时间】:2010-12-27 23:34:07 【问题描述】:我正在寻找创建鱼眼镜头效果的方法,查看了 openCV 的文档,看起来它包含用于鱼眼等径向失真的相机校准功能。是否可以通过openCV模拟鱼眼失真?
如果可以通过 openCV 来实现,与 openGL 相比,哪一个会产生更好的结果?谢谢。
【问题讨论】:
【参考方案1】:我使用 opencv 创建了this app。这就是你说的效果吗? 我基本上编写了***“失真(光学)”上显示的公式,如果需要,我可以显示代码
更新: 好的,下面是使用 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
【讨论】:
是的! Wiki 的“失真(光学)”页面上的桶形失真正是我正在寻找的!我想知道如何使用openCV在鱼眼镜头周围映射图像。你能在这里显示你的代码吗?或者给我一些提示?谢谢你。问候 我试图理解代码,但有点犹豫,有许多我不知道为什么会发生的操作。是否可以添加简短的简介或说明?【参考方案2】:感谢以上 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 承诺
下面是让用户触摸坐标然后在选定区域调用过滤器的视图。所选区域是绳索,例如圆心加上半径(圆)。该代码在隆胸应用程序中执行此操作的两倍:)只需注释掉 HorizontalSlider 代码,因为您不需要它。
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
如果您需要任何帮助,请询问。希望这会有所帮助
【讨论】:
我已经在 android 中尝试过您的代码,但球体仍然是黑色的。我也在 OpenCV 上试过这个,它工作正常,但我需要在 android 应用程序中使用这个功能。你能指导我吗?谢谢 @Challenger 你在哪个版本的 android 上运行它? 我已经调试过了,发现像素的alpha值没有在球体区域设置,为什么它会变黑。设置像素的 alpha 解决了这个问题。感谢您的宝贵时间 @challenge 嘿,很高兴你成功了!我实际上已经重新完成了这段代码,所以它使用并行化处理位图。它检查设备以查看有多少处理器可用,例如在我的 htc one X 上有 4 个内核。它将位图分成 4 个,为每个核心分配一个段,然后在完成后将它们全部缝合在一起。如果您愿意,您可以拥有代码,请告诉我。它适用于 android 2.1,但在 android 4.0 上不太好。如果你想玩它,看看你能不能让它继续下去,如果你愿意,我只是要求更新;) 谢谢,感谢您的帮助。我已经使用了上面的代码,它非常适合方形图像,但是当图像的宽度和高度之间的差异太大时,输出球体将从边界变为黑色,也不是从中心,我尝试调试但尚未成功,如果您知道如何解决此问题,请分享。如果您与我分享并行化代码,我会很高兴。【参考方案3】:感谢您提供该代码。它对我有很大帮助。我为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);
【讨论】:
嗨,这个java代码正是我需要的。我正在尝试在 Android 上创建相同的效果,但不能使用 bufferedimage,因为 android 不支持它。有没有办法让这段代码在android上运行?任何帮助将不胜感激,谢谢马特【参考方案4】:我调试了 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_
android:layout_ 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_
android:layout_>
<Button
android:id="@+id/buttontoggle"
android:text="Barrel 1P"
android:layout_
android:layout_ />
<Button
android:id="@+id/buttonbarrel"
android:text="Barrele NP"
android:layout_
android:layout_ />
<Button
android:id="@+id/button0"
android:text="ORIGINAL"
android:layout_
android:layout_ />
</LinearLayout>
<TextView
android:id="@+id/mStatus"
android:layout_
android:layout_
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_
android:layout_
android:layout_centerHorizontal="true"
/>
<!--ImageView
android:id="@+id/touchview2"
android:layout_below="@+id/touchview1"
android:layout_alignParentBottom="true"
android:layout_
android:layout_
android:layout_centerHorizontal="true" /-->
【讨论】:
【参考方案5】:你想在sintetic图像上使用这种失真,还是想应用到摄像机或其他东西上?
在 OpenCv 中,您应该能够进行相机校准(使用内置函数,张氏算法)..
在OpenGL 看到这个。
问候
【讨论】:
以上是关于如何通过openCV模拟鱼眼镜头效果?的主要内容,如果未能解决你的问题,请参考以下文章
OpenCV3.0.0dev中鱼眼摄像机模型的主要参考是什么?