- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我有大量用鱼眼镜头拍摄的照片。因为我想对照片进行一些图像处理(例如边缘检测),所以我想消除严重影响结果的桶形失真。
经过一些研究和大量阅读文章后,我发现了这个 page : 他们描述了一种算法(和一些公式)来解决这个问题。
M = a *rcorr^3 + b * rcorr^2 + c * rcorr + d
rsrc = (a * rcorr^3 + b * rcorr^2 + c * rcorr + d) * rcorrrsrc = distance of a pixel from the center of the source image
rcorr = distance of a pixel from the center in the corrected image
a,b,c = distortion of image d = linear scaling of image
我使用了这些公式并尝试在 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) 还有其他算法(例如 How to simulate fisheye lens effect by openCV? 或 wiki/Distortion_(optics)),它们更好吗?
感谢您的帮助!
最佳答案
您遇到的主要错误是算法指定 r_corr 和 r_src 以 min((xDim-1)/2, (yDim-1)/2) 为单位。需要这样做来规范化计算,以便参数值不依赖于源图像的大小。使用代码,您需要为 paramB 使用更小的值,例如paramB = 0.00000002(对于尺寸为 2272 x 1704 的图像)对我来说效果很好。
您在计算与中心的差异时也有一个错误,导致生成的图像与源图像相比旋转了 180 度。
修复这两个错误应该会给你这样的东西:
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;
}
有了这个版本,您可以使用现有镜头数据库(例如 LensFun)中的参数值(尽管您需要翻转每个参数的符号)。描述该算法的页面现在可以在 http://mipav.cit.nih.gov/pubwiki/index.php/Barrel_Distortion_Correction 找到。
关于java - 用于校正 FishEye 镜头的桶形畸变校正算法 - 无法使用 Java 实现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12620025/
在面向 Web 的应用程序中开发优雅的 Pub-Sub 架构是一项真正的挑战。尽管有一些非常有趣的解决方案使用长轮询连接(例如 COMET)和重复超时(例如 js setTimeout)。恕我直言,A
我需要关于设计这样一个存储库的反馈,它会帮助我晚上休息,真的...... 我无意为 Web 表单编写测试,涉及的开销太大。 我无意在明天、下个月或明年更改 ORM 或数据库,并且我需要一个地方来集中查
我是一名优秀的程序员,十分优秀!