0

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()
Adam
  • 1,254
  • 12
  • 25

1 Answers1

1

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++.

Jeru Luke
  • 20,118
  • 13
  • 80
  • 87