手动创建矩阵进行OpenCV立体校正

6

我目前正在进行X射线图像的3D重建,因此需要对两个视角的图像进行立体矫正,以便在epilines的帮助下匹配一些特征。我正在使用C++中的OpenCV 2.4。

为此,我得到了一组X射线图像对(锥束X射线图像,没有具有畸变参数或实际焦距的真正相机),一个来自前后位视图(直接查看胸部),另一个来自侧面视图(从侧面查看胸部)。我知道一些参数,例如虚拟焦距(对两个视图相等),可以使用它,而且图像的分辨率为512x512px,因此相机在图像上的投影为(255,255)对于两个视图来说都是一样的。我还知道相机是垂直的。根据这些信息,我开发了一个旋转矩阵R和一个平移向量t(均在Matlab中通过3D绘图验证)。

问题:在OpenCV中,R和t实际上足以进行立体矫正,但是矫正后的图像是黑色的。通过谷歌搜索,我发现了stereoRectify中的一个错误,但我怀疑这不是错误,因为我可以运行OpenCV stereoRectification示例,它确实有效。当我尝试在Matlab中进行立体矫正时,我至少可以看到一些扭曲的矫正结果。
以下是我的C++代码:
float camera_matrix_ap_data[] = {1207*2.0, 0.0, 255.0,
                 0.0, 1207*2, 255.0,
                                 0.0, 0.0, 1.0};
cv::Mat camera_matrix_ap(3, 3, CV_64F, camera_matrix_ap_data);
float camera_matrix_lat_data[] = {1207*2, 0.0, 255.0,
                 0.0, 1207*2, 255.0,
                                 0.0, 0.0, 1.0};
 cv::Mat camera_matrix_lat(3, 3, CV_64F, camera_matrix_lat_data);

 ///
 /// @brief the distortion matrices
 ///
 cv::Mat distortion_ap(4, 1, CV_64F, 0.0);
 cv::Mat distortion_lat(4, 1, CV_64F, 0.0);

 ///
 /// @brief Translation and Rotation matrices
 ///
 float R_data[] = {0.0, 0.0, 1.0,
           0.0, 1.0, 0.0,
           -1.0, 0.0, 0.0};
 float T_data[] = {-(1207.0*2 + 255), 0.0, 1207.0*2 + 255};

 cv::Mat R(3, 3, CV_64F, R_data);
 cv::Mat T(3, 1, CV_64F, T_data);

 for (int i=1; i<=20; i++) {
std::stringstream filenameAP_tmp;
std::stringstream filenameLAT_tmp;
filenameAP_tmp << "imageAP"<< i <<".jpg";
filenameAP = filenameAP_tmp.str();
filenameLAT_tmp << "imageLAT"<< i <<".jpg";
filenameLAT = filenameLAT_tmp.str();

    rectimg_ap = cv::imread(filenameAP);
    rectimg_lat = cv::imread(filenameLAT);
    // Yes, these images are grayscale

    /// Experimental
    /// Stereo rectify both images
 cv::Mat R1(3, 3, CV_64F);
 cv::Mat R2(3, 3, CV_64F);
 cv::Mat P1(3, 4, CV_64F);
 cv::Mat P2(3, 4, CV_64F);
 cv::Mat Q(4, 4, CV_64F);
 cv::Rect validRoi[2];

// buggy?
cv::stereoRectify(camera_matrix_ap, distortion_ap, camera_matrix_lat, distortion_lat, rectimg_ap.size(), R, T, R1, R2, P1, P2, Q, CALIB_ZERO_DISPARITY, 1, rectimg_ap.size(), &validRoi[0], &validRoi[1] );


// Maps for AP View
cv::Mat map1x(rectimg_ap.size(), CV_32FC1, 255.0);
cv::Mat map2x(rectimg_ap.size(), CV_32FC1, 255.0);
// Maps for LAT View
cv::Mat map1y(rectimg_ap.size(), CV_32FC1, 255.0);
cv::Mat map2y(rectimg_ap.size(), CV_32FC1, 255.0);

cv::initUndistortRectifyMap(camera_matrix_ap, distortion_ap, R1, P1, rectimg_ap.size(), CV_32FC1, map1x, map1y);
cv::initUndistortRectifyMap(camera_matrix_lat, distortion_lat, R2, P2, rectimg_lat.size(), CV_32FC1, map2x, map2y);

cv::Mat tmp1, tmp2;
cv::remap(rectimg_ap, tmp1, map1x, map1y, INTER_LINEAR);
cv::remap(rectimg_lat, tmp2, map2x, map2y, INTER_LINEAR);

//findHomography(rectimg_ap, rectimg_lat, CV_RANSAC);

}

我在想这段代码或者我的矩阵有什么问题,因为重新映射后的校正图像完全是黑色的。OpenCV和Matlab之间的坐标系轴是否有区别?据我所知,在OpenCV中,z轴指向图像平面,而Matlab也是如此。

如果有人能帮助我,我会非常感激,我已经被这个问题困扰了几周。非常感谢!


你尝试过不同的 alpha 参数值吗?在你发布的代码中,alpha 是1。你尝试过0吗?根据OpenCV文档中的 stereoRectify:*alpha=0 表示矫正后的图像被缩放和移位,以便只有有效像素可见(矫正后没有黑色区域)*。 - Alessandro Jacopson
1个回答

1
尝试将“float”变量类型更改为“double”。CV_64F对应于双精度浮点数,而不是浮点数,因为它是8字节(= 64位)。我使用自己的矩阵值尝试了您的代码,并且这样做就可以了。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接