标签: camera-calibration

从图像点计算x,y坐标(3D)

我有一个任务是在3D坐标系中定位一个对象.由于我必须得到几乎精确的X和Y坐标,我决定使用已知的Z坐标跟踪一个颜色标记,该坐标将放置在移动对象的顶部,如此图片中的橙色球: undistored

首先,我已完成相机校准以获取内部参数,之后我使用cv :: solvePnP获取旋转和平移向量,如下面的代码所示:

std::vector<cv::Point2f> imagePoints;
std::vector<cv::Point3f> objectPoints;
//img points are green dots in the picture
imagePoints.push_back(cv::Point2f(271.,109.));
imagePoints.push_back(cv::Point2f(65.,208.));
imagePoints.push_back(cv::Point2f(334.,459.));
imagePoints.push_back(cv::Point2f(600.,225.));

//object points are measured in millimeters because calibration is done in mm also
objectPoints.push_back(cv::Point3f(0., 0., 0.));
objectPoints.push_back(cv::Point3f(-511.,2181.,0.));
objectPoints.push_back(cv::Point3f(-3574.,2354.,0.));
objectPoints.push_back(cv::Point3f(-3400.,0.,0.));

cv::Mat rvec(1,3,cv::DataType<double>::type);
cv::Mat tvec(1,3,cv::DataType<double>::type);
cv::Mat rotationMatrix(3,3,cv::DataType<double>::type);

cv::solvePnP(objectPoints, imagePoints, cameraMatrix, distCoeffs, rvec, tvec);
cv::Rodrigues(rvec,rotationMatrix);
Run Code Online (Sandbox Code Playgroud)

拥有所有矩阵之后,这个可以帮助我转换图像的方程指向wolrd坐标:

transform_equation

其中M是cameraMatrix,R - rotationMatrix,t - tvec和s是未知的.Zconst表示橙色球的高度,在本例中为285毫米.所以,首先我需要解决前面的方程,得到"s",然后通过选择图像点找出X和Y坐标: 方程2

解决这个问题我可以找到变量"s",使用矩阵的最后一行,因为Zconst是已知的,所以这里有以下代码:

cv::Mat uvPoint = (cv::Mat_<double>(3,1) << 363, 222, 1); // u = 363, v = 222, got this point using mouse callback …
Run Code Online (Sandbox Code Playgroud)

opencv camera-calibration pose-estimation

54
推荐指数
2
解决办法
2万
查看次数

如何验证网络摄像头校准的正确性?

我对相机校准技术完全不了解......我正在使用OpenCV棋盘技术...我正在使用Quantum的网络摄像头......

这是我的观察和步骤..

  1. 我保持每个国际象棋方面= 3.5厘米.这是一个7 x 5的棋盘,有6 x 4个内角.我在距离网络摄像头1到1.5米的距离拍摄了10张不同视角/姿势的图像.
  2. 我下面的C代码学习OpenCV的Bradski用于校准.我的校准代码是

    cvCalibrateCamera2(object_points,image_points,point_counts,cvSize(640,480),intrinsic_matrix,distortion_coeffs,NULL,NULL,CV_CALIB_FIX_ASPECT_RATIO);
    
    Run Code Online (Sandbox Code Playgroud)
  3. 在调用此函数之前,我将沿着内部矩阵的对角线的第一个和第二个元素作为一个,以保持焦距的比率恒定并使用 CV_CALIB_FIX_ASPECT_RATIO

  4. 随着棋盘距离的变化fxfy变化fx:fy几乎等于1.有200到400的数量级cxcy值.当我改变距离时fx,fy它们在300到700的数量级.

  5. 目前我把所有的失真系数都归零,因为我没有得到包括失真系数在内的好结果.我的原始图像看起来比未失真的图像更漂亮!!

我正确地进行了校准吗?我应该使用除CV_CALIB_FIX_ASPECT_RATIO?之外的任何其他选项吗?如果是的话,哪一个?

opencv computer-vision camera-calibration

53
推荐指数
2
解决办法
3万
查看次数

OpenCV 3.0:校准不符合预期

当我使用OpenCV 3.0 calibrateCamera时,我得到的结果是我没想到的.这是我的算法:

  1. 加载30个图像点
  2. 加载30个相应的世界点(在这种情况下是共面的)
  3. 使用点校准相机,只是为了不扭曲
  4. 不扭曲图像点,但不使用内在函数(共面世界点,因此内在函数是狡猾的)
  5. 使用未失真的点来找到单应性,转换为世界点(可以这样做,因为它们都是共面的)
  6. 使用单应性和透视变换将未失真的点映射到世界空间
  7. 将原始世界点与映射点进行比较

我所拥有的点是嘈杂的,只有一小部分图像.单个视图中有30个共面点,因此我无法获得相机内在函数,但应该能够获得失真系数和单应性以创建前平行视图.

正如预期的那样,误差取决于校准标志.但是,它与我的预期相反.如果我允许所有变量调整,我会期望错误降低.我不是说我期待一个更好的模型; 我实际上期望过度拟合,但这仍然应该减少错误.我看到的是,我使用的变量越少,我的错误越低.最好的结果是直接的单应性.

我有两个可疑的原因,但它们似乎不太可能,我想在播出它们之前听到一个纯粹的答案.我已经拿出代码来做我正在谈论的事情.它有点长,但它包括加载点.

代码似乎没有错误; 我使用了"更好"的点,它完美无缺.我想强调的是,这里的解决方案不能是使用更好的点或执行更好的校准; 练习的重点是看各种校准模型如何响应不同质量的校准数据.

有任何想法吗?

添加

要清楚,我知道结果会很糟糕,我希望如此.我也明白,我可能会学习不良的失真参数,这会导致在测试尚未用于训练模型的点时导致更糟糕的结果.我不明白的是当使用训练集作为测试集时,失真模型如何有更多的错误.也就是说,如果cv :: calibrateCamera应该选择参数来减少所提供的训练点集的误差,那么它产生的错误比它刚为K!,K2,... K6,P1选择0时产生的误差更大. ,P2.不管数据与否,它至少应该在训练集上做得更好.在我说数据不适合这个模型之前,我必须确保我能用尽可能多的数据做到最好,而且我现在不能说这个.

这是一个示例图像

标有绿色针脚的点.这显然只是一个测试图像. 示例图片

这是更多的例子

在下文中,图像是从上面的大图像中裁剪出来的.该中心没有改变.当我只用绿色引脚手动标记的点并且允许K1(仅K1)从0变化时,会发生这种情况:

之前 设置图像,1920 x 1080,失真

将图像设置为1920 x 1080,不失真

我会把它归结为一个bug,但是当我使用更大的一组点来覆盖更多的屏幕时,即使是在一个平面上,它的工作也相当不错.这看起来很可怕.但是,错误并不像你从图片中看到的那样糟糕.

// Load image points
    std::vector<cv::Point2f> im_points;
    im_points.push_back(cv::Point2f(1206, 1454));
    im_points.push_back(cv::Point2f(1245, 1443));
    im_points.push_back(cv::Point2f(1284, 1429));
    im_points.push_back(cv::Point2f(1315, 1456));
    im_points.push_back(cv::Point2f(1352, 1443));
    im_points.push_back(cv::Point2f(1383, 1431));
    im_points.push_back(cv::Point2f(1431, 1458));
    im_points.push_back(cv::Point2f(1463, 1445));
    im_points.push_back(cv::Point2f(1489, 1432));
    im_points.push_back(cv::Point2f(1550, 1461));
    im_points.push_back(cv::Point2f(1574, 1447));
    im_points.push_back(cv::Point2f(1597, 1434));
    im_points.push_back(cv::Point2f(1673, 1463));
    im_points.push_back(cv::Point2f(1691, 1449));
    im_points.push_back(cv::Point2f(1708, 1436));
    im_points.push_back(cv::Point2f(1798, 1464));
    im_points.push_back(cv::Point2f(1809, 1451));
    im_points.push_back(cv::Point2f(1819, 1438));
    im_points.push_back(cv::Point2f(1925, 1467));
    im_points.push_back(cv::Point2f(1929, …
Run Code Online (Sandbox Code Playgroud)

c++ opencv camera-calibration

41
推荐指数
1
解决办法
1708
查看次数

如果已知外部和内部参数,则从2D图像像素获取3D坐标

我正在从tsai algo做相机校准.我有内在和外在矩阵,但我怎样才能从该信息中重建三维坐标?

在此输入图像描述

1) 我可以使用高斯消元法找到X,Y,Z,W,然后将点作为齐次系统的X/W,Y/W,Z/W.

2)我可以使用 OpenCV文档方法:

在此输入图像描述

因为我知道u,v,R,t,我可以计算X,Y,Z.

然而,这两种方法最终都会产生不正确的结果.

我做错了什么?

c++ opencv homogenous-transformation camera-calibration pose-estimation

32
推荐指数
1
解决办法
3万
查看次数

为什么相机内在矩阵中的焦距有两个维度?

针孔摄像机模型中,只有一个焦距位于主点和摄像机中心之间.

但是,在计算相机的内部参数后,矩阵包含

(fx,  0,  offsetx,  0,
 0,  fy,  offsety,  0,
 0,   0,  1,        0)
Run Code Online (Sandbox Code Playgroud)

这是因为图像传感器的像素在x和y中不是正方形吗?

谢谢.

computer-vision perspectivecamera camera-calibration

24
推荐指数
1
解决办法
2万
查看次数

OpenCV:solvePnP检测问题

我有使用OpenCV精确检测标记的问题.

我录制了这个问题的视频:http://youtu.be/IeSSW4MdyfU

如你所见,我正在检测的标记在某些摄像机角度稍微移动.我在网上看到这可能是相机校准问题,所以我会告诉你们我是如何校准相机的,也许你能告诉我我做错了什么?

在开始时我正在从各种图像中收集数据,并将校准角存储在这样的_imagePoints矢量中

std::vector<cv::Point2f> corners;
_imageSize = cvSize(image->size().width, image->size().height);

bool found = cv::findChessboardCorners(*image, _patternSize, corners);

if (found) {
    cv::Mat *gray_image = new cv::Mat(image->size().height, image->size().width, CV_8UC1);
    cv::cvtColor(*image, *gray_image, CV_RGB2GRAY);

    cv::cornerSubPix(*gray_image, corners, cvSize(11, 11), cvSize(-1, -1), cvTermCriteria(CV_TERMCRIT_EPS+ CV_TERMCRIT_ITER, 30, 0.1));

    cv::drawChessboardCorners(*image, _patternSize, corners, found);
}

_imagePoints->push_back(_corners);
Run Code Online (Sandbox Code Playgroud)

收集到足够的数据后,我用这段代码计算相机矩阵和系数:

std::vector< std::vector<cv::Point3f> > *objectPoints = new std::vector< std::vector< cv::Point3f> >();

for (unsigned long i = 0; i < _imagePoints->size(); i++) {
    std::vector<cv::Point2f> currentImagePoints = _imagePoints->at(i);
    std::vector<cv::Point3f> currentObjectPoints;

    for (int j = …
Run Code Online (Sandbox Code Playgroud)

camera opencv markers camera-calibration ios

20
推荐指数
2
解决办法
6467
查看次数

Python Opencv SolvePnP产生错误的翻译向量

我正在尝试使用单应性校准并在Blender 3d中找到单个虚拟相机的位置和旋转.我正在使用Blender,以便在我进入真实世界之前我可以仔细检查我的结果.我在固定相机的视野中渲染了十张不同位置的棋盘图片和旋转.使用opencv的python,我使用cv2.calibrateCamera从十个图像中检测到的棋盘角上找到内在矩阵,然后在cv2.solvePnP中使用它来查找外部参数(平移和旋转).然而,尽管估计的参数接近实际参数,但仍然存在一些可疑的参数.我对翻译的初步估计是(-0.11205481,-0.0490256,8.13892491).实际位置是(0,0,8.07105).非常接近吧?但是,当我移动并稍微旋转相机并重新渲染图像时,估计的平移变得更远了.估计:( - 0.15933154,0.13367286,9.34058867).实际:( - 1.7918,-1.51073,9.76597).Z值接近,但X和Y不接近.我完全糊涂了.如果有人能帮助我解决这个问题,我将非常感激.这是代码(它基于随opencv提供的python2校准示例):

#imports left out
USAGE = '''
USAGE: calib.py [--save <filename>] [--debug <output path>] [--square_size] [<image mask>]
'''   

args, img_mask = getopt.getopt(sys.argv[1:], '', ['save=', 'debug=', 'square_size='])
args = dict(args)
try: img_mask = img_mask[0]
except: img_mask = '../cpp/0*.png'
img_names = glob(img_mask)
debug_dir = args.get('--debug')
square_size = float(args.get('--square_size', 1.0))

pattern_size = (5, 8)
pattern_points = np.zeros( (np.prod(pattern_size), 3), np.float32 )
pattern_points[:,:2] = np.indices(pattern_size).T.reshape(-1, 2)
pattern_points *= square_size

obj_points = []
img_points = []
h, w = 0, …
Run Code Online (Sandbox Code Playgroud)

python opencv camera-calibration

17
推荐指数
1
解决办法
1万
查看次数

更小的重投影错误总是意味着更好的校准吗?

在相机校准期间,通常的建议是使用许多图像(> 10),其中包括姿势,深度等变化.但是我注意到,通常我使用的图像越少,重投影误差越小.例如,对于27个图像,cv :: calibrateCamera返回0.23并且仅有3我得到0.11这可能是由于在校准期间我们正在解决超定系统的最小二乘问题.

问题:

  1. 我们是否真的使用重投影误差作为校准良好程度的绝对量度?例如,如果我使用3张图像进行校准并获得0.11,然后使用其他27张图像进行校准并得到0.23,我们真的可以说"第一次校准更好"吗?

  2. OpenCV使用相同的图像进行校准和计算误差.是不是有某种形式的过度拟合?如果我实际使用了2个不同的设置 - 一个用于计算校准参数而另一个用于计算误差 - 那么这不是更正确吗?在这种情况下,我会使用相同的(测试)集来计算来自不同(训练)集的所有校准结果的误差.那不是更公平吗?

opencv camera-calibration

16
推荐指数
1
解决办法
1万
查看次数

OpenCV3.0.0dev中鱼眼摄像机模型的主要参考是什么?

我正在与OpenCV 3.0.0.dev中使用的鱼眼相机模型搏斗.我已多次阅读此链接中的文档 ,尤其是"详细说明"部分和鱼眼失真模型.到现在为止,我有两个问题:

  1. 基于这里列出的投影模型及其在" 鱼眼镜头模型的准确性 "中的概念解释,Hughes,我无法弄清楚在OpenCV实现中使用了哪种投影模型.
  2. 由于描述非常简洁,我需要了解OpenCV开发人员用于实现鱼眼命名空间的主要参考文件,以便我能够掌控并了解更多细节.PS我检查了OpenCV 3.0.0-dev文档,但没有找到任何有用的东西.
    谢谢大家的帮助,

亲切的问候,

马希赫

c++ opencv fisheye camera-calibration opencv3.0

16
推荐指数
2
解决办法
8187
查看次数

FindChessboardCorners无法通过长焦距镜头检测非常大的图像上的棋盘

我可以将FindChessboardCorners函数用于小于15百万像素的图像,如2k x 1.5k.然而,当我在DSLR的图像上使用它时,分辨率为3700x5300,它不起作用.

我试图使用resize()直接缩小图像大小,然后它工作.

显然,OpenCV源代码中存在一些硬编码或错误.

你能帮我解决一下,还是指点一下这个补丁?

我发现有人在2006年发布了类似的问题,在这里,所以它看起来像问题仍然存在.

我使用的代码就像

found = findChessboardCorners( viewGray, boardSize, ptvec,
                                CV_CALIB_CB_ADAPTIVE_THRESH + CV_CALIB_CB_FILTER_QUADS + CV_CALIB_CB_NORMALIZE_IMAGE + CV_CALIB_CB_FAST_CHECK);
Run Code Online (Sandbox Code Playgroud)

更新

就在这里澄清一下.我认为该算法适用于较大的图像分辨率,但当棋​​盘占据较大比例的图像时,它会失败.例如,当我在相同的相机位置使用50mm固定镜头时,FindChessboardCorners永远不会失败.将其更改为100mm固定镜头后,该功能开始停止检测图案.我认为这与比例或焦距有关.

下图是100mm镜头效果.

更新2

我为大图像添加了一个锐化滤镜,它开始解决问题.

首先我用过

//do a sharpen filter for the large resolution image
if (viewGray.cols > 1500)
{
  Mat temp ;
  GaussianBlur(viewGray,temp, Size(0,0), 105) ; //hardcoded filter size, to be tested on 50 mm lens
  addWeighted(viewGray, 1.8, temp, -0.8,0,viewGray) ; //hardcoded weight, to be tested.
//imwrite("test"+ imageList[k][i], viewGray) ;

}

found = findChessboardCorners( viewGray, boardSize, …
Run Code Online (Sandbox Code Playgroud)

c++ opencv computer-vision camera-calibration

15
推荐指数
1
解决办法
1万
查看次数