我有大量用鱼眼镜头拍摄的照片。因为我想对照片进行一些图像处理(例如边缘检测),所以我想消除严重影响我的结果的桶形失真。
经过一些研究和大量阅读文章后,我发现了这个页面:他们描述了一种算法(和一些公式)来解决这个问题。
M = a *rcorr^3 + b * rcorr^2 + c * rcorr + d
rsrc = (a * rcorr^3 + b * rcorr^2 + c * rcorr + d) * rcorrrsrc = 像素到源图像中心的
距离 rcorr = 像素到校正后图像中心的距离
a,b,c = 图像失真 d = 图像线性缩放
我使用了这些公式并尝试在 Java 应用程序中实现它。不幸的是,它不起作用,我没能使它起作用。“更正”的图像看起来与原始照片完全不同,而是在中间显示了一些神秘的圆圈。看这里:
http://imageshack.us/f/844/barreldistortioncorrect.jpg/ (这曾经是一头白牛在蓝墙前的照片)
这是我的代码:
protected int[] correction(int[] pixels) {
    //
    int[] pixelsCopy = pixels.clone();
    // parameters for correction
    double paramA = 0.0; // affects only the outermost pixels of the image
    double paramB = -0.02; // 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 < dstView.getImgWidth(); x++) {
        for(int y = 0; y < dstView.getImgHeight(); y++) {
            int dstX = x;
            int dstY = y;
            // center of dst image
            double centerX = (dstView.getImgWidth() - 1) / 2.0;
            double centerY = (dstView.getImgHeight() - 1) / 2.0;
            // difference between center and point
            double diffX = centerX - dstX;
            double diffY = centerY - dstY;
            // distance or radius of dst image
            double dstR = Math.sqrt(diffX * diffX + diffY * diffY);
            // 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 + (diffX * factor);
            double srcYd = centerY + (diffX * factor);
            // no interpolation yet (just nearest point)
            int srcX = (int)srcXd;
            int srcY = (int)srcYd;
            if(srcX >= 0 && srcY >= 0 && srcX < dstView.getImgWidth() && srcY < dstView.getImgHeight()) {
                int dstPos = dstY * dstView.getImgWidth() + dstX;
                pixels[dstPos] = pixelsCopy[srcY * dstView.getImgWidth() + srcX];
            }
        }
    }
    return pixels;
}
我的问题是:
1)这个公式正确吗?
2)我把这个公式变成一个软件是不是犯了一个错误?
3)还有其他算法(例如如何通过openCV模拟鱼眼镜头效果?或wiki/Distortion_(光学)),它们更好吗?
谢谢你的帮助!