Barrel distortion correction algorithm to correct FishEye lens - failing to implement with Java

前端 未结 4 1418
无人及你
无人及你 2021-01-12 17:32

I have a large bulk of photographs taken with a fisheye lens. As I want to do some image-processing (e.g. edge detection) on the photos I want to remove the barrel distortio

相关标签:
4条回答
  • 2021-01-12 18:07

    Probably your radial distortion parameters are too large, and the image became packed on a sphere. Try to put smaller values in a,b,c and d.

    0 讨论(0)
  • 2021-01-12 18:12

    Your values are very extreme, so you see extreme results.

    Try a=0, b=0, c=1. That describes no correction at all, if your program is correct you should see the original image. Then gradually change c and b. Changing in increments of 0.1 is a good start.

    0 讨论(0)
  • 2021-01-12 18:17

    I think your circles are caused by this line:

    double srcYd = centerY + (diffX * factor);
    

    which I'm guessing should be:

    double srcYd = centerY + (diffY * factor);
    
    0 讨论(0)
  • 2021-01-12 18:21

    The main bug you have is that the algorithm specifies that r_corr and r_src are in units of min((xDim-1)/2, (yDim-1)/2). That needs to be done to normalise the calculation so that the parameter values are not dependent on the size of the source image. With the code as it is you'll need to use much smaller values for paramB, e.g. it worked ok for me with paramB = 0.00000002 (for an image with dimensions 2272 x 1704).

    You also have a bug in calculating the difference from the center that causes the resulting image to be rotated 180 degree compared to the source image.

    Fixing both these bugs should give you something like this:

    protected static int[] correction2(int[] pixels, int width, int height) {
        int[] pixelsCopy = pixels.clone();
    
        // parameters for correction
        double paramA = -0.007715; // affects only the outermost pixels of the image
        double paramB = 0.026731; // most cases only require b optimization
        double paramC = 0.0; // most uniform correction
        double paramD = 1.0 - paramA - paramB - paramC; // describes the linear scaling of the image
    
        for (int x = 0; x < width; x++) {
            for (int y = 0; y < height; y++) {
                int d = Math.min(width, height) / 2;    // radius of the circle
    
                // center of dst image
                double centerX = (width - 1) / 2.0;
                double centerY = (height - 1) / 2.0;
    
                // cartesian coordinates of the destination point (relative to the centre of the image)
                double deltaX = (x - centerX) / d;
                double deltaY = (y - centerY) / d;
    
                // distance or radius of dst image
                double dstR = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
    
                // distance or radius of src image (with formula)
                double srcR = (paramA * dstR * dstR * dstR + paramB * dstR * dstR + paramC * dstR + paramD) * dstR;
    
                // comparing old and new distance to get factor
                double factor = Math.abs(dstR / srcR);
    
                // coordinates in source image
                double srcXd = centerX + (deltaX * factor * d);
                double srcYd = centerY + (deltaY * factor * d);
    
                // no interpolation yet (just nearest point)
                int srcX = (int) srcXd;
                int srcY = (int) srcYd;
    
                if (srcX >= 0 && srcY >= 0 && srcX < width && srcY < height) {
                    int dstPos = y * width + x;
                    pixels[dstPos] = pixelsCopy[srcY * width + srcX];
                }
            }
        }
    
        return pixels;
    }
    

    With this version you can use parameter values from existing lens databases like LensFun (though you'll need to flip the sign of each parameter). The page describing the algorithm can now be found at http://mipav.cit.nih.gov/pubwiki/index.php/Barrel_Distortion_Correction

    0 讨论(0)
提交回复
热议问题