Python中快速的笛卡尔坐标系到极坐标系再到笛卡尔坐标系的转换

8
我想在Python中将二维数组/图像转换为极坐标,进行处理,然后再转换回笛卡尔坐标系。以下是ImajeJ Polar Transformer插件(用于示例代码的同心圆)的结果:链接如下:Polar Transformer 由于图像的数量和维数相当大,因此我正在查看openCV是否有一种快速简便的方法来完成此操作。
我了解到cv. CartToPolarPolarToCart,但我无法使用它们。我更理解LogPolar,其中输入和输出都是数组,并且可以设置中心,插值和反演(即CV_WARP_INVERSE_MAP)。是否有一种类似的方式使用CartToPolar/PolarToCart?
    import numpy as np
    import cv

    #sample 2D array that featues concentric circles
    circlesArr = np.ndarray((512,512),dtype=np.float32)
    for i in range(10,600,10): cv.Circle(circlesArr,(256,256),i-10,np.random.randint(60,500),thickness=4)

    #logpolar
    lp = np.ndarray((512,512),dtype=np.float32)
    cv.LogPolar(circlesArr,lp,(256,256),100,cv.CV_WARP_FILL_OUTLIERS)

    #logpolar Inverse
    lpinv = np.ndarray((512,512),dtype=np.float32)
    cv.LogPolar(lp,lpinv,(256,256),100, cv.CV_WARP_INVERSE_MAP + cv.CV_WARP_FILL_OUTLIERS)

    #display images
    from scipy.misc import toimage
    toimage(lp, mode="L").show()
    toimage(lpinv, mode="L").show()

这是针对计算机断层扫描(CT)工作流程的,如果出现环形伪影,可以更容易地将其过滤为线条。

4个回答

6

最新版本的opencv支持cv2.linearPolar函数。这可能是另一种解决方案,不需要使用opencv:

def polar2cart(r, theta, center):

    x = r  * np.cos(theta) + center[0]
    y = r  * np.sin(theta) + center[1]
    return x, y

def img2polar(img, center, final_radius, initial_radius = None, phase_width = 3000):

    if initial_radius is None:
        initial_radius = 0

    theta , R = np.meshgrid(np.linspace(0, 2*np.pi, phase_width), 
                            np.arange(initial_radius, final_radius))

    Xcart, Ycart = polar2cart(R, theta, center)

    Xcart = Xcart.astype(int)
    Ycart = Ycart.astype(int)

    if img.ndim ==3:
        polar_img = img[Ycart,Xcart,:]
        polar_img = np.reshape(polar_img,(final_radius-initial_radius,phase_width,3))
    else:
        polar_img = img[Ycart,Xcart]
        polar_img = np.reshape(polar_img,(final_radius-initial_radius,phase_width))

    return polar_img

嗨,亚历山德罗 - 我也尝试用类似的方法解决这个问题,并编写了类似的代码,尽管我使用了一个循环而不是meshgrid(我以前从未见过这样的东西); 你知道这表现如何吗?我的需要花费约1秒钟来处理VGA图像 - 太长了。 - cjm2671
1
好的,我已经测试了你的代码,与我的迭代解法相比它非常快 - 而且我学到了新东西 - 非常感谢! - cjm2671

2
CV源代码提到了一个LinearPolar。虽然没有详细文档说明,但它似乎与LogPolar类似。您试过这个吗?

非常非常感谢!的确 LinearPolar 做了它所说的。不幸的是,通过使用 import cv 它无法使用,但我尝试了 from opencv import cv 然后使用 cv.cvLinearPolar ,它能正常工作。接下来几天我会在大型数据集上测试其性能。谢谢! - Papado
很酷。我想知道为什么它不可见?我会尝试提交一个错误报告。 - andrew cooke

2

亲爱的Stefan,非常感谢您的反馈。我会在接下来的几天内检查和基准测试您的实现。顺便说一句,我最终浏览了Supreme,它似乎非常有趣。您是否发表过任何关于它的文章? - Papado
@Papado我从未看到你的评论,但是没错--arXiv上有一篇论文和一篇论文。顺便说一句,现在可以使用“skimage.transform.warp”在约5行代码中实现对数极坐标变换了。 - Stefan van der Walt

0
更新:我正在寻找类似的东西,现在您可以使用以下的cv2来完成往返。
import cv2
import math

# img -> your image 
h, w = img.shape[:2]
img_center = (h/2, w/2)
img_radius = math.hypot(h/2, w/2)

cart_2_polar_flag = cv2.WARP_FILL_OUTLIERS
img_forth = cv2.linearPolar(img, img_center, img_radius, cart_2_polar_flag)


polar_2_cart_flag = cv2.WARP_INVERSE_MAP
img_back = cv2.linearPolar(img_forth, img_center, img_radius, polar_2_cart_flag)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接