在Java中不能使用鱼眼镜头效果对我的图像

时间:2013-12-24 21:35:08

标签: java distortion fisheye lens

我想在Java中使用fisheye lens algorithm,但我无法实现主方法。

this site的底部,我找到了实现鱼眼算法的java代码,但是没有任何main()方法。我试图用自己的方法实现一个main()方法,但到目前为止我只能显示图像,但我不能在该图像上使用barrel()方法,这会对我的图像产生鱼眼效果。

你能否修正我的主要方法,或者实现一个新方法,加载一些图像(bufferedImage)然后在该图像上使用barrel()方法?

到目前为止我的代码是:

import java.awt.FlowLayout;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;

public class DisplayImage {
float xscale;
float yscale;
float xshift;
float yshift;
int [] s;                             


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_ARGB); //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);
  }
}



public static void main(String avg[]) throws IOException
{
    BufferedImage img=ImageIO.read(new File("image.jpg"));       
    ImageIcon icon=new ImageIcon(img);   
    JFrame frame=new JFrame();
    frame.setLayout(new FlowLayout());
    frame.setSize(625,648);
    JLabel lbl=new JLabel();
    lbl.setIcon(icon);
    frame.add(lbl);
    frame.setVisible(true);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);


}

}

代码正在运行,但它只显示图像。我想在我的图像上使用barrel()方法,这将产生鱼眼效果。因为我是java的新手,我不能这样做,请帮忙。

3 个答案:

答案 0 :(得分:1)

请参阅此网站:

http://popscan.blogspot.in/2012/04/fisheye-lens-equation-simple-fisheye.html

它包含了本文末尾的概念和工作源。

答案 1 :(得分:1)

让你的功能静止

public static BufferedImage barrel (BufferedImage input, float k)

并更改

public static void main(String avg[]) throws IOException
{ 
    BufferedImage img=ImageIO.read(new File("image.jpg"));

    //now pass this image to your barrel method and return in new image
    //note that, method can be called now without instatntiating any object, as it is static now
    BufferImage barrelImage = barrel(img,2.0);       
    ImageIcon icon=new ImageIcon(barrelImage);   
    ...
    ...
}

答案 2 :(得分:0)

所以我终于实现了所需的鱼眼!仅仅因为thisthis网站。对于有类似问题的人,我在这里给的是非常混乱但工作的代码:

package fisheye;

import java.awt.image.BufferedImage;
import java.awt.image.WritableRaster;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;

public class DitherMain {

   static String imageString = "image.bmp";

   BufferedImage startImage, endImage;
   int[] startPixels, endPixels, imR, imG, imB;
   int width, height;

   public static void main(String[] args){
      new DitherMain(loadImage(imageString));
   }

   //this object transforms the old image and writes the new image
   DitherMain(BufferedImage img){
      //filing the image into startpixels
      startImage = img;
      width = img.getWidth();
      height = img.getHeight();
      startPixels = new int[width*height];
      img.getRGB(0, 0, width, height, startPixels, 0, width);

      endPixels = fisheye(startPixels, width, height);

      transformPixels();

      WritableRaster wRaster = endImage.getData().createCompatibleWritableRaster();

      wRaster.setSamples(0, 0, width, height, 0, imR);
      wRaster.setSamples(0, 0, width, height, 1, imG);
      wRaster.setSamples(0, 0, width, height, 2, imB);

      endImage.setData(wRaster);
      System.out.println(endImage);

      //writing the file for endImage into the harddrive
      writeFile();
   }

   void transformPixels(){
      //endPixels = startPixels;
      endImage = startImage;

      imR = new int[endPixels.length];
      imG = new int[endPixels.length];
      imB = new int[endPixels.length];

      for(int i = 0; i < endPixels.length; i++){
         imR[i] = (endPixels[i] >> 16) & 0x000000FF;
         imG[i] = (endPixels[i] >> 8) & 0x000000FF;
         imB[i] = endPixels[i] & 0x000000FF;
      }
   }

   void writeFile(){
      try {
         ImageIO.write(endImage,"BMP",new File("RESULT.bmp"));
      } catch (IOException e) {
         e.printStackTrace();
      }
   }

   //this method just loads a specific buffered image
   public static BufferedImage loadImage(String fileName){   
      BufferedImage img;

      try{
         img=ImageIO.read(new File("image.bmp"));
         //img = ImageIO.read(DitherMain.class.getResource(fileName));
      } catch (Exception e) {
         e.printStackTrace();
         throw new RuntimeException(e);
      }
      return img;
   }

public static int[] fisheye(int[] srcpixels, double w, double h) {

    /*
     *    Fish eye effect
     *    tejopa, 2012-04-29
     *    http://popscan.blogspot.com
     *    http://www.eemeli.de
     */

    // create the result data
    int[] dstpixels = new int[(int)(w*h)];            
    // for each row
    for (int y=0;y<h;y++) {                                
        // normalize y coordinate to -1 ... 1
        double ny = ((2*y)/h)-1;                        
        // pre calculate ny*ny
        double ny2 = ny*ny;                                
        // for each column
        for (int x=0;x<w;x++) {                            
            // normalize x coordinate to -1 ... 1
            double nx = ((2*x)/w)-1;                    
            // pre calculate nx*nx
            double nx2 = nx*nx;
            // calculate distance from center (0,0)
            // this will include circle or ellipse shape portion
            // of the image, depending on image dimensions
            // you can experiment with images with different dimensions
            double r = Math.sqrt(nx2+ny2);                
            // discard pixels outside from circle!
            if (0.0<=r&&r<=1.0) {                            
                double nr = Math.sqrt(1.0-r*r);            
                // new distance is between 0 ... 1
                nr = (r + (1.0-nr)) / 2.0;
                // discard radius greater than 1.0
                if (nr<=1.0) {
                    // calculate the angle for polar coordinates
                    double theta = Math.atan2(ny,nx);         
                    // calculate new x position with new distance in same angle
                    double nxn = nr*Math.cos(theta);        
                    // calculate new y position with new distance in same angle
                    double nyn = nr*Math.sin(theta);        
                    // map from -1 ... 1 to image coordinates
                    int x2 = (int)(((nxn+1)*w)/2.0);        
                    // map from -1 ... 1 to image coordinates
                    int y2 = (int)(((nyn+1)*h)/2.0);        
                    // find (x2,y2) position from source pixels
                    int srcpos = (int)(y2*w+x2);            
                    // make sure that position stays within arrays
                    if (srcpos>=0 & srcpos < w*h) {
                        // get new pixel (x2,y2) and put it to target array at (x,y)
                        dstpixels[(int)(y*w+x)] = srcpixels[srcpos];    
                    }
                }
            }
        }
    }
    //return result pixels
    return dstpixels;
}    

}