使用Python Numpy将图像投影到球体内部

时间:2017-03-11 17:04:19

标签: python numpy geometry projection geometry-surface

问题:

我们说我的图像很大,5000x3000像素。我想将此图像粘贴到任意半径的球体内部。

为此,我将图像作为数组导入,我将确定数组的中心。我将遍历每个像素,确定它与中心的位移距离,并使用这个x和y位移,我将使用简单的几何来确定它应该在输出数组上复制到何处。

以下是我的输入和输出的一些示例(但是比我尝试使用的规模小得多)。

示例输入

Example input image

示例输出

Example output image

如何使用python和numpy来加速我的方法,这个方法在一个非常大的数组中逐像素,需要几分钟?

代码:

(x_d, y_d, z_d) = image.shape #get image dimensions
(x_c, y_c) = (x_d/2.0, y_d/2.0) #determine centre of image
new_image = np.zeros([x_m, y_m, d]) #create empty output image

for x in range(0, x_d): #iterate across pixels
    for y in range(0, y_d): #iterate down pixels
        (x_1, y_1) = (x-x_c, y-y_c) #determine pixel displacement from centre
        (r_x, r_y) = (np.sqrt((rad**2.0)-(y_1**2.0)), np.sqrt((rad**2.0)-(x_1**2.0))) #determine relative radius (maths part 2)
        #determine the relative radius
        x_2 = int(np.round(r_x*np.sin(x_1/r_x), 0)) #determine new x-position (maths part 1)
        y_2 = int(np.round(r_y*np.sin(y_1/r_y), 0)) #determine new y-position (maths part 1)
        x_2 = int(np.round(x_2+x_c, 0)) #convert back to absolute pixel location
        y_2 = int(np.round(y_2+y_c, 0)) #convert back to absolute pixel location
        new_image[x_2, y_2, :] = image[x, y, :] #...place the pixel there

尝试:

我已经搜索了预先构建的库来执行此操作,但我在使用某些特定术语时仍然没有找到任何内容。

我尝试使用numpy的项目和项目集功能读取和编写数组值,但实际上这似乎会减慢处理速度。

由于我将在多个图像上运行此操作,因此我首先尝试生成转换数组,但这对运行时间的影响非常小。即:

def generate_array(array, rad):
    """
    Function takes image and returns array that can be used to warp it
    """
    #array generated as code above but saved to 2 dimensional array for resultant x and y locations
    return array

def spherize(image, array):
    """
    Function takes image and warps it up as defined by the array
    """
    #image processed as code above but maths is not performed, instead output x and y locations are read from previously generated array
    return new_image

数学:

Image explaining maths part 1 referred to in the code 图像解释"数学第1部分"正如代码中所提到的那样。这样得到的结果像素位置就像从粘贴图像的球体顶部看到的一样。如果半径在另一个维度中保持相同,则这在一个维度上起作用,但是对于球体,此有效半径会发生变化,因为球体内部绘制的圆越小,离中心越远。因此"数学第2部分"在y中找到从球体中心位移的x中球体内部绘制的圆的有效半径。

Image explaining maths part 2 referred to in the code 图像解释"数学第2部分"如代码中所述。这将根据y中球体中心的位移来找到计算合成x位置的有效半径。

1 个答案:

答案 0 :(得分:1)

我在跟踪您共享的代码中的逻辑时遇到问题。如果您在图表中显示图像的位置以及是否可以提供原始图像点到新图像点(可能是10x10图像)的正确映射的小示例,将会有所帮助。

话虽这么说,我认为你可以使用universal functions数组加速计算。这些函数使用优化的代码对整个阵列进行逐元素计算。

例如,您可以使用indices函数创建一个包含图像中每个像素的索引(x和y坐标)的数组,然后对其进行所有计算。

这是使用数组计算的代码版本。这应该比在所有像素上循环运行得快得多。

(x_d, y_d, z_d) = (10,10,3) #image.shape #get image dimensions
(x_c, y_c) = (x_d/2.0, y_d/2.0) #determine centre of image
new_image = np.zeros([x_m, y_m, z_d]) #create empty output image

x, y = np.indices( (x_d, y_d) ) #create an array with the x and y coordintes of the pixels

# determine pixel displacement from centre
x1 = x - x_c
y1 = y - y_c

#determine relative radius (maths part 2)
rx = np.sqrt(rad**2 - y1**2)
ry = np.sqrt(rad**2 - x1**2)

#determine new x-position (maths part 1)
x2 = rx*np.sin(x1/rx)+x_c
y2 = ry*np.sin(y1/ry)+y_c

#convert back to absolute pixel location
x2 = (np.round(x2)).astype(int)
y2 = (np.round(y2)).astype(int)

#...place the pixel there
new_image[x2, y2] = image[x,y]

我相信我已根据您的代码正确地重新创建了您的计算,但没有输入示例我无法确定这是否正确。我希望这会有所帮助。