我从摄像机获取图像,无法拍摄棋盘图像并使用OpenCV计算校正矩阵。到目前为止,我使用imagemagick转换使用选项'-distort Barrel“0.0 0.0 -0.035 1.1”'来校正图像,其中我得到了试验和错误的参数。手动校正OpenCV桶形失真,没有棋盘图像
现在我想在OpenCV中做到这一点,但我在网上找到的是使用棋盘图像的自动更正。有没有机会像我用imagemagick一样应用一些简单的手动试错镜头畸变校正?
我从摄像机获取图像,无法拍摄棋盘图像并使用OpenCV计算校正矩阵。到目前为止,我使用imagemagick转换使用选项'-distort Barrel“0.0 0.0 -0.035 1.1”'来校正图像,其中我得到了试验和错误的参数。手动校正OpenCV桶形失真,没有棋盘图像
现在我想在OpenCV中做到这一点,但我在网上找到的是使用棋盘图像的自动更正。有没有机会像我用imagemagick一样应用一些简单的手动试错镜头畸变校正?
如果你没有棋盘图案但是你知道失真系数,这里有一个方法可以使图像不失真。
因为我不知道哪个系数的桶形畸变参数对应(也许在http://docs.opencv.org/doc/tutorials/calib3d/camera_calibration/camera_calibration.html看看和http://docs.opencv.org/modules/imgproc/doc/geometric_transformations.html#initundistortrectifymap你将不得不尝试一下,也许有人能够帮助你在这里。
还有一点就是我不能确定的OpenCV是否会同时处理,浮动和自动加倍如果不是这种情况有可能是在这个代码中的错误(我不知道单或双精度是否假设):
cv::Mat distCoeff;
distCoeff = cv::Mat::zeros(8,1,CV_64FC1);
// indices: k1, k2, p1, p2, k3, k4, k5, k6
// TODO: add your coefficients here!
double k1 = 0;
double k2 = 0;
double p1 = 0;
double p2 = 0;
double k3 = 0;
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;
// assume unit matrix for camera, so no movement
cv::Mat cam1,cam2;
cam1 = cv::Mat::eye(3,3,CV_32FC1);
cam2 = cv::Mat::eye(3,3,CV_32FC1);
//cam2.at<float>(0,2) = 100; // for testing a translation
// here the undistortion will be computed
cv::Mat map1, map2;
cv::initUndistortRectifyMap(cam1, distCoeff, cv::Mat(), cam2, input.size(), CV_32FC1, map1, map2);
cv::Mat distCorrected;
cv::remap(input, distCorrected, map1, map2, cv::INTER_LINEAR);
k4,k5和k6从哪里来?它不是文档的一部分,是吗?是否还有一个Python代码片段? – 2014-10-28 15:09:44
如果我按照你的链接,我看到类似这样的东西:xcor = x *(1 + k1 * r^2 + k2 * r^4 + k3 * r^6);这与以下公式适用的imagemagick(http://www.imagemagick.org/Usage/distorts/#barrel)中的描述不同:Rsrc = r *(A * r^3 + B * r^2 + C * r + D);因此将例如k1设置为0.001会导致非常奇怪的图像,但不会校正桶形失真?尽管如此,我认为我们更接近解决方案。 – 2014-10-28 15:31:11
抱歉,我这边没有python代码片段,但它只是关于initUndistortRectifyMap调用和设置系数。维基百科给出了一些与OpenCV类似的系数(虽然没有检查这些术语)http://en.wikipedia.org/wiki/Distortion_%28optics%29#Software_correction因此,也许imageMagick使用不同的失真模型,或者他们会假设某种反向参数?!?不知道,抱歉=) – Micka 2014-10-28 15:52:29
好,我想我知道了,在矩阵cam1,cam2中,图像中心缺失了(参见doc umentation)。我添加了它并改变了焦距以避免图像尺寸变化太大。这里是代码:
import numpy as np
import cv2
src = cv2.imread("distortedImage.jpg")
width = src.shape[1]
height = src.shape[0]
distCoeff = np.zeros((4,1),np.float64)
# TODO: add your coefficients here!
k1 = -1.0e-5; # negative to remove barrel distortion
k2 = 0.0;
p1 = 0.0;
p2 = 0.0;
distCoeff[0,0] = k1;
distCoeff[1,0] = k2;
distCoeff[2,0] = p1;
distCoeff[3,0] = p2;
# assume unit matrix for camera
cam = np.eye(3,dtype=np.float32)
cam[0,2] = width/2.0 # define center x
cam[1,2] = height/2.0 # define center y
cam[0,0] = 10. # define focal length x
cam[1,1] = 10. # define focal length y
# here the undistortion will be computed
dst = cv2.undistort(src,cam,distCoeff)
cv2.imshow('dst',dst)
cv2.waitKey(0)
cv2.destroyAllWindows()
非常感谢您的支持。
很高兴听到。如果你已经测试过它并且工作,afaik你可以接受你自己的答案来帮助其他人寻找相同问题的解决方案 – Micka 2014-10-28 21:14:04
这是一个互补的功能undistort,可能会更快,更好的方式来做到这一点,但它的工作原理:利用棋盘他们应该随时随地计算失真参数
void distort(const cv::Mat& src, cv::Mat& dst, const cv::Mat& cameraMatrix, const cv::Mat& distCoeffs)
{
cv::Mat distort_x = cv::Mat(src.size(), CV_32F);
cv::Mat distort_y = cv::Mat(src.size(), CV_32F);
cv::Mat pixel_locations_src = cv::Mat(src.size(), CV_32FC2);
for (int i = 0; i < src.size().height; i++) {
for (int j = 0; j < src.size().width; j++) {
pixel_locations_src.at<cv::Point2f>(i,j) = cv::Point2f(j,i);
}
}
cv::Mat fractional_locations_dst = cv::Mat(src.size(), CV_32FC2);
cv::undistortPoints(pixel_locations_src, pixel_locations_dst, cameraMatrix, distCoeffs);
cv::Mat pixel_locations_dst = cv::Mat(src.size(), CV_32FC2);
const float fx = cameraMatrix.at<double>(0,0);
const float fy = cameraMatrix.at<double>(1,1);
const float cx = cameraMatrix.at<double>(0,2);
const float cy = cameraMatrix.at<double>(1,2);
// is there a faster way to do this?
for (int i = 0; i < fractional_locations_dst.size().height; i++) {
for (int j = 0; j < fractional_locations_dst.size().width; j++) {
const float x = fractional_locations_dst.at<cv::Point2f>(i,j).x*fx + cx;
const float y = fractional_locations_dst.at<cv::Point2f>(i,j).y*fy + cy;
pixel_locations_dst.at<cv::Point2f>(i,j) = cv::Point2f(x,y);
}
}
cv::remap(src, dst, pixel_locations_dst, cv::Mat(), CV_INTER_LINEAR);
}
在例子。只需跳过计算并明确提供这些参数。如果封装了这部分,您可以查看oprnCV源代码并使用内部使用的函数 – Micka 2014-10-28 07:47:26
我试图自己定义棋盘角(例如4x4点),但没有得到角阵列的结构应该是什么。有没有人有任何想法? – 2014-10-28 08:00:27
好吧,我认为最小的数组应该像这样配置:corners = np.zeros((4 * 4,1,2),dtype =“float32”)。用3x3它似乎不工作。不过,我宁愿像convert -distort Barrel这样的东西,而不是现在定义扭曲的点。 – 2014-10-28 08:22:41