// This file is part of OpenCV project. // It is subject to the license terms in the LICENSE file found in the top-level directory // of this distribution and at http://opencv.org/license.html #include "precomp.hpp" #include "opencv2/core/affine.hpp" namespace cv { namespace fisheye { void initUndistortRectifyMap( InputArray K, InputArray D, InputArray R, InputArray P, const cv::Size& size, int m1type, OutputArray map1, OutputArray map2 ) { CV_INSTRUMENT_REGION(); CV_Assert( m1type == CV_16SC2 || m1type == CV_32F || m1type <=0 ); map1.create( size, m1type <= 0 ? CV_16SC2 : m1type ); map2.create( size, map1.type() == CV_16SC2 ? CV_16UC1 : CV_32F ); CV_Assert((K.depth() == CV_32F || K.depth() == CV_64F) && (D.depth() == CV_32F || D.depth() == CV_64F)); CV_Assert((P.empty() || P.depth() == CV_32F || P.depth() == CV_64F) && (R.empty() || R.depth() == CV_32F || R.depth() == CV_64F)); CV_Assert(K.size() == Size(3, 3) && (D.empty() || D.total() == 4)); CV_Assert(R.empty() || R.size() == Size(3, 3) || R.total() * R.channels() == 3); CV_Assert(P.empty() || P.size() == Size(3, 3) || P.size() == Size(4, 3)); Vec2d f, c; if (K.depth() == CV_32F) { Matx33f camMat = K.getMat(); f = Vec2f(camMat(0, 0), camMat(1, 1)); c = Vec2f(camMat(0, 2), camMat(1, 2)); } else { Matx33d camMat = K.getMat(); f = Vec2d(camMat(0, 0), camMat(1, 1)); c = Vec2d(camMat(0, 2), camMat(1, 2)); } Vec4d k = Vec4d::all(0); if (!D.empty()) k = D.depth() == CV_32F ? (Vec4d)*D.getMat().ptr(): *D.getMat().ptr(); Matx33d RR = Matx33d::eye(); if (!R.empty() && R.total() * R.channels() == 3) { Vec3d rvec; R.getMat().convertTo(rvec, CV_64F); RR = Affine3d(rvec).rotation(); } else if (!R.empty() && R.size() == Size(3, 3)) R.getMat().convertTo(RR, CV_64F); Matx33d PP = Matx33d::eye(); if (!P.empty()) P.getMat().colRange(0, 3).convertTo(PP, CV_64F); Matx33d iR = (PP * RR).inv(cv::DECOMP_SVD); for( int i = 0; i < size.height; ++i) { float* m1f = map1.getMat().ptr(i); float* m2f = map2.getMat().ptr(i); short* m1 = (short*)m1f; ushort* m2 = (ushort*)m2f; double _x = i*iR(0, 1) + iR(0, 2), _y = i*iR(1, 1) + iR(1, 2), _w = i*iR(2, 1) + iR(2, 2); for( int j = 0; j < size.width; ++j) { double u, v; if( _w <= 0) { u = (_x > 0) ? -std::numeric_limits::infinity() : std::numeric_limits::infinity(); v = (_y > 0) ? -std::numeric_limits::infinity() : std::numeric_limits::infinity(); } else { double x = _x/_w, y = _y/_w; double r = sqrt(x*x + y*y); double theta = std::atan(r); double theta2 = theta*theta, theta4 = theta2*theta2, theta6 = theta4*theta2, theta8 = theta4*theta4; double theta_d = theta * (1 + k[0]*theta2 + k[1]*theta4 + k[2]*theta6 + k[3]*theta8); double scale = (r == 0) ? 1.0 : theta_d / r; u = f[0]*x*scale + c[0]; v = f[1]*y*scale + c[1]; } if( m1type == CV_16SC2 ) { int iu = cv::saturate_cast(u*static_cast(cv::INTER_TAB_SIZE)); int iv = cv::saturate_cast(v*static_cast(cv::INTER_TAB_SIZE)); m1[j*2+0] = (short)(iu >> cv::INTER_BITS); m1[j*2+1] = (short)(iv >> cv::INTER_BITS); m2[j] = (ushort)((iv & (cv::INTER_TAB_SIZE-1))*cv::INTER_TAB_SIZE + (iu & (cv::INTER_TAB_SIZE-1))); } else if( m1type == CV_32FC1 ) { m1f[j] = (float)u; m2f[j] = (float)v; } _x += iR(0, 0); _y += iR(1, 0); _w += iR(2, 0); } } } void undistortImage(InputArray distorted, OutputArray undistorted, InputArray K, InputArray D, InputArray Knew, const Size& new_size) { CV_INSTRUMENT_REGION(); Size size = !new_size.empty() ? new_size : distorted.size(); Mat map1, map2; fisheye::initUndistortRectifyMap(K, D, Matx33d::eye(), Knew, size, CV_16SC2, map1, map2 ); cv::remap(distorted, undistorted, map1, map2, INTER_LINEAR, BORDER_CONSTANT); } } // namespace fisheye } // namespace cv