Harium / keel

An Image Processing Library made in pure java from scratch
GNU Lesser General Public License v3.0
5 stars 1 forks source link

Add lens correction #37

Open yuripourre opened 6 years ago

yuripourre commented 6 years ago

Add lens to ImageSource.

ImageSource should be initialized with perfect lens when getRGB(x,y,source) is called, the lens returns the real(distorted) position based on lens params.

To distort camera images, usually only k1, k2, p1 and p2 are necessary.

Radial and Tangential coefficients.

yuripourre commented 5 years ago
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;
}

https://stackoverflow.com/a/16371584

Other Reference

https://www.mathworks.com/help/symbolic/examples/developing-an-algorithm-for-undistorting-an-image.html

yuripourre commented 4 years ago

A simple approach to handle radial distortion would be:

The correction is performed on normalized image coordinates 𝑥, 𝑦.

• Let 𝑥', 𝑦' denote the corrected normalized image coordinates, then a simple radial distortion model can look like this: 𝑥' = 𝑥(1 + 𝜅1(𝑥^2 + 𝑦^2) + 𝜅2(𝑥^2 + 𝑦^2)^2) 𝑦' = 𝑦(1 + 𝜅1(𝑥^2 + 𝑦^2) + 𝜅2(𝑥^2 + 𝑦^2)^2)

Radial distortion is K1 and K2