2

I'm trying to undistort an image with OpenCV (through OpenCVSharp's wrapper) and i'm having trouble figuring out the correct format for the matrices, i'm improting them through the CvFileStorage as used in the undistort sample however i'm getting really unexpected results.

From another software i use i get the following data (which should be right as that software undistorts the iamge just fine with those parameters)

    <sensor id="0" label="RP_OV5647 (3.5976 mm)" type="frame">
      <resolution width="2592" height="1944"/>
      <property name="focal_length" value="3.5975999999999999e+000"/>
      <property name="fixed" value="false"/>
      <calibration type="frame" class="adjusted">
        <resolution width="2592" height="1944"/>
        <fx>2.5667779156627239e+003</fx>
        <fy>2.5654169232963172e+003</fy>
        <cx>1.2933905910821311e+003</cx>
        <cy>9.6694162774618212e+002</cy>
        <skew>2.9824815660771562e+000</skew>
        <k1>9.1041365324307497e-002</k1>
        <k2>-4.0485507081497402e-001</k2>
        <k3>3.3943759073230600e-001</k3>
        <p1>3.4409596859645629e-004</p1>
        <p2>-3.9472652058529605e-005</p2>
      </calibration>
    </sensor>

i'm using the following code to undistort the images, the intrinsic matrix is fine (gives the expected result when applying no distortion) however the distortion matrix is giving me issues, from what i understand of the expected layout (didn't find any samples but that's what i gather from the OpenCV source) a 4X1 matrix with k1k2p1p2 should work so i have this in my configuration file:

<?xml version="1.0"?>
<opencv_storage>
   <intrinsic type_id="opencv-matrix">
   <rows>3</rows>
   <cols>3</cols>
   <dt>f</dt>
   <data>
      1293.3905910821311 0. 966.94162774618212 0. 2566.7779156627239 2565.4169232963172 0. 0. 1.
   </data>
 </intrinsic>
 <distortion type_id="opencv-matrix">
   <rows>1</rows>
   <cols>5</cols>
   <dt>f</dt>
   <data>
  0.091041365324307497 -0.40485507081497402 0.00034409596859645629 -0.000039472652058529605 0.33943759073230600
   </data>
 </distortion>

Code :

            using (IplImage srcImg = new IplImage(img.Path, LoadMode.Color))
            using (IplImage dstImg = srcImg.Clone())
            {
                CvMat intrinsic, distortion;
                using (CvFileStorage fs = new CvFileStorage("camera.xml", null, FileStorageMode.Read))
                {
                    CvFileNode param = fs.GetFileNodeByName(null, "intrinsic");
                    intrinsic = fs.Read<CvMat>(param);
                    param = fs.GetFileNodeByName(null, "distortion");
                    distortion = fs.Read<CvMat>(param);
                }
                Cv.Undistort2(srcImg, dstImg, intrinsic, distortion);
                dstImg.SaveImage(new System.IO.FileInfo(img.Path).Name);
            }

However i'm getting completly distorted images (Whirlpool) , do i have the matrix order wrong? is there any code sample (i couldn't find any) with a matrix constructed from named parameters (all i found was a sample using a sample file with a matrix in it and no documentation on the component orders)?

4

2 回答 2

3

不确定skew参数,但是此代码给我的结果与您提供的图像完全不同(但它也不等于您的“正确”校正图像)

int main()
{
    // camera resolution
    cv::Mat input= cv::imread("../inputData/distorted1.jpg");


    cv::Mat distCoeff;
    distCoeff = cv::Mat::zeros(8,1,CV_64FC1);

    // indices: k1, k2, p1, p2, k3, k4, k5, k6 
    // your coefficients here!
    double k1 = 9.1041365324307497e-002;
    double k2 = -4.0485507081497402e-001;
    double p1 = 3.4409596859645629e-004;
    double p2 = -3.9472652058529605e-005;
    double k3 = 3.3943759073230600e-001;
    double k4 = 0;
    double k5 = 0;
    double k6 = 0;

    distCoeff.at<double>(0,0) = k1;
    distCoeff.at<double>(1,0) = k2;
    distCoeff.at<double>(2,0) = p1;
    distCoeff.at<double>(3,0) = p2;
    distCoeff.at<double>(4,0) = k3;
    distCoeff.at<double>(5,0) = k4;
    distCoeff.at<double>(6,0) = k5;
    distCoeff.at<double>(7,0) = k6;


    // camera intrinsics
    cv::Mat cam1;
    cam1 = cv::Mat::eye(3,3,CV_32FC1);
    cam1.at<float>(0,0) = 2.5667779156627239e+003;
    //cam1.at<float>(0,1) = 0;
    cam1.at<float>(0,1) = 2.9824815660771562e+000; // skew?
    cam1.at<float>(0,2) = 1.2933905910821311e+003;

    cam1.at<float>(1,0) = 0;
    cam1.at<float>(1,1) = 2.5654169232963172e+003;
    cam1.at<float>(1,2) = 9.6694162774618212e+002;

    // direct undistort:
    cv::Mat output;
    cv::undistort(input, output, cam1,distCoeff);


    cv::imshow("input", input);
    cv::imshow("distCorr-direct", output);

    cv::waitKey(-1);

    return 0;
}
于 2015-09-28T13:18:56.637 回答
2

由于您获得的校准是针对五个参数的k1, k2, k3, p1, p2,因此您应该将所有这些参数用于不失真。目前您正在跳过k3.

尝试将 的值添加k3到您的配置文件中以使distortion参数具有尺寸1x5。注意顺序应该是k1, k2, p1, p2, k3

于 2015-09-28T11:53:04.690 回答