2

整晚都在追这个bug,所以请原谅任何不连贯的地方。

我正在尝试使用 OpenCVcalibrateCamera()从一组 15 张图片中提取内在和外在参数,这些图片的对象点和世界点都已给出。从调试中可以看出,我正在从输入文件中获取有效点并将它们放在 avector<Point3f>中,而它本身又放在另一个vector.

calibrateCamera()我把整个shebang传给

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;
}
...

据我所知,aPoint3f具有CV_32F深度,并且在调用 calibrateCamera 之前,我可以在双向量中看到良好的数据。

有什么想法可能在这里发生吗?calibrateCamera()需要 a vector<vector<Point3f>>,如http://aishack.in/tutorials/calibrating-undistorting-with-opencv-in-c-oh-yeah/和文档所述;希望 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
4

2 回答 2

1

问题可能出在您的 InputArrayOfArrays 参数之一中(确切地说,在 worldPoints 中,如果断言是从粘贴在您问题中的行中抛出的)。Mat:s 在这里应该可以正常工作。

我通过使所有 3 个 InputArrayOfArrays(或向量 > 和向量 > 在我的例子中)具有完全填充的条目的相同长度向量解决了我的代码中的相同断言错误。所以我的问题出在我的架构中:我的 objectPoints 向量包含空条目(即使现有数据是有效的),并且 calibrate.cpp 要求 3 个 InputArrayOfArrays 中的任何一个中都不存在空条目。顺便说一句,我使用灰度图像来校准单通道数据。

在 calib3d 源中,如果您检查了数据类型是否匹配,则引发错误的最可能原因是 null 值。您可以尝试仔细检查您的有效输入数据:

1)从您选择的结构中计算有效校准图像的数量 validCalibImages = (int)goodCalibrationImages.size()

2) 将 worldPoints 定义为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));
            }
        }
    }

' 希望能帮助到你!

于 2013-08-10T14:54:38.320 回答
-1

我同意 FSaccilotto - 调用 checkVector 并确保您传递的是大小为 n 的Mat 1x1:{3 channel}向量而不是向量Mat 1 x n:{3 channel}或更糟的向量,Mat 1 x n:{2 channel}这就是 MatOfPoint 吐出的。这通常可以解决 90% 的断言失败问题。自己明确声明 Mat。

对象模式有点奇怪,因为 xyz 坐标在通道中而不是在 Mat 尺寸中。

于 2013-07-29T20:17:07.450 回答