校正鱼眼镜头的桶形畸变校正算法-未能用Java实现
我有大量的照片是用鱼眼镜头拍摄的。因为我想对照片进行一些图像处理(如边缘检测),所以我想消除严重影响结果的桶形失真 经过一些研究和阅读大量文章后,我发现:他们描述了解决这个问题的算法(和一些公式) M=a*rcorr^3+b*rcorr^2+c*rcorr+d校正鱼眼镜头的桶形畸变校正算法-未能用Java实现,java,algorithm,image-processing,distortion,fisheye,Java,Algorithm,Image Processing,Distortion,Fisheye,我有大量的照片是用鱼眼镜头拍摄的。因为我想对照片进行一些图像处理(如边缘检测),所以我想消除严重影响结果的桶形失真 经过一些研究和阅读大量文章后,我发现:他们描述了解决这个问题的算法(和一些公式) M=a*rcorr^3+b*rcorr^2+c*rcorr+d rsrc=(a*rcorr^3+b*rcorr^2+c*rcorr+d)*rcorr rsrc=像素到源图像中心的距离 rcorr=校正图像中像素与中心的距离 a、 b,c=图像失真 d=图像的线性缩放 我使用了这些公式,并试图在Java
rsrc=(a*rcorr^3+b*rcorr^2+c*rcorr+d)*rcorr rsrc=像素到源图像中心的距离
rcorr=校正图像中像素与中心的距离
a、 b,c=图像失真 d=图像的线性缩放 我使用了这些公式,并试图在Java应用程序中实现这一点。不幸的是,它不起作用,我没能让它起作用。“修正”的图像看起来不像原来的照片,而在中间显示一些神秘的圆圈。看这里: (这张照片曾经是一头白母牛在一堵蓝色的墙前的照片) 这是我的密码:
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;
}
受保护的int[]校正(int[]像素){
//
int[]像素透视=像素。克隆();
//校正参数
double paramA=0.0;//仅影响图像的最外层像素
double paramB=-0.02;//大多数情况下只需要b优化
双参数C=0.0;//最均匀校正
double paramD=1.0-paramA-paramB-paramC;//描述图像的线性缩放
//
对于(int x=0;x=0&&srcY>=0&&srcX
我的问题是:1) 这个公式正确吗?
2) 我把这个公式变成一个软件是错误的吗?
3) 还有其他的算法(例如wiki/扭曲(光学)),它们更好吗
谢谢你的帮助 可能是您的径向失真参数太大,图像被压缩在球体上。尝试在
a
、b
、c
和d
中输入较小的值。您的值非常极端,因此您会看到极端结果
试试a=0,b=0,c=1。这说明没有任何修正,如果你的程序是正确的,你应该看到原始图像。然后逐渐改变c和b。以0.1的增量进行更改是一个好的开始。我认为您的圆圈是由这条线引起的:
double srcYd = centerY + (diffX * factor);
我猜应该是:
double srcYd = centerY + (diffY * factor);
您遇到的主要错误是,该算法指定r_corr和r_src的单位为min((xDim-1)/2,(yDim-1)/2)。这需要进行正常化计算,以便参数值不依赖于源图像的大小。按照代码的原样,您需要为paramB使用更小的值,例如,它在paramB=0.00000002(对于尺寸为2272 x 1704的图像)的情况下工作正常 您在计算与中心的差异时也有一个错误,导致生成的图像与源图像相比旋转180度 修复这两个bug会给您带来如下好处:
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;
}
受保护的静态int[]校正2(int[]像素、int宽度、int高度){
int[]像素透视=像素。克隆();
//校正参数
双参数=-0.007715;//仅影响图像的最外层像素
double paramB=0.026731;//大多数情况下只需要b优化
双参数C=0.0;//最均匀校正
double paramD=1.0-paramA-paramB-paramC;//描述图像的线性缩放
对于(int x=0;x