首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >计算集贸市场的MCP几何

计算集贸市场的MCP几何
EN

Stack Overflow用户
提问于 2020-06-01 15:34:18
回答 1查看 223关注 0票数 1

我试图使用几何学 find_costs函数计算市场集。它一直在出色地计算最低成本的路线,但我不想找到最近的来源的旅行成本,我想计算最近的来源的指数。

示例代码

代码语言:javascript
复制
import numpy as np
import skimage.graph as graph
import copy

img = np.array([[1,1,2,2],[2,1,1,3],[3,2,1,2],[2,2,2,1]])
mcp = graph.MCP_Geometric(img)

destinations = [[0,0],[3,3]]
costs, traceback = mcp.find_costs(destinations)
print(costs)

[[0.         1.         2.5        4.5       ]
 [1.5        1.41421356 2.41421356 4.        ]
 [4.         2.91421356 1.41421356 1.5       ]
 [5.5        3.5        1.5        0.        ]]

这如预期的工作,并创造了一个不错的旅行成本光栅。但是,我希望(对于每个单元)知道哪个目的地是最近的。我找到的最佳解决方案是分别运行每个目的地,然后通过最小计算将它们组合起来。它起作用,但速度慢,而且一直没有大规模发挥作用。

代码语言:javascript
复制
all_c = []
for dest in destinations:
    costs, traceback = mcp.find_costs([dest])
    all_c.append(copy.deepcopy(costs))

res = np.dstack(all_c)
res_min = np.amin(res, axis=2)
output = np.zeros([res_min.shape[0], res_min.shape[1]])
for idx in range(0, res.shape[2]):
    cur_data = res[:,:,idx]
    cur_val = (cur_data == res_min).astype(np.byte) * idx
    output = output + cur_val
output = output.astype(np.byte)

print(output)
array([[0, 0, 0, 0],
       [0, 0, 1, 1],
       [0, 1, 1, 1],
       [1, 1, 1, 1]], dtype=int8)

我一直在研究MCP_Geometric和MCP_Flexible函数的重载问题,但是我找不到提供目的地索引的任何信息。

希望这能提供足够的信息来复制和理解我想要做的事情,谢谢!

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-06-02 03:54:53

好吧,这是一段旅程,但弄清楚这很有趣。我不清楚它的速度会有多快,但我认为在很多目的地和舒适的RAM图像中,它应该是相当快的。

关键是traceback返回值,它某种程度上告诉您邻居索引要到达最近的目的地。因此,只要找到一点路径,你就能找到目的地。能快点吗?事实证明,它可以,与一些NumPy索引争论,scipy.sparse矩阵,和connected_componentsscipy.sparse.csgraph

让我们从相同的成本数组开始,这两个目的地:

代码语言:javascript
复制
import numpy as np

image = np.array(
    [[1, 1, 2, 2],
     [2, 1, 1, 3],
     [3, 2, 1, 2],
     [2, 2, 2, 1]]
)
destinations = [[0, 0], [3, 3]]

然后我们绘制图表,得到成本和追溯:

代码语言:javascript
复制
from skimage import graph

mcp = graph.MCP_Geometric(image)
costs, traceback = mcp.find_costs(destinations)
print(traceback)

给予:

代码语言:javascript
复制
[[-1  4  4  4]
 [ 6  7  7  1]
 [ 6  6  0  1]
 [ 3  3  3 -1]]

现在,我必须查找回溯是什么的文档:

costs数组相同的形状;该数组包含其先前索引中对任何给定索引的偏移量。将偏移索引索引到offsets属性中,这是一个n-d偏移量数组。在2-d情况下,如果偏移量[tracebackx,y]是(-1,-1),这意味着x,y在到某个起始位置的最小成本路径中的前身是x+1,y+1。注意,如果offset_index是-1,则不考虑给定的索引。

由于某种原因,我的mcp对象没有一个偏移属性--可能是Cython?不知道,稍后再研究--但是搜索源代码会告诉我,偏移是用函数定义的。因此,我做了一件坏事,从那个私有模块导入,这样我就可以声称什么是正确的--偏移列表,它从traceback中的数字转换为图像坐标中的偏移:

代码语言:javascript
复制
from skimage.graph import _mcp

offsets = _mcp.make_offsets(2, True)
print(offsets)

这意味着:

代码语言:javascript
复制
[array([-1, -1]),
 array([-1,  0]),
 array([-1,  1]),
 array([ 0, -1]),
 array([0, 1]),
 array([ 1, -1]),
 array([1, 0]),
 array([1, 1])]

现在,与偏移量有关的最后一件事是:您将注意到,目标在回溯中标记为"-1",这与偏移量数组的最后一个元素不对应。因此,我们附加np.array([0, 0]),然后traceback中的每个值都对应于一个真正的偏移量。在目的地的情况下,你有一个自我优势,但这是好的。

代码语言:javascript
复制
offsets.append(np.array([0, 0]))
offsets_arr = np.array(offsets)  # shape (9, 2)

现在,我们可以通过偏移量、像素坐标和像素ids构建一个图形。首先,我们使用np.indices为图像中的每个像素获取一个索引:

代码语言:javascript
复制
indices = np.indices(traceback.shape)
print(indices.shape)

给予:

代码语言:javascript
复制
(2, 4, 4)

为了获得一个数组,该数组对于每个像素都具有它的邻居的偏移量,我们使用花式数组索引

代码语言:javascript
复制
offset_to_neighbor = offsets_arr[traceback]
print(offset_to_neighbor.shape)

这意味着:

代码语言:javascript
复制
(4, 4, 2)

追溯索引和numpy索引之间的轴是不同的,但是任何小的转换都不能修复:

代码语言:javascript
复制
neighbor_index = indices - offset_to_neighbor.transpose((2, 0, 1))

最后,我们希望处理整数像素in,以便创建一个所有像素的图形,而不是坐标。为此,我们使用np.ravel_multi_index

代码语言:javascript
复制
ids = np.arange(traceback.size).reshape(image.shape)
neighbor_ids = np.ravel_multi_index(
    tuple(neighbor_index), traceback.shape
)

这为每个像素提供了唯一的ID,然后为每个像素提供了唯一的“到达目的地的步骤”:

代码语言:javascript
复制
print(ids)
print(neighbor_ids)
代码语言:javascript
复制
[[ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]
 [12 13 14 15]]
[[ 0  0  1  2]
 [ 0  0  1 11]
 [ 4  5 15 15]
 [13 14 15 15]]

然后,我们可以使用SciPy稀疏矩阵将其转化为一个图。我们不关心这个图的权重,所以我们只对边使用1的值。

代码语言:javascript
复制
from scipy import sparse

g = sparse.coo_matrix((
    np.ones(traceback.size),
    (ids.flat, neighbor_ids.flat),
    shape=(ids.size, ids.size),
)).tocsr()

(这使用稀疏COOrdinate矩阵的(值、(行、列)或(数据,(i,j))输入格式)。

最后,我们使用连通元件获取图--距离每个目标最近的像素组。该函数返回组件的数量,并将“像素id”映射到组件:

代码语言:javascript
复制
n, components = sparse.csgraph.connected_components(g)
basins = components.reshape(image.shape)
print(basins)
代码语言:javascript
复制
[[0 0 0 0]
 [0 0 0 1]
 [0 0 1 1]
 [1 1 1 1]]

(请注意,这个结果与您的结果略有不同,因为有关像素的成本与目标0和1相同,因此标记哪个像素是任意的。)

代码语言:javascript
复制
print(costs)
代码语言:javascript
复制
[[0.         1.         2.5        4.5       ]
 [1.5        1.41421356 2.41421356 4.        ]
 [4.         2.91421356 1.41421356 1.5       ]
 [5.5        3.5        1.5        0.        ]]

希望这能有所帮助!

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/62135639

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档