Undistort失真参数
Undistort distortion parameters
我正在尝试使用 OpenCV(通过 OpenCVSharp 的包装器)对图像进行去畸变,但我无法确定矩阵的正确格式,我正在通过去畸变样本中使用的 CvFileStorage 导入它们我得到了非常意想不到的结果。
从我使用的另一个软件我得到了以下数据(这应该是正确的,因为该软件使用这些参数可以很好地消除图像失真)
<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>
我正在使用以下代码来消除图像失真,内在矩阵很好(在不应用失真时给出预期结果)但是失真矩阵给我带来了问题,据我对预期布局的理解(没有找到任何样本,但这就是我从 OpenCV 源收集的)一个带有 k1k2p1p2 的 4X1 矩阵应该可以工作,所以我在我的配置文件中有这个:
<?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>
代码:
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);
}
但是我得到的图像完全扭曲 (Whirlpool),我的矩阵顺序错了吗?是否有任何代码示例(我找不到任何代码示例),其中包含一个由命名参数构造的矩阵(我发现的只是一个示例,其中使用了一个包含矩阵的示例文件,但没有关于组件订单的文档)?
由于您得到的校准是针对五个参数的k1, k2, k3, p1, p2
,因此您应该将所有参数都用于不失真。
目前您正在跳过 k3
.
尝试将 k3
的值添加到配置文件中,使 distortion
参数的维度为 1x5
。
注意顺序应该是k1, k2, p1, p2, k3
.
不确定 skew
参数,但这段代码给我的结果与您提供的图像完全不同(但它也不等于您的 "correct" 校正后的图像)
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;
}
我正在尝试使用 OpenCV(通过 OpenCVSharp 的包装器)对图像进行去畸变,但我无法确定矩阵的正确格式,我正在通过去畸变样本中使用的 CvFileStorage 导入它们我得到了非常意想不到的结果。
从我使用的另一个软件我得到了以下数据(这应该是正确的,因为该软件使用这些参数可以很好地消除图像失真)
<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>
我正在使用以下代码来消除图像失真,内在矩阵很好(在不应用失真时给出预期结果)但是失真矩阵给我带来了问题,据我对预期布局的理解(没有找到任何样本,但这就是我从 OpenCV 源收集的)一个带有 k1k2p1p2 的 4X1 矩阵应该可以工作,所以我在我的配置文件中有这个:
<?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>
代码:
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);
}
但是我得到的图像完全扭曲 (Whirlpool),我的矩阵顺序错了吗?是否有任何代码示例(我找不到任何代码示例),其中包含一个由命名参数构造的矩阵(我发现的只是一个示例,其中使用了一个包含矩阵的示例文件,但没有关于组件订单的文档)?
由于您得到的校准是针对五个参数的k1, k2, k3, p1, p2
,因此您应该将所有参数都用于不失真。
目前您正在跳过 k3
.
尝试将 k3
的值添加到配置文件中,使 distortion
参数的维度为 1x5
。
注意顺序应该是k1, k2, p1, p2, k3
.
不确定 skew
参数,但这段代码给我的结果与您提供的图像完全不同(但它也不等于您的 "correct" 校正后的图像)
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;
}