Search code examples
pythonnumpyopencvpolar-coordinatescartesian

Comparing opencv lineartoPolar() transformation in python


My objective is to convert a 2D power spectrum (below) from cartesian to polar coordinates.

imshow(np.log10(psd2shift),cmap=cm.jet)

enter image description here There are several posts on stackoverflow on how to do just that such as this link. And so I believe my code is right.

ro,col=psd2shift.shape
cent=(int(ro/2),int(col/2))
max_radius = int(np.sqrt(ro**2+col**2)/2)
polar=cv.linearPolar(np.log10(psd2shift),cent,max_radius,cv.WARP_FILL_OUTLIERS)
plt.imshow(polar,cmap=cm.jet, interpolation='bicubic')

enter image description here

Nonetheless I am not getting what I want which is this: enter image description here

Obviously there is a difference in the transformation that I have not been able to uncover despite digging into the help of linearPolar function or the documentation here. It almost seems that the center is not defined right, but I am pretty sure it is.Thoughts?

With help(cv.linearPolar) Returns: Help on built-in function linearPolar:

linearPolar(...)
    linearPolar(src, center, maxRadius, flags[, dst]) -> dst
    .   @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]
    .   
    .   where
    .   \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]
    .   
    .   
    .   @param src Source image
    .   @param dst Destination image. It will have same size and type as src.
    .   @param center The transformation center;
    .   @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.

Solution

  • My first impression is that you might have messed up the center's coordinates. Points in OpenCV are refered as (x,y) which is confusingly translated to (col, row). Swapping those in your code

    ro,col=img.shape
    cent=(int(col/2),int(ro/2))
    max_radius = int(np.sqrt(ro**2+col**2)/2)
    polar=cv2.linearPolar(img,cent,max_radius,cv2.WARP_FILL_OUTLIERS)
    
    plt.figure(figsize=(16,10))
    plt.imshow(polar,cmap='jet', interpolation='bicubic')
    plt.show()
    

    I get the image, which I think is close to what you want.

    enter image description here