OpenCV(3.4.1)错误:在cv :: Mat :: locateROI中断言失败(昏暗<= 2 && step [0]> 0)

时间:2018-06-20 13:08:10

标签: c++ visual-studio opencv exception camera-calibration

解释问题后,我将发布代码和异常。因此,基本上,我正在编写一个程序,其最终目标是能够校准鱼眼镜头相机,然后将其从相机的rtsp流中输出,并使用OpenCV和到目前为止的许多代码通过zoneminder进行记录。从这里得到:

http://aishack.in/tutorials/calibrating-undistorting-opencv-oh-yeah/

但是我刚开始注意到在我的代码的第53行弹出一个异常

 bool found = findChessboardCorners(image, board_sz,corners, CV_CALIB_CB_ADAPTIVE_THRESH | CV_CALIB_CB_FILTER_QUADS); 

,我不知道到底是什么原因造成的,一般来说,我对很多我尝试做的事情(包括堆栈溢出)还是陌生的,所以请随时留下任何您认为可能有帮助的输入或问可能需要问的任何问题。

另外,如果您自己运行代码,请注意,堆栈溢出似乎希望将某些行分开,因此请记住这一点以及需要OpenCV的事实。

代码:

// ConsoleApplication2.cpp : Defines the entry point for the console 
application.

#include <opencv2\videoio.hpp>
#include <opencv2\highgui.hpp>
#include <opencv\cv.hpp>
#include <opencv\cv.h>
#include <iostream>
#include <stdio.h>
#include <chrono>
#include <thread>


using namespace cv;
using namespace std;

int main (){
int numBoards = 0;
int numCornersHor;
int numCornersVer;

printf("Enter number of corners along width: ");
scanf_s("%d", &numCornersHor);

printf("Enter number of corners along height: ");
scanf_s("%d", &numCornersVer);

printf("Enter number of boards: ");
scanf_s("%d", &numBoards);

int numSquares = numCornersHor * numCornersVer;
Size board_sz = Size(numCornersHor, numCornersVer);

VideoCapture capture = VideoCapture("rtsp://172.16.127.27:554/mpeg4");

vector<vector<Point3f>> object_points;
vector<vector<Point2f>> image_points;

vector<Point2f> corners;
int successes = 0;

Mat image;
Mat gray_image;
capture >> image;

vector<Point3f> obj;
for (int j = 0; j < numSquares; j++)
    obj.push_back(Point3f(j / numCornersHor, j%numCornersHor, 0.0f));

while (successes < numBoards) {
    this_thread::sleep_for(chrono::milliseconds(100));
    cvtColor(image, gray_image, CV_BGR2GRAY);

    bool found = findChessboardCorners(image, board_sz, corners, 
CV_CALIB_CB_ADAPTIVE_THRESH | CV_CALIB_CB_FILTER_QUADS);

    if (found) {
        cornerSubPix(gray_image, corners, Size(11,11), Size(-1, -1), 
TermCriteria(CV_TERMCRIT_EPS | CV_TERMCRIT_ITER, 30, 0.1));
        drawChessboardCorners(gray_image, board_sz, corners, found);
    }

    imshow("win1", image);
    imshow("win2", gray_image);

    capture >> image;
    int key = waitKey(1);

    if (key == 27)

        return 0;

    if (key == ' ' && found != 0){
        image_points.push_back(corners);
        object_points.push_back(obj);

        printf("Snap stored!");

        successes++;

        if (successes >= numBoards)
            break;
    }
}

Mat intrinsic = Mat(3, 3, CV_32FC1);
Mat distCoeffs;
vector<Mat> rvecs;
vector<Mat> tvecs;

intrinsic.ptr<float>(0)[0] = 1;
intrinsic.ptr<float>(1)[1] = 1;

calibrateCamera(object_points, image_points, image.size(), intrinsic, 
distCoeffs, rvecs, tvecs);

Mat imageUndistorted;
while (1) {
    capture >> image;
    undistort(image, imageUndistorted, intrinsic, distCoeffs);

    imshow("win1", image);
    imshow("win2", imageUndistorted);
    waitKey(1);
}

capture.release();

return 0;
}

控制台错误:

OpenCV(3.4.1) Error: Assertion failed (dims <= 2 && step[0] > 0) in 
cv::Mat::locateROI, file C:\build\master_winpack-build-win64- 
vc15\opencv\modules\core\src\matrix.cpp, line 760

例外:

Exception thrown at 0x00007FFEFC21A388 in ConsoleApplication2.exe: Microsoft 
C++ exception: cv::Exception at memory location 0x000000637891D640.
Exception thrown at 0x00007FFEFC21A388 in ConsoleApplication2.exe: Microsoft 
C++ exception: [rethrow] at memory location 0x0000000000000000.
Exception thrown at 0x00007FFEFC21A388 in ConsoleApplication2.exe: Microsoft 
C++ exception: cv::Exception at memory location 0x000000637891D640.
Unhandled exception at 0x00007FFEFC21A388 in ConsoleApplication2.exe: 
Microsoft C++ exception: cv::Exception at memory location 0x000000637891D640.

编辑:所以,奇怪的是,我不再遇到这个问题,但是如果其他任何人碰巧遇到这个问题或有一些仍然有用的见解,我仍然会保留这个问题,我仍然遇到的问题是,尽管使用网络摄像头时相机没有问题,但相机似乎在第一帧上冻结了,但可以通过rtsp捕获,但是我将单独解决这个问题,因为这不是问题所在。

1 个答案:

答案 0 :(得分:0)

在第一帧校准代码开始冻结之前添加的最后一个代码是什么?

# 参考您的睡眠声明(在第一帧校准代码中)。我假设您是为了减少CPU使用率而介绍的,我将其删除并修改底部主循环中的waitKey()方法为waitKey(100),以在两次读取流之间等待100毫秒(或更短的时间)。

  1. 睡眠语句所在的位置并不是大多数CPU使用率所在的位置。您只需在应用程序的校准部分中执行一次即可。我将其删除。

  2. 您的计算机真正运转的地方是while(1)循环的主要底部,该循环不断从流中读取数据。

  3. 这就是说,实际上,当您调用waitKey()函数时,实际上不需要在底部的主while循环中使用sleep语句。只需将调用更改为waitKey(100)。

# 请参考您的scanf_s语句:将其转换为#defines,以便我们都知道您的输入是什么,或者向我们显示您输入的运行此命令行。重要信息。

希望有帮助!