整晚都在追逐这个错误,所以请原谅任何不连贯的地方。
我正在尝试使用 OpenCV 的calibrateCamera()
从一组 15 张图片中提取内在和外在参数,这些图片给出了对象点和世界点。从调试中可以看出,我从输入文件中获取有效点并将它们放置在一个vector<Point3f>
中,该本身被放置在另一个vector
中。
我把整个舍邦传给calibrateCamera()
,
double rms = calibrateCamera(worldPoints, pixelPoints, src.size(), intrinsic, distCoeffs, rvecs, tvecs);
抛出Assertion failed (ni >= 0) in unknown function, file ...calibration.cpp, line 3173
拉起这个文件给了我们
static void collectCalibrationData( InputArrayOfArrays objectPoints,
InputArrayOfArrays imagePoints1,
InputArrayOfArrays imagePoints2,
Mat& objPtMat, Mat& imgPtMat1, Mat* imgPtMat2,
Mat& npoints )
{
int nimages = (int)objectPoints.total();
int i, j = 0, ni = 0, total = 0;
CV_Assert(nimages > 0 && nimages == (int)imagePoints1.total() &&
(!imgPtMat2 || nimages == (int)imagePoints2.total()));
for( i = 0; i < nimages; i++ )
{
ni = objectPoints.getMat(i).checkVector(3, CV_32F);
CV_Assert( ni >= 0 );
total += ni;
}
...
据我所知,Point3f
的深度CV_32F
,在调用校准相机之前,我可以在双向量中看到良好的数据。
知道这里会发生什么吗? calibrateCamera()
需要vector<vector<Point3f>>
,正如 http://aishack.in/tutorials/calibrating-undistorting-with-opencv-in-c-oh-yes/和文档所说;希望getMat(i(不会因此而失败。
它是否可能在它之后的像素点vector<vector<Point2f>>
上调用?我犯了太多错误,我愿意相信任何事情。
编辑:因此,checkVector()
的文档并没有真正的帮助。
int cv::Mat::checkVector (int elemChannels, int depth = -1, bool RequireContinuous = true) const
returns N if the matrix is 1-channel (N x ptdim) or ptdim-channel (1 x N) or (N x 1); negative number otherwise
问题可能出在你的一个 InputArrayOfArrays 参数中(准确地说,在 worldPoints 中,如果断言是从粘贴在问题中的行中抛出的(。Mat:s 在这里应该可以正常工作。
我通过使所有 3 个 InputArrayOfArrays(或向量>和向量>在我的例子中(具有完全填充条目的相同长度的向量来解决代码中的相同断言错误。所以我的问题出在我的架构上:我的objectPoints向量包含空条目(即使现有数据有效(,并且校准.cpp要求在3个InputArrayOfArray中的任何一个中不存在空条目。顺便说一句,我正在使用灰度图像进行校准,因此单通道数据。
在 calib3d 源中,如果已检查数据类型是否匹配,则引发错误的最可能原因是空值。您可以尝试仔细检查有效的输入数据:
1( 从您选择的结构中计算有效校准图像的 # 个 validCalibImages = (int)goodCalibrationImages.size()
2( 将世界点定义为vector<vector<Point3f> > worldPoints
3( 重要提示:调整大小以适应每个校准条目的数据 worldPoints.resize(validCalibImages)
4( 填充数据,例如
for(int k = 0; k < (int)goodCalibImages.size(); k++){
for(int i = 0; i < chessboardSize.height; i++){
for(int j = 0; j < chessboardSize.width; j++){
objectPoints[k].push_back(Point3f(i*squareSize, j*squareSize, 0));
}
}
}
'希望对您有所帮助!
我同意 FSaccilotto - 调用 checkVector 并确保你传递的是一个大小为 n 的向量 Mat 1x1:{3 channel}
而不是 Mat 1 x n:{3 channel}
或更糟的向量Mat 1 x n:{2 channel}
这是 MatOfPoint 吐出的。 这通常可以修复 90% 的断言失败问题。 自己明确声明垫子。
对象模式有点奇怪,因为 x y z 坐标位于通道中,而不是在垫子维度中。