I discovered how to map a linear lens ,从destination
坐标到source
坐标。
如何计算从中心到鱼眼到直线的径向距离?
我有一些要点描述了用鱼眼镜头拍摄的照片中的位置。
我想将这些点转换为直线坐标。我想使图像不失真。
我已经找到this description关于如何产生鱼眼效果,但是没有扭转它的方法。
还有一个blog post描述如何使用工具来完成它。这些图片来自:
(1):
SOURCE
Original photo link输入:修正了鱼眼失真的原始图像。
(2):
DESTINATION
Original photo link输出:校正后的图像(技术上也可以使用透视校正,但这是一个单独的步骤)。
您如何计算从中心到鱼眼到直线的径向距离?
我的函数存根看起来像这样:
Point correct_fisheye(const Point& p,const Size& img) {
// to polar
const Point centre = {img.width/2,img.height/2};
const Point rel = {p.x-centre.x,p.y-centre.y};
const double theta = atan2(rel.y,rel.x);
double R = sqrt((rel.x*rel.x)+(rel.y*rel.y));
// fisheye undistortion in here please
//... change R ...
// back to rectangular
const Point ret = Point(centre.x+R*cos(theta),centre.y+R*sin(theta));
fprintf(stderr,"(%d,%d) in (%d,%d) = %f,%f = (%d,%d)\n",p.x,p.y,img.width,img.height,theta,R,ret.x,ret.y);
return ret;
}
或者,我可以在找到点之前以某种方式将图像从鱼眼转换为直线,但是我完全被OpenCV documentation所迷惑。在OpenCV中是否有一种简单的方法可以做到这一点,并且它的性能足以将其用于实时视频供稿?
最佳答案
description you mention指出针孔相机的投影(不引起镜头失真的投影)是通过以下方式建模的:
R_u = f*tan(theta)
普通鱼眼镜头相机的投影(即变形)的模型为
R_d = 2*f*sin(theta/2)
您已经知道R_d和theta,并且如果您知道相机的焦距(用f表示),那么校正图像就等于根据R_d和theta计算R_u。换一种说法,
R_u = f*tan(2*asin(R_d/(2*f)))
是您要寻找的公式。估计焦距f可以通过校准相机或其他方式来解决,例如让用户提供有关图像校正程度的反馈或使用原始场景的知识。
为了使用OpenCV解决相同的问题,您必须获得相机的固有参数和镜头畸变系数。例如,参见Learning OpenCV的第11章(不要忘记检查correction)。然后,您可以使用诸如此类的程序(使用针对OpenCV的Python绑定(bind)编写)来消除镜头失真:
#!/usr/bin/python
# ./undistort 0_0000.jpg 1367.451167 1367.451167 0 0 -0.246065 0.193617 -0.002004 -0.002056
import sys
import cv
def main(argv):
if len(argv) < 10:
print 'Usage: %s input-file fx fy cx cy k1 k2 p1 p2 output-file' % argv[0]
sys.exit(-1)
src = argv[1]
fx, fy, cx, cy, k1, k2, p1, p2, output = argv[2:]
intrinsics = cv.CreateMat(3, 3, cv.CV_64FC1)
cv.Zero(intrinsics)
intrinsics[0, 0] = float(fx)
intrinsics[1, 1] = float(fy)
intrinsics[2, 2] = 1.0
intrinsics[0, 2] = float(cx)
intrinsics[1, 2] = float(cy)
dist_coeffs = cv.CreateMat(1, 4, cv.CV_64FC1)
cv.Zero(dist_coeffs)
dist_coeffs[0, 0] = float(k1)
dist_coeffs[0, 1] = float(k2)
dist_coeffs[0, 2] = float(p1)
dist_coeffs[0, 3] = float(p2)
src = cv.LoadImage(src)
dst = cv.CreateImage(cv.GetSize(src), src.depth, src.nChannels)
mapx = cv.CreateImage(cv.GetSize(src), cv.IPL_DEPTH_32F, 1)
mapy = cv.CreateImage(cv.GetSize(src), cv.IPL_DEPTH_32F, 1)
cv.InitUndistortMap(intrinsics, dist_coeffs, mapx, mapy)
cv.Remap(src, dst, mapx, mapy, cv.CV_INTER_LINEAR + cv.CV_WARP_FILL_OUTLIERS, cv.ScalarAll(0))
# cv.Undistort2(src, dst, intrinsics, dist_coeffs)
cv.SaveImage(output, dst)
if __name__ == '__main__':
main(sys.argv)
还要注意,OpenCV使用的镜头畸变模型与您链接到的网页中的模型完全不同。
关于math - 以编程方式校正鱼眼失真,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/2477774/