diff --git a/modules/imgproc/doc/pics/polar_remap_doc.png b/modules/imgproc/doc/pics/polar_remap_doc.png new file mode 100644 index 0000000000..e3e4105bb8 Binary files /dev/null and b/modules/imgproc/doc/pics/polar_remap_doc.png differ diff --git a/modules/imgproc/doc/pics/polar_remap_doc.svg b/modules/imgproc/doc/pics/polar_remap_doc.svg new file mode 100644 index 0000000000..544221569d --- /dev/null +++ b/modules/imgproc/doc/pics/polar_remap_doc.svg @@ -0,0 +1,3776 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + maxRadius + angle° + magnitude + + + + + + dx + dy + centerC(xc , yc) + A(xA , yA) + + BOUNDING CIRCLE + + + + + + a) Source Image + + ρ: 0 .. Kx * maxRadius = src.cols + centerC(0,0) + + + centerC(0,0) + + ρA = Kx * magnitude + + ϕA = Ky * angle° + + A(ρA , ϕA) + if 2 * maxRadius > min(srcSize)CV_WARP_FILL_OUTLIERS + + + M = src.cols / loge(maxRadius)Ky = src.rows / 360.0 + + Blue cross in the center + + + if 2 * maxRadius > min(srcSize)CV_WARP_FILL_OUTLIERS + Blue cross in the center + + + + c) linearPolar Result Image + + d) logPolar Result Image + + + + + + ϕA = Ky * angle° + + A(ρA , ϕA) + + + Kx = src.cols / maxRadiusKy = src.rows / 360.0 + + ρ: 0 .. M * loge(maxRadius) = src.cols + + ϕ: 0 .. Ky * 360 = src.rows + + ρA = M * loge(magnitude ) + + + + + + + + + + + + + + + + + + 270 + 240 + 210 + 180 + 150 + 120 + 90 + 60 + 30 + 300 + 330 + 0 + + + + + + + + + + + Size: W:600 H:440 pxCenter = x:240, y:220magnitude=100pxangle = 60degmaxRadius= 230px + Kx = 600px / 230px = 2.609 => rho = 260.869pxKy = 440px / 360deg = 1.222 pix/deg = phi = 73.333pxM = 600px / ln(230px) = 110.33 pn/ln(px) => rho = 508.103px + + + b) Params References + + + + + image/svg+xml + + + + + OpenCV + + + + 2016-08-08 + + + + + PkLab.net + + + + + linearPolar + logPolar + image processing + OpenCV + + + + + + + + + + + diff --git a/modules/imgproc/include/opencv2/imgproc.hpp b/modules/imgproc/include/opencv2/imgproc.hpp index ee022476f0..b8d95e3fc1 100644 --- a/modules/imgproc/include/opencv2/imgproc.hpp +++ b/modules/imgproc/include/opencv2/imgproc.hpp @@ -284,9 +284,9 @@ enum InterpolationFlags{ WARP_FILL_OUTLIERS = 8, /** flag, inverse transformation - For example, polar transforms: - - flag is __not__ set: \f$dst( \phi , \rho ) = src(x,y)\f$ - - flag is set: \f$dst(x,y) = src( \phi , \rho )\f$ + For example, @ref cv::linearPolar or @ref cv::logPolar transforms: + - flag is __not__ set: \f$dst( \rho , \phi ) = src(x,y)\f$ + - flag is set: \f$dst(x,y) = src( \rho , \phi )\f$ */ WARP_INVERSE_MAP = 16 }; @@ -2418,41 +2418,78 @@ CV_EXPORTS_W void getRectSubPix( InputArray image, Size patchSize, An example using the cv::linearPolar and cv::logPolar operations */ -/** @brief Remaps an image to log-polar space. +/** @brief Remaps an image to semilog-polar coordinates space. + +Transform the source image using the following transformation (See @ref polar_remaps_reference_image "Polar remaps reference image"): +\f[\begin{array}{l} + dst( \rho , \phi ) = src(x,y) \\ + dst.size() \leftarrow src.size() +\end{array}\f] -transforms the source image using the following transformation: -\f[dst( \phi , \rho ) = src(x,y)\f] where -\f[\rho = M \cdot \log{\sqrt{x^2 + y^2}} , \phi =atan(y/x)\f] +\f[\begin{array}{l} + I = (dx,dy) = (x - center.x,y - center.y) \\ + \rho = M \cdot log_e(\texttt{magnitude} (I)) ,\\ + \phi = Ky \cdot \texttt{angle} (I)_{0..360 deg} \\ +\end{array}\f] + +and +\f[\begin{array}{l} + M = src.cols / log_e(maxRadius) \\ + Ky = src.rows / 360 \\ +\end{array}\f] The function emulates the human "foveal" vision and can be used for fast scale and -rotation-invariant template matching, for object tracking and so forth. The function can not operate -in-place. - +rotation-invariant template matching, for object tracking and so forth. @param src Source image -@param dst Destination image +@param dst Destination image. It will have same size and type as src. @param center The transformation center; where the output precision is maximal -@param M Magnitude scale parameter. +@param M Magnitude scale parameter. It determines the radius of the bounding circle to transform too. @param flags A combination of interpolation methods, see cv::InterpolationFlags - */ + +@note +- The function can not operate in-place. +- To calculate magnitude and angle in degrees @ref cv::cartToPolar is used internally thus angles are measured from 0 to 360 with accuracy about 0.3 degrees. +*/ CV_EXPORTS_W void logPolar( InputArray src, OutputArray dst, Point2f center, double M, int flags ); -/** @brief Remaps an image to polar space. +/** @brief Remaps an image to polar coordinates space. + +@anchor polar_remaps_reference_image +![Polar remaps reference](pics/polar_remap_doc.png) + +Transform the source image using the following transformation: +\f[\begin{array}{l} + dst( \rho , \phi ) = src(x,y) \\ + dst.size() \leftarrow src.size() +\end{array}\f] -transforms the source image using the following transformation: -\f[dst( \phi , \rho ) = src(x,y)\f] where -\f[\rho = (src.width/maxRadius) \cdot \sqrt{x^2 + y^2} , \phi =atan(y/x)\f] +\f[\begin{array}{l} + I = (dx,dy) = (x - center.x,y - center.y) \\ + \rho = Kx \cdot \texttt{magnitude} (I) ,\\ + \phi = Ky \cdot \texttt{angle} (I)_{0..360 deg} +\end{array}\f] + +and +\f[\begin{array}{l} + Kx = src.cols / maxRadius \\ + Ky = src.rows / 360 +\end{array}\f] -The function can not operate in-place. @param src Source image -@param dst Destination image +@param dst Destination image. It will have same size and type as src. @param center The transformation center; -@param maxRadius Inverse magnitude scale parameter +@param maxRadius The radius of the bounding circle to transform. It determines the inverse magnitude scale parameter too. @param flags A combination of interpolation methods, see cv::InterpolationFlags - */ + +@note +- The function can not operate in-place. +- To calculate magnitude and angle in degrees @ref cv::cartToPolar is used internally thus angles are measured from 0 to 360 with accuracy about 0.3 degrees. + +*/ CV_EXPORTS_W void linearPolar( InputArray src, OutputArray dst, Point2f center, double maxRadius, int flags ); diff --git a/samples/cpp/polar_transforms.cpp b/samples/cpp/polar_transforms.cpp index 3cbc431c3c..adbc955b17 100644 --- a/samples/cpp/polar_transforms.cpp +++ b/samples/cpp/polar_transforms.cpp @@ -34,10 +34,10 @@ int main( int argc, char** argv ) return -1; } - namedWindow( "Linear-Polar", WINDOW_NORMAL ); - namedWindow( "Log-Polar", WINDOW_NORMAL ); - namedWindow( "Recovered Linear-Polar", WINDOW_NORMAL ); - namedWindow( "Recovered Log-Polar", WINDOW_NORMAL ); + namedWindow( "Linear-Polar", WINDOW_AUTOSIZE ); + namedWindow( "Log-Polar", WINDOW_AUTOSIZE); + namedWindow( "Recovered Linear-Polar", WINDOW_AUTOSIZE); + namedWindow( "Recovered Log-Polar", WINDOW_AUTOSIZE); moveWindow( "Linear-Polar", 20,20 ); moveWindow( "Log-Polar", 700,20 ); @@ -53,13 +53,14 @@ int main( int argc, char** argv ) break; Point2f center( (float)frame.cols / 2, (float)frame.rows / 2 ); - double M = (double)frame.cols / 8; + double radius = (double)frame.cols / 4; + double M = (double)frame.cols / log(radius); logPolar(frame,log_polar_img, center, M, INTER_LINEAR + WARP_FILL_OUTLIERS); - linearPolar(frame,lin_polar_img, center, M, INTER_LINEAR + WARP_FILL_OUTLIERS); + linearPolar(frame,lin_polar_img, center, radius, INTER_LINEAR + WARP_FILL_OUTLIERS); logPolar(log_polar_img, recovered_log_polar, center, M, WARP_INVERSE_MAP + INTER_LINEAR); - linearPolar(lin_polar_img, recovered_lin_polar_img, center, M, WARP_INVERSE_MAP + INTER_LINEAR + WARP_FILL_OUTLIERS); + linearPolar(lin_polar_img, recovered_lin_polar_img, center, radius, WARP_INVERSE_MAP + INTER_LINEAR + WARP_FILL_OUTLIERS); imshow("Log-Polar", log_polar_img ); imshow("Linear-Polar", lin_polar_img );