Hey guys,
i've started to implement zhangs algorithm for a camera-calibration(2D-Rig). Now i've got a fundamental issue at the beginning. I think i'm getting a wrong homography.This can be seen by looking at the image. The red dots are the detected corners by findChessboardCorners() and the blue circles are a transformation (homography) by the 3D-Points to the image-points.
I dont know what the problem could be, because the Design-matrix(the matrix to solve homogeneous equation system with svd and so get the homography vec) seems to be right (but i also attach a screenshot of the matrix). The width and height of a square a 20mm. Image size 3200x2400.!3200x2400.! Design Matrix:
Could anybody pls tell me what the issue may be? I dont have any clue, but i think the computations of the svd should be correct because ive checked it with other online-svd-calulators.
Thanks
cv::Mat calib_img_copy = calibImg->clone();
cv::Mat homogenous_image(3, m_detectedCorners.rows,CV_32FC1);
cv::Mat homogenous_world(3, m_detectedCorners.rows, CV_32FC1);
char counter = 0; char image_row = 1; char image_col = 1;
//Writes matrices (2D and 3D-Coordinates without z) in desired form
for (int i = 0; i < m_detectedCorners.rows; i++)
{
cv::Point2f k(m_detectedCorners.at<float>(i,0), m_detectedCorners.at<float>(i, 1));
cv::circle(calib_img_copy, k, 2, cvScalar(0, 0, 255), 2, 1);
//put the detected corners in homogeneous form into vector
homogenous_image.at<float>(0, i) = k.x;
homogenous_image.at<float>(1, i) = k.y;
homogenous_image.at<float>(2, i) = 1.0f;
homogenous_world.at<float>(0, i) = 20*image_col;
homogenous_world.at<float>(1, i) = 20*image_row;
homogenous_world.at<float>(2, i) = 1.0f;
image_col++;
if (counter == 14)
{
image_row++;
image_col = 1;
counter = 0;
}
counter++;
}
m_homogenous_image = homogenous_image;
m_homogenous_world = homogenous_world;
//Gets design Matrix, with it the homogeneous equation system can be solved
cv::Mat A_01 = getDesignMatrix_camera(m_homogenous_image, m_homogenous_world);
cv::Mat H_01 = solve_dlt(A_01); //desired homography
cv::Mat converted = H*m_homogenous_world; //calculate the "projected 3D Points"
//draw homogeneous coordinates / convert them to inhomogen
for (int i = 0; i < m_homogenous_world.cols; i++)
{
float kl = converted.at<float>(2, i);
cv::Point2d h(converted.at<float>(0, i) / kl, converted.at<float>(1, i) / kl);
cv::circle(calib_img_copy, h, 5, cvScalar(255, 0, 0), 3);
}
cv::namedWindow("Detected Points", CV_WINDOW_KEEPRATIO);
cv::imshow("Detected Points", calib_img_copy);
cv::waitKey();
cv::Mat cComputerVision::getDesignMatrix_camera(cv::Mat& points2D, cv::Mat& points3D) {
//should write the matrix as shown in the upper picture
cv::Mat base = points2D;
cv::Mat attach = points3D;
cv::Mat design = cv::Mat::zeros(base.cols * 2, 9, CV_32FC1);
int indx;
for (int i = 0; i < base.cols; ++i)
{
indx = i * 2;
for (int j = 0; j < 3; ++j)
{
design.at<float>(indx + 1, j + 3) = design.at<float>(indx, j) = -base.at<float>(2, i) * attach.at<float>(j, i);
design.at<float>(indx, 6 + j) = base.at<float>(0, i) * attach.at<float>(j, i);
design.at<float>(indx + 1, 6 + j) = base.at<float>(1, i) * attach.at<float>(j, i);
}
}
return design;
}
cv::Mat cComputerVision::solve_dlt(cv::Mat& A) {
cv::SVD svd(A, cv::SVD::FULL_UV);
cv::Mat H;
cv::SVD::solveZ(A, H);
return H.reshape(1,3);
}
And that codes ends in the upper (unfortunately not shown) picture: following picture (without normalization of coordinates - the above picture is with normalization of coordinates):
Horst(/upfiles/15541077502037527.jpg)(/upfiles/15541077394872235.jpg)