2

I try to recreate the image transformation ( log-polar mapping) from OpenCV doc.

Here is the input
Input image

An I should have such output ( semilog = flase):

enter image description here

My code ( modified example ):

#include <opencv2/core/core.hpp>
#include "opencv2/imgproc.hpp"
#include "opencv2/highgui.hpp"
#include <iostream>


using namespace cv;
using namespace std;

int main( int argc, char** argv )
{
    
    // 
    Mat src;
    Mat log_polar_img, lin_polar_img, recovered_log_polar, recovered_lin_polar_img;
    Mat dst;
    
    
    
        // image file to read
    std::string name =  "p"; // name of the file to read without extension
    std::string path =  "./"; // path to the file 
    std::string ext =   ".png"; // extension
    std::string file_in =   path + name + ext;
    std::cout << "file name = " << file_in << std::endl;
    
    
    
    
    // read the file 
    src = imread(file_in, cv::IMREAD_COLOR); // CV_LOAD_IMAGE_COLOR
    if (src.empty()) {// Error Handling
            std::cout << "Image File " << file_in << " not found. Press any key to end. " << std::endl;
        std::cin.get();  return -1; // wait for any key press
            }
            
        std::cout << "Image File " << file_in << " found and opened" << std::endl;
        
            
            
    
    
        
    
    
    
        int flags = INTER_LINEAR + WARP_FILL_OUTLIERS;
   
    
        Point2f center( (float)src.cols / 2, (float)src.rows / 2 );
        double maxRadius = 0.7*min(center.y, center.x);
        
 
        //double M = (float)src.cols  / log(maxRadius);
        //logPolar(src, log_polar_img, center, M, flags);
        //linearPolar(src, lin_polar_img, center, maxRadius, flags);
        //logPolar(log_polar_img, recovered_log_polar, center, M, flags + WARP_INVERSE_MAP);
        //linearPolar(lin_polar_img, recovered_lin_polar_img, center, maxRadius, flags + WARP_INVERSE_MAP);
        
        

        // direct transform
        warpPolar(src, lin_polar_img, Size(),center, M, flags);                     // linear Polar
        warpPolar(src, log_polar_img, Size(),center, maxRadius, flags + WARP_POLAR_LOG);    // semilog Polar
        
        // inverse transform
        warpPolar(lin_polar_img, recovered_lin_polar_img, src.size(), center, maxRadius, flags + WARP_INVERSE_MAP);
        warpPolar(log_polar_img, recovered_log_polar, src.size(), center, maxRadius, flags + WARP_POLAR_LOG + WARP_INVERSE_MAP);
        
        // Below is the reverse transformation for (rho, phi)->(x, y) :
        
        if (flags & WARP_POLAR_LOG)
            dst = log_polar_img;
        else
            dst = lin_polar_img;
        
        //get a point from the polar image
        int rho = cvRound(dst.cols * 0.75);
        int phi = cvRound(dst.rows / 2.0);
        double angleRad, magnitude;
        double Kangle = dst.rows / CV_2PI;
        angleRad = phi / Kangle;
        if (flags & WARP_POLAR_LOG)
        {
            double Klog = dst.cols / std::log(maxRadius);
            magnitude = std::exp(rho / Klog);
        }
        else
        {
            double Klin = dst.cols / maxRadius;
            magnitude = rho / Klin;
        }
        int x = cvRound(center.x + magnitude * cos(angleRad));
        int y = cvRound(center.y + magnitude * sin(angleRad));
        
        drawMarker(src, Point(x, y), Scalar(0, 255, 0));
        drawMarker(dst, Point(rho, phi), Scalar(0, 255, 0));
        
        
        
        
        // windows 
        namedWindow( "Src", WINDOW_AUTOSIZE );// 
        namedWindow( "Linear-Polar", WINDOW_AUTOSIZE );
        namedWindow( "Log-Polar", WINDOW_AUTOSIZE);
        namedWindow( "Recovered Linear-Polar", WINDOW_AUTOSIZE);
        namedWindow( "Recovered Log-Polar", WINDOW_AUTOSIZE);
        namedWindow( "Dst", WINDOW_AUTOSIZE );// 
        //
        moveWindow( "Linear-Polar", 20,20 );
        moveWindow( "Log-Polar", 700,20 );
        moveWindow( "Recovered Linear-Polar", 20, 350 );
        moveWindow( "Recovered Log-Polar", 700, 350 );
        //
        imshow("Src", src);
        imshow("Log-Polar", log_polar_img);
        imshow("Linear-Polar", lin_polar_img);
        imshow("Recovered Linear-Polar", recovered_lin_polar_img );
        imshow("Recovered Log-Polar", recovered_log_polar );
        imshow("Dst", dst);
        //
        waitKey(0);
        std::cout << "Press any key to end " << std::endl;  
        
    return 0;
}

It works, but the result is not as expected (p265.png)

enter image description here

How can I get the same image as in OpenCV documentation ?
Why the official example does not do what documentation says ?

===================== edit 1 ====================================

The question is about OpenCV and geometric transformation. The OpenCV has many language bindings. Below is example in python

# https://stackoverflow.com/questions/2164570/reprojecting-polar-to-cartesian-grid
# HanClinto
# https://docs.opencv.org/3.4/d2/de6/tutorial_py_setup_in_ubuntu.html
import numpy as np
import cv2
from matplotlib import pyplot as plt

# Read in our image from disk
image = cv2.imread('Q.png',0)
plt.imshow(image),plt.show()

margin = 0.9 # Cut off the outer 10% of the image
# Do the polar rotation along 1024 angular steps with a radius of 256 pixels.
polar_img = cv2.warpPolar(image, (256, 1024), (image.shape[0]/2,image.shape[1]/2), image.shape[1]*margin*0.5, cv2.WARP_POLAR_LINEAR) # WARP_POLAR_LINEAR
# Rotate it sideways to be more visually pleasing
polar_img = cv2.rotate(polar_img, cv2.ROTATE_90_COUNTERCLOCKWISE)
plt.imshow(polar_img),plt.show()
2
  • please show the result. Commented May 2, 2022 at 7:22
  • looks like the center isn't right, and the radius is smaller than the circle in the input picture Commented May 2, 2022 at 16:20

1 Answer 1

2

Problem

According to the documentation, the center must be the center of the circle not the center of the image (as you have done in your case Point2f center( (float)src.cols / 2, (float)src.rows / 2 );). And the max_Radius must be a fixed distance from the center of this circle and not the image.

I was able to obtain a near representation of the expected output, using the following image:

enter image description here

I manually cropped the image such that the center of the circle matches the center of the image. But the result was not as expected:

enter image description here

Illustration

So for the purpose of illustrating a valid example, I drew a circle at the center of a black image with fixed thickness and made an attempt to convert to its polar form. (Following snippet is in python):

black = np.zeros((300, 300, 3), np.uint8)
# drawing a circle at 
cv2.circle(black, (150,150), 100, (255,255,0) , 8)

enter image description here

img = black.astype(np.float32)
polar_image = cv2.linearPolar(src = img, center = (img.shape[0]/2, img.shape[1]/2), maxRadius = 125.0, flags = cv2.WARP_FILL_OUTLIERS)
polar_image = polar_image.astype(np.uint8)

enter image description here

I am sure you can replicate the above in C++.

Sign up to request clarification or add additional context in comments.

4 Comments

Good example. It would be nice to add center and radius on the image
Whay you do not use cv2.warpPolar ?
@Adam I haven't used it before.
@Adam You can also check out: stackoverflow.com/questions/51675940/…

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.