在python numpy数组中,如何知道哪个对象更接近一张图像中的一点? 输出

问题描述

我有一个numpy数组,代表一个图像。图像具有3种颜色:橙色(背景),蓝色(对象1)和绿色(对象2)。我使用3个值(0、1和2)来指示numpy数组中的3种颜色。两个对象没有重叠。

我的问题是:如何知道哪个对象更靠近图像的中心(红点)? (此处,更近表示从物体到一个物体的图像中心的最近距离小于与物体之间的最近距离到目标物体图像的中心)

我的代码是这样的:

import numpy as np
from scipy import spatial
import time

sub_image1 = np.ones((30,30,30))
sub_image2 = np.ones((20,10,15))

# pad the two sub_images to same shape (1200,1200,1200) to simulate my 3D medical data
img_1 = np.pad(sub_image1,((1100,70),(1100,70)))
img_2 = np.pad(sub_image1,80),(1130,60),(1170,15)))

def nerest_dis_to_center(img):
    position = np.where(img > 0)
    coordinates = np.transpose(np.array(position))  # get the coordinates where the voxels is not 0
    cposition = np.array(img.shape) / 2  # center point position/coordinate
    distance,index = spatial.KDTree(coordinates).query(cposition)
    return distance

t1 = time.time()
d1 = nerest_dis_to_center(img_1)
d2 = nerest_dis_to_center(img_2)

if d1 > d2:
    print("img2 object is nearer")
elif d2 > d1:
    print("img1 object is nearer")
else:
    print("They are the same far")
t2 = time.time()
print("used time: ",t2-t1)
# 30 seconds

上面的代码可以运行,但是速度很慢,并且需要很大的内存(大约30 GB)。如果要在PC上重现我的代码,则可以使用较小的形状而不是(3200,1200,1200)。有什么更有效的方法可以实现我的目标?

注意:实际上我的图像是3D CT医学图像,太大了,无法上传。图像中的对象是随机的,可以是凸的或不是凸的。这就是为什么我的内含非常缓慢。在这里为了澄清我的问题,我使用2D图像来解释我的方法

Figure

解决方法

这可能不是最终的解决方案,也不是最佳的时间,必须使用实际数据进行测试。为了使我的想法更完整,我选择了较小的矩阵尺寸和2D情况

import numpy as np
import matplotlib.pyplot as plt


sub_image1 = np.ones((30,30))  # 1st object
sub_image2 = np.ones((20,10)) * 2  # 2nd object

# pad the two sub_images to same shape (120,120)
img_1 = np.pad(sub_image1,((110,60),(60,110)))
img_2 = np.pad(sub_image2,((100,80),(130,60)))

final_image = img_1 + img_2  # creating final image with both objects in a background of zeros

image_center = (np.array([final_image.shape[0],final_image.shape[1]]) / 2).astype(np.int)

# mark the center
final_image[image_center[0],image_center[1]] = 10

# find the coordinates of where the objects are
first_obj_coords = np.argwhere(final_image == 1)  # could be the most time consuming operation
second_obj_coords = np.argwhere(final_image == 2) # could be the most time consuming 

# find their centers
first_obj_ctr = np.mean(first_obj_coords,axis=0)
second_obj_ctr = np.mean(second_obj_coords,axis=0)

# turn the centers to int for using them to index
first_obj_ctr = np.floor(first_obj_ctr).astype(int)
second_obj_ctr = np.floor(second_obj_ctr).astype(int)

# mark the centers of the objects
final_image[first_obj_ctr[0],first_obj_ctr[1]] = 10
final_image[second_obj_ctr[0],second_obj_ctr[1]] = 10

# calculate the distances from center to the object center
print('Distance to first object: ',np.linalg.norm(image_center - first_obj_ctr))
print('Distance to second object: ',np.linalg.norm(image_center - second_obj_ctr))

plt.imshow(final_image)
plt.show()

输出

Distance to first object:  35.38361202590826
Distance to second object:  35.17101079013795

enter image description here

,

我解决了这个问题。

因为两个3D阵列太大。因此,首先我使用最近邻居方法将它们采样到较小的尺寸。然后继续:

import numpy as np
from scipy import spatial
import time

sub_image1 = np.ones((30,30,30))
sub_image2 = np.ones((20,10,15))

# pad the two sub_images to same shape (1200,1200,1200) to simulate my 3D medical data
img_1 = np.pad(sub_image1,((1100,70),(1100,70)))
img_2 = np.pad(sub_image1,(1130,(1170,15)))

ori_sz = np.array(img_1.shape)
trgt_sz = ori_sz / 4
zoom_seq = np.array(trgt_sz,dtype='float') / np.array(ori_sz,dtype='float')
img_1 = ndimage.interpolation.zoom(img_1,zoom_seq,order=0,prefilter=0)
img_2 = ndimage.interpolation.zoom(img_2,prefilter=0)
print("it cost this secons to downsample the nearer image" + str(time.time() - t0))  # 0.8 seconds


def nerest_dis_to_center(img):
    position = np.where(img > 0)
    coordinates = np.transpose(np.array(position))  # get the coordinates where the voxels is not 0
    cposition = np.array(img.shape) / 2  # center point position/coordinate
    distance,index = spatial.KDTree(coordinates).query(cposition)
    return distance

t1 = time.time()
d1 = nerest_dis_to_center(img_1)
d2 = nerest_dis_to_center(img_2)

if d1 > d2:
    print("img2 object is nearer")
elif d2 > d1:
    print("img1 object is nearer")
else:
    print("They are the same far")
t2 = time.time()
print("used time: ",t2-t1)
# 1.1 seconds