I keep getting an assertion failed(0 <= i && i < (int)vv.size())in cv::_InputArray::getMat, in file matrix.cpp when trying to run projectPoints. I have checked everything I can think of but I can't work out what's wrong. My guess is something went wrong with the calibratecamera but I don't know how I would find out what is wrong exactly. Here is my code, thanks.
using namespace cv;
using namespace std;
std::vector<cv::Point3f> Generate3DPoints()
{
std::vector<cv::Point3f> points;
float x,y,z;
x=.5;y=.5;z=.5;
points.push_back(cv::Point3f(x,y,z));
x=0;y=0;z=0;
points.push_back(cv::Point3f(x,y,z));
x=-0;y=0;z=.5;
points.push_back(cv::Point3f(x,y,z));
x=0;y=.5;z=.5;
points.push_back(cv::Point3f(x,y,z));
x=0;y=-.5;z=0;
points.push_back(cv::Point3f(x,y,z));
x=.5;y=0;z=.5;
points.push_back(cv::Point3f(x,y,z));
x=.5;y=0;z=0;
points.push_back(cv::Point3f(x,y,z));
/*
for(unsigned int i = 0; i < points.size(); ++i)
{
std::cout << points[i] << std::endl;
}
*/
return points;
}
int main()
{
int numBoards = 4;
int numCornersHor = 6;
int numCornersVer = 9;
int numSquares = numCornersHor * numCornersVer;
Size board_sz = Size(numCornersHor, numCornersVer);
VideoCapture capture = VideoCapture(0);
vector<vector<Point3f>> object_points;
vector<vector<Point2f>> imagePoints;
vector<vector<Point2f>> image_points;
vector<Point3f> objectPoints1 = Generate3DPoints();
vector<Point2f> corners;
int successes=0;
Mat image;
Mat gray_image;
//capture >> image;
Sleep(1000);
capture.read(image);
imshow("Welcome", image);
vector<Point3f> obj;
for(int j=0;j<numSquares;j++)
obj.push_back(Point3f(j/numCornersHor, j%numCornersHor, 0.0f));
while(successes<numBoards)
{
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);
cout << "SUCESS\n";
}
else
cout << "FAIL\n";
imshow("win1", image);
imshow("win2", gray_image);
capture.read(image);
image_points.push_back(corners);
object_points.push_back(obj);
printf("Snap stored!\n");
char continues;
cout << "Press c to continue\n";
cin >> continues;
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);
cout << "Done\n";
projectPoints(objectPoints1, rvecs, tvecs, intrinsic, distCoeffs, imagePoints);
cout << "done2";
return 0;
}
You are trying to pass rvecs and tvecs to the function projectPoints, which expects Mat and not vector<Mat>.
Basically, the calibrateCamera function estimates the intrinsics matrix and distortion coefficients of the camera using several images of a chessboard. The function also returns multiple versions of the extrinsics parameters (rotation+translation), one for each image you used. These extrinsic parameters are stored in rvecs and tvecs.
However, you want to project the 3D points in only one of these images, so you should choose what set of extrinsic parameters you want (i.e. rvecs[i] and tvecs[i], i corresponding to the image in which you want to project your object) and call projectPoints for these extrinsic parameters only, not the whole vectors<Mat>.
Related
I need to find the yaw, roll and pitch angles from a webcam stream of a face. I used opencv to get face landmarks and detect the face. Can someone help or guide me on how to find and print those angles?
I am using Visual Studio 2022 (community).
Ptr<Facemark> facemark; //mark detection
CascadeClassifier faceDetector; //face detection
void process(Mat img, Mat imgcol) {
vector<Rect> faces;
faceDetector.detectMultiScale(img, faces);
Mat imFace;
if (faces.size() != 0) {
for (size_t i = 0; i < faces.size(); i++)
{
cv::rectangle(imgcol, faces[i], Scalar(255, 0, 0));
imFace = imgcol(faces[i]);
resize(imFace, imFace, Size(imFace.cols * 5, imFace.rows * 5));
faces[i] = Rect(faces[i].x = 0, faces[i].y = 0, faces[i].width * 5,
(faces[i].height) * 5);
}
vector< vector<Point2f> > shapes;
if (facemark->fit(imFace, faces, shapes))
{
for (unsigned long i = 0; i < faces.size(); i++) {
for (unsigned long k = 0; k < shapes[i].size(); k++) {
cv::circle(imFace, shapes[i][k], 5, cv::Scalar(0, 0, 255),FILLED);
}
}
}
namedWindow("Detected_shape");
imshow("Detected_shape", imFace);
waitKey(5);
}
else {
cout << "Faces not detected." << endl;
}
}
int main()
{
facemark = FacemarkLBF::create();
facemark->loadModel("lbfmodel.yml");
faceDetector.load("D:/opencv/build/install/etc/haarcascades/haarcascade_frontalface_alt2.xml");
cout << "Loaded model" << endl;
VideoCapture cap(1); //capture image
int initialized = 0;
for (;;)
{
if (!cap.isOpened()) {
cout << "Video Capture Fail" << endl;
break;
}
else {
Mat img; //image containers
Mat imgbw;
cap >> img; //image from webcam
resize(img, img, Size(460, 460), 0, 0, INTER_LINEAR_EXACT);
cvtColor(img, imgbw, COLOR_BGR2GRAY);
process(imgbw, img);
namedWindow("Live", WINDOW_AUTOSIZE);
imshow("Live", img);
waitKey(5);
}
}
}
The code includes what I could do so far. It detects a face and landmarks. How do I find the angles and print them from this?
I tried to calibrate Iphone 11 Pro camera and openCV calibrateCamera() function returns error more than 1.2+ (same for computeReprojectionErrors() below). I want them to be lower than 0.5, because after this I am making disparity map and I need it to be smooth. How can I minimize it? Here is my code and I made 90 pictures of board from diffirent angles which are stored in ../chess_image. Here is code: github.com/markilebyak/opencv.git
Also here: 4shared.com/folder/PSDaeTcI/opencv.html are 36 images from those 90 I used, and 34 grayscaled with detected lines from those 36.
void createKnownBoardPosition(Size &boardSize, float squareEdgeLength, vector<Point3f>& corners) {
for (int i = 0; i < boardSize.height; i++) {
for (int j = 0; j < boardSize.width; j++) {
corners.emplace_back((float)j * squareEdgeLength, (float)i * squareEdgeLength, 0.0f);
}
}
}
void process_images(std::string &path_to_directory, Size &chessboard_size, vector<vector<Point2f>>& allFoundCorners) {
// Function to iterate through images
// taken for camera calibration
vector<String> filenames;
cv::glob(path_to_directory, filenames);
vector<Point2f> pointBuffer;
int counter = 0;
for (const auto & filename : filenames) {
if (filename != "../chess_images/.DS_Store"){
Mat im = imread(filename);
std::cout << filename << std::endl;
Mat gray_im;
cvtColor(im, gray_im, COLOR_BGR2GRAY);
bool found = findChessboardCorners(gray_im, chessboard_size, pointBuffer,
CALIB_CB_ADAPTIVE_THRESH | CALIB_CB_NORMALIZE_IMAGE);
if (found) {
counter++;
TermCriteria criteria = TermCriteria( TermCriteria::EPS + TermCriteria::MAX_ITER,
30,0.0001 );
Size winSize = Size( 11, 11);
Size zeroZone = Size( -1, -1 );
//cornerSubPix is the algorithm focused on relocating the points. it receives the image, the corners
// a window size, zeroZone and the actual criteria. The window size is the search area.
cornerSubPix(gray_im, pointBuffer, winSize, zeroZone, criteria );
drawChessboardCorners( gray_im, chessboard_size, Mat(pointBuffer), found );
string nametext = "../drawn_chessboard/" + to_string(counter) + ".jpg";
imwrite(nametext, gray_im);
allFoundCorners.push_back(pointBuffer);
}
}
}
std::cout << "Images used: " << counter << std::endl;
}
double computeReprojectionErrors( const vector<vector<Point3f> >& objectPoints,
const vector<vector<Point2f> >& imagePoints,
const vector<Mat>& rvecs, const vector<Mat>& tvecs,
const Mat& cameraMatrix , const Mat& distCoeffs,
vector<float>& perViewErrors, bool fisheye) {
vector<Point2f> imagePoints2;
size_t totalPoints = 0;
double totalErr = 0, err;
perViewErrors.resize(objectPoints.size());
for(size_t i = 0; i < objectPoints.size(); ++i )
{
if (fisheye)
{
fisheye::projectPoints(objectPoints[i], imagePoints2, rvecs[i], tvecs[i], cameraMatrix,
distCoeffs);
}
else
{
projectPoints(objectPoints[i], rvecs[i], tvecs[i], cameraMatrix, distCoeffs, imagePoints2);
}
err = norm(imagePoints[i], imagePoints2, NORM_L2);
size_t n = objectPoints[i].size();
perViewErrors[i] = (float) std::sqrt(err*err/n);
totalErr += err*err;
totalPoints += n;
}
return std::sqrt(totalErr/totalPoints);
}
void calibration_process(Size &boardSize, float &squareEdgeLength, Mat& cameraMatrix, Mat& distortionCoefficients,
std::string &path_to_directory) {
vector<vector<Point2f>> checkerboardImageSpacePoints;
process_images(path_to_directory, boardSize, checkerboardImageSpacePoints);
vector<vector<Point3f>> worldSpaceCornerPoints(1);
createKnownBoardPosition(boardSize, squareEdgeLength, worldSpaceCornerPoints[0]);
worldSpaceCornerPoints.resize(checkerboardImageSpacePoints.size(), worldSpaceCornerPoints[0]);
//rotation and translation vectors (rVectors, tVectors)
vector<Mat> rVectors, tVectors;
distortionCoefficients = Mat::zeros(8, 1, CV_64F);
calibrateCamera(worldSpaceCornerPoints, checkerboardImageSpacePoints, boardSize, cameraMatrix,
distortionCoefficients, rVectors, tVectors, CALIB_FIX_K5 + CALIB_FIX_INTRINSIC);
vector<float> perViewErrors;
double rep_error = computeReprojectionErrors(worldSpaceCornerPoints, checkerboardImageSpacePoints, rVectors, tVectors, cameraMatrix,
distortionCoefficients, perViewErrors, false);
std::cout << "Reprojection Error: " << rep_error << std::endl;
}
int main() {
Mat cameraMatrix, distortionCoefficient;
Size chessboardDimensions = Size(6, 9);
float calibrationSquareDimension = 0.03f;
std::string path = "../chess_images";
calibration_process(chessboardDimensions, calibrationSquareDimension, cameraMatrix,
distortionCoefficient, path);
return 0;
}
The Error:
OpenCV(3.4.1) Error: Assertion failed (i < 0) in cv::debug_build_guard::_InputArray::getMat_,
file C:\build\master_winpack-build-win64-vc15\opencv\modules\core\src\matrix_wrap.cpp, line 50
The Code inside "matrix_wrap.cpp" that triggers the Error:
if( k == STD_VECTOR )
{
CV_Assert( i < 0 );
int t = CV_MAT_TYPE(flags);
const std::vector<uchar>& v = *(const std::vector<uchar>*)obj;
return !v.empty() ? Mat(size(), t, (void*)&v[0]) : Mat();
}
Entire Code:
#include <iostream>
#include <opencv2/opencv.hpp>
int main(int argc, char *argv[])
{
cv::Mat img = cv::imread(argv[1], CV_LOAD_IMAGE_GRAYSCALE);
cv::Size imageSize = cv::Size(img.size[0], img.size[1]);
cv::Mat cameraMatrix, distCoeffs;
double squareSize = 30;
cv::Size boardSize = cv::Size(6, 11);
std::vector<cv::Point2f> imagePoints;
std::vector<cv::Point3f> objectPoints;
for (int i = 0; i < boardSize.height; i++) {
for (int j = 0; j < boardSize.width; j++) {
objectPoints.push_back(
cv::Point3f(float(j * squareSize), float(i * squareSize), 0));
}
}
std::vector<cv::Mat> rvecs, tvecs;
bool found = false;
if (img.size[0] > 1)
{
bool found = findChessboardCorners(img, boardSize, imagePoints, cv::CALIB_CB_ADAPTIVE_THRESH);
if (found)
{
drawChessboardCorners(img, boardSize, imagePoints, found);
}
objectPoints.resize(imagePoints.size(), objectPoints[0]);
double rms = calibrateCamera(objectPoints, imagePoints, imageSize, cameraMatrix, distCoeffs, rvecs, tvecs);
cv::namedWindow("My Image");
cv::imshow("My Image", img);
cv::waitKey(1000);
}
return 0;
}
I want to use a basic camera calibration with a straigth chessboard.
Until the function "calibrateCamera" everything works fine, but I can't figure out why this Error shows up.
The size of "objectPoints" and "imagePoints" is the same.
Thank you in advance.
P.S.:
I'm new in this forum and also in OpenCV ;)
As per this source of opencv, lines 3139 and 3142 :
CV_Error(CV_StsUnsupportedFormat, "objectPoints should contain vector of vectors of points of type Point3f");
CV_Error(CV_StsUnsupportedFormat, "imagePoints1 should contain vector of vectors of points of type Point2f");
the types for objectPoints and imagePoints should be std::vector<std::vector<Point{2|3}f>>
EDIT: I found the cause of the problem, the fisheye::undistortImage() function was not working correctly, I replaced it with estimateNewCameraMatrixForUndistortRectify(), initUndistortRectifyMap(), and remap() as in the original calibrate camera example. Not perfect yet but going in the right direction. Output image: http://imgur.com/a/Xm5vq
Mat output;
Mat newK;
Mat view, map1, map2;
Size newSize(1200, 1200);
Mat rview(newSize, frame.type());
//resize(rview, rview, newSize);
fisheye::estimateNewCameraMatrixForUndistortRectify(K, D, frame.size(), Matx33d::eye(), newK, 1);
fisheye::initUndistortRectifyMap(K, D, Matx33d::eye(), newK, frame.size(), CV_16SC2, map1, map2);
//fisheye::undistortImage(frame, output, K, D, identity);
remap(frame, rview, map1, map2, INTER_LINEAR);
imshow("Image View", rview);
imshow(window_name, frame);
if (waitKey(50) == 27) {
break;
}
Original post:
I'm trying to calibrate and undistort an image coming from an 180 degree fisheye USB camera. Most of this code is from existing examples that claim to be functional.
The code runs fine until fisheye::undistortImage where the output image is very distorted and centered around the top left corner of the window.
Screen shot of the "undistorted" chess board and calibration matrix outputs -
http://imgur.com/a/RTIoT
What am I missing here?
int main(int argc, char** argv) {
VideoCapture camera;
camera.open(1);
if (!camera.isOpened()) {
cout << "Failed to open camera." << std::endl;
return -1;
}
double fWidth = camera.get(CAP_PROP_FRAME_WIDTH);
double fHeight = camera.get(CAP_PROP_FRAME_HEIGHT);
cout << fWidth << std::endl;
cout << fHeight << std::endl;
/*
640 320
480 240
*/
const char* window_name = "output";
namedWindow(window_name, WINDOW_NORMAL);
Mat frame;
Size boardSize;
boardSize.width = 9;
boardSize.height = 6;
int remaining_frames = 30;
Mat K;// = Mat(3, 3, CV_64F, vK);
Mat D;
Mat identity = Mat::eye(3, 3, CV_64F);
vector<vector<Point2f> > img_points;
vector<vector<Point3f> > obj_points(1);
int sq_sz = 25;
for (int i = 0; i < boardSize.height; i++) {
for (int j = 0; j < boardSize.width; j++) {
obj_points[0].push_back(Point3f(float(j * sq_sz), float(i * sq_sz), 0));
}
}
obj_points.resize(remaining_frames, obj_points[0]);
bool found = false;
clock_t prevTimestamp = 0;
int delay = 500;
while (1) {
frame = nextFrame(camera);
bool blinkOutput = false;
if (remaining_frames > 0) {
vector<Point2f> corners;
int chessBoardFlags = CALIB_CB_ADAPTIVE_THRESH + CALIB_CB_NORMALIZE_IMAGE;
found = findChessboardCorners(frame, boardSize, corners, chessBoardFlags);
if (found) {
drawChessboardCorners(frame, boardSize, corners, found);
if (clock() - prevTimestamp > delay*1e-3*CLOCKS_PER_SEC) {
Mat viewGray;
cvtColor(frame, viewGray, COLOR_BGR2GRAY);
cornerSubPix(viewGray, corners, Size(11, 11), Size(-1, -1), TermCriteria(TermCriteria::EPS + TermCriteria::COUNT, 30, 0.1));
img_points.push_back(corners);
remaining_frames--;
cout << remaining_frames << " frames to calibration." << endl;
blinkOutput = true;
prevTimestamp = clock();
}
if (remaining_frames == 0) {
cout << "Computing distortion" << endl;
int flags = 0;
flags |= cv::fisheye::CALIB_RECOMPUTE_EXTRINSIC;
flags |= cv::fisheye::CALIB_CHECK_COND;
flags |= cv::fisheye::CALIB_FIX_SKEW;
fisheye::calibrate(obj_points, img_points, frame.size(), K, D, noArray(), noArray(), flags);
cout << "Finished computing distortion" << endl;
cout << K << endl;
cout << D << endl;
}
}
if (blinkOutput) { bitwise_not(frame, frame); }
cv::imshow(window_name, frame);
if (waitKey(50) == 27) {
break;
}
}
else {
Mat output;
fisheye::undistortImage(frame, output, K, D, identity);
cv::imshow(window_name, output);
if (waitKey(50) == 27) {
break;
}
}
}
return 0;
}
I am trying to generate a point cloud with my Minoru3D stereo camera, but it does not work.
The generated points are definitely not correct.
The camera is correctly calibrated.
My rectified images(rec1, rec2), the disparity map(disp) and the depth map(depth):
And the pointcloud:
I create the depth image with reprojectImageTo3D and then read the points at every pixel.
Full Code:
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/contrib/contrib.hpp>
#include <opencv2/calib3d/calib3d.hpp>
#include "libcam.h"
#include <stdio.h>
#include <fstream>
using namespace cv;
using namespace std;
int main(int argc, char** argv) {
// The camera properties
int w = 640;
int h = 480;
int fps = 20;
// The images, which are proceeded
Mat img1, img2;
// The grayscale versions of the images
Mat gray1, gray2;
// The disparity and depth map
Mat disparity;
Mat depth(Size(h, w), CV_32FC3);
// The iplImage versions of the images used to get the images from the camera
IplImage *iplImg1 = cvCreateImage(cvSize(w, h), 8, 3), *iplImg2 = cvCreateImage(cvSize(w, h), 8, 3);
// The cameras
Camera cam1("/dev/video0", w, h, fps), cam2("/dev/video1", w, h, fps);
// Load the camera model
Mat CM1, CM2, D1, D2, R, T, E, F, R1, R2, P1, P2, Q;
FileStorage fs("data/stereocalib.yml", FileStorage::READ);
fs["CM1"] >> CM1;
fs["CM2"] >> CM2;
fs["D1"] >> D1;
fs["D2"] >> D2;
fs["R"] >> R;
fs["T"] >> T;
fs["E"] >> E;
fs["F"] >> F;
fs["R1"] >> R1;
fs["R2"] >> R2;
fs["P1"] >> P1;
fs["P2"] >> P2;
fs["Q"] >> Q;
fs.release();
Mat map1x = Mat(h, w, CV_32F);
Mat map1y = Mat(h, w, CV_32F);
Mat map2x = Mat(h, w, CV_32F);
Mat map2y = Mat(h, w, CV_32F);
initUndistortRectifyMap(CM1, D1, R1, P1, cvSize(w, h), CV_32FC1, map1x, map1y);
initUndistortRectifyMap(CM2, D2, R2, P2, cvSize(w, h), CV_32FC1, map2x, map2y);
// The rectified images
Mat imgU1 = Mat(img1.size(), img1.type()), imgU2 = Mat(img2.size(), img2.type());
Ptr<StereoBM> sbm = createStereoBM(16 * 10, 5);
while (true) {
// Get the images from the cameras
cam1.Update();
cam2.Update();
cam1.toIplImage(iplImg1);
cam2.toIplImage(iplImg2);
img1 = cvarrToMat(iplImg1);
img2 = cvarrToMat(iplImg2);
// Rectify
remap(img1, imgU1, map1x, map1y, INTER_LINEAR, BORDER_CONSTANT, Scalar());
remap(img2, imgU2, map2x, map2y, INTER_LINEAR, BORDER_CONSTANT, Scalar());
// Convert the rectified images to grayscale images
cvtColor(imgU1, gray1, CV_BGR2GRAY);
cvtColor(imgU2, gray2, CV_BGR2GRAY);
// Create disparity map
sbm->compute(gray1, gray2, disparity);
// Create depth map
reprojectImageTo3D(disparity, depth, Q, true, CV_32F);
//imshow("img1", img1);
//imshow("img2", img2);
imshow("rec1", gray1);
imshow("rec2", gray2);
imshow("disp", disparity);
imshow("depth", depth);
int key = waitKey(10);
if (key == 'q') {
break;
}
else if (key == 's') {
stringstream output;
for (int x = 0; x < img1.rows; x++) {
for (int y = 0; y < img1.cols; y++) {
Point3f p = depth.at<Point3f>(x, y);
if(p.z >= 10000) continue; // Filter errors
output << p.x << "," << p.y << "," << p.z << endl;
}
}
ofstream outputFile("points");
outputFile << output.str();
outputFile.close();
cout << "saved" << endl;
}
else if (key == 'p') {
waitKey(0);
}
}
destroyAllWindows();
return 0;
}