geodesic distance

1、python实现geodesic距离

其中见到的出现最多的名词之一就是 geodesic distance ,这个单词的中文翻译是测地距离,其实测地距离的意思就是在三维空间中,两点之间的最短路径,归根究底就是最短路径,在三维中间从一个点到另外一个点的路径有无数种,但是最短路径只有一条,那么这个最短路径的长度就是测地距离 geodesic distance

# -*- coding: utf-8 -*-
"""
Created on Mon Jan 24 15:00:35 2022

@author: wmz
"""
import numpy as np
import matplotlib.pyplot as plt
import numpy.ma as ma

# %pylab
from scipy.ndimage.morphology import distance_transform_edt
l = 100
x, y = np.indices((l, l))
center1 = (50, 20)
center2 = (28, 24)
center3 = (30, 50)
center4 = (60,48)
radius1, radius2, radius3, radius4 = 15, 12, 19, 12
circle1 = (x - center1[0])**2 + (y - center1[1])**2 < radius1**2
circle2 = (x - center2[0])**2 + (y - center2[1])**2 < radius2**2
circle3 = (x - center3[0])**2 + (y - center3[1])**2 < radius3**2
circle4 = (x - center4[0])**2 + (y - center4[1])**2 < radius4**2
# 3 circles
img = circle1 + circle2 + circle3 + circle4
mask = ~img.astype(bool)
img = img.astype(float)
m = np.ones_like(img)
m[center1] = 0
#imshow(distance_transform_edt(m), interpolation='nearest')
m = ma.masked_array(distance_transform_edt(m), mask)
plt.imshow(m, interpolation='nearest')
plt.show()

在这里插入图片描述

I implemented the Dijkstra algorithm to apply a geodesic distance transform to the shape above:

# -*- coding: utf-8 -*-
"""
Created on Mon Jan 24 15:43:44 2022

@author: wmz
"""

import numpy
import numpy as np
import matplotlib.pyplot as plt
import numpy.ma as ma
from math import *
from numpy import *

# %pylab
from scipy.ndimage.morphology import distance_transform_edt


def geodesic_distance_transform(m):
    visit_mask = mask.copy() # mask visited cells
    m = m.filled(numpy.inf)
    m[m!=0] = numpy.inf
    distance_increments = numpy.asarray([sqrt(2), 1., sqrt(2), 1., 1., sqrt(2), 1., sqrt(2)])
    connectivity = [(i,j) for i in [-1, 0, 1] for j in [-1, 0, 1] if (not (i == j == 0))]
    cc = unravel_index(m.argmin(), m.shape) # current_cell
    while (~visit_mask).sum() > 0:
        neighbors = [tuple(e) for e in asarray(cc) - connectivity 
                     if not visit_mask[tuple(e)]]
        tentative_distance = [distance_increments[i] for i,e in enumerate(asarray(cc) - connectivity) 
                              if not visit_mask[tuple(e)]]
        for i,e in enumerate(neighbors):
            d = tentative_distance[i] + m[cc]
            if d < m[e]:
                m[e] = d
        visit_mask[cc] = True
        m_mask = ma.masked_array(m, visit_mask)
        cc = unravel_index(m_mask.argmin(), m.shape)
    return m


if __name__ == "__main__":
    
    l = 100
    x, y = np.indices((l, l))
    center1 = (50, 20)
    center2 = (28, 24)
    center3 = (30, 50)
    center4 = (60,48)
    radius1, radius2, radius3, radius4 = 15, 12, 19, 12
    circle1 = (x - center1[0])**2 + (y - center1[1])**2 < radius1**2
    circle2 = (x - center2[0])**2 + (y - center2[1])**2 < radius2**2
    circle3 = (x - center3[0])**2 + (y - center3[1])**2 < radius3**2
    circle4 = (x - center4[0])**2 + (y - center4[1])**2 < radius4**2
    # 3 circles
    img = circle1 + circle2 + circle3 + circle4
    mask = ~img.astype(bool)
    img = img.astype(float)
    m = np.ones_like(img)
    m[center1] = 0
    m = ma.masked_array(distance_transform_edt(m), mask)
    gdt = geodesic_distance_transform(m)
    plt.imshow(gdt, interpolation='nearest')
    plt.colorbar()
    plt.show()

执行时间:

0.22861695289611816 s

在这里插入图片描述

安装软件包

conda install sscikit-fmm
# -*- coding: utf-8 -*-
"""
Created on Mon Jan 24 15:43:44 2022

@author: wmz
"""

import numpy
import numpy as np
import matplotlib.pyplot as plt
import numpy.ma as ma
from math import *
from numpy import *
import skfmm
import time
# %pylab
from scipy.ndimage.morphology import distance_transform_edt


def geodesic_distance_transform(m):
    visit_mask = mask.copy() # mask visited cells
    m = m.filled(numpy.inf)
    m[m!=0] = numpy.inf
    distance_increments = numpy.asarray([sqrt(2), 1., sqrt(2), 1., 1., sqrt(2), 1., sqrt(2)])
    connectivity = [(i,j) for i in [-1, 0, 1] for j in [-1, 0, 1] if (not (i == j == 0))]
    cc = unravel_index(m.argmin(), m.shape) # current_cell
    while (~visit_mask).sum() > 0:
        neighbors = [tuple(e) for e in asarray(cc) - connectivity 
                     if not visit_mask[tuple(e)]]
        tentative_distance = [distance_increments[i] for i,e in enumerate(asarray(cc) - connectivity) 
                              if not visit_mask[tuple(e)]]
        for i,e in enumerate(neighbors):
            d = tentative_distance[i] + m[cc]
            if d < m[e]:
                m[e] = d
        visit_mask[cc] = True
        m_mask = ma.masked_array(m, visit_mask)
        cc = unravel_index(m_mask.argmin(), m.shape)
    return m


if __name__ == "__main__":
    
    l = 100
    x, y = np.indices((l, l))
    center1 = (50, 20)
    center2 = (28, 24)
    center3 = (30, 50)
    center4 = (60,48)
    radius1, radius2, radius3, radius4 = 15, 12, 19, 12
    circle1 = (x - center1[0])**2 + (y - center1[1])**2 < radius1**2
    circle2 = (x - center2[0])**2 + (y - center2[1])**2 < radius2**2
    circle3 = (x - center3[0])**2 + (y - center3[1])**2 < radius3**2
    circle4 = (x - center4[0])**2 + (y - center4[1])**2 < radius4**2
    # 3 circles
    img = circle1 + circle2 + circle3 + circle4
    mask = ~img.astype(bool)
    img = img.astype(float)
    m = np.ones_like(img)
    m[center1] = 0
    m = ma.masked_array(m, mask) # distance_transform_edt(m)
    t1 = time.time()
    # gdt = geodesic_distance_transform(m)
    distance = skfmm.distance(m)
    t2 = time.time()
    eclipsed = t2 - t1
    print(eclipsed, "s")
    # plt.imshow(gdt, interpolation='nearest')
    plt.imshow(distance, interpolation='nearest')

    plt.colorbar()
    plt.show()

执行时间:

0.0009877681732177734 s

在这里插入图片描述
速度skfmm.distance是前者的231倍,效果skfmm.distance还要好于前者。

参考:关于 geodesic distance 的通俗解释
参考:geodesic distance transform in python

2、c++实现geodesic距离

编译与安装参考 GeographicLib 1.52

测试程序:
In order to use GeographicLib from C++ code, you will need to

Include the header files for the GeographicLib classes in your code. E.g.,

#include <GeographicLib/LambertConformalConic.hpp> 

Include the GeographicLib:: namespace prefix to the GeographicLib classes, or include

using namespace GeographicLib; 

in your code.

  • Finally compile and link your code. You have two options here.
    • Use cmake to build your package. If you are familiar with cmake this typically will be far the simplest option.
    • Set the include paths and linking options “manually”.
  • Building your code with cmake. In brief, the necessary steps are:

include in your CMakeLists.txt files

	find_package (GeographicLib REQUIRED)
    add_executable (program source1.cpp source2.cpp)
    target_link_libraries (program ${GeographicLib_LIBRARIES}) 
  • configure your package, e.g., with
 mkdir BUILD
    cd BUILD
    cmake -G "Visual Studio 14" -A x64 \
      -D CMAKE_PREFIX_PATH="C:/Program Files" \
      -D CMAKE_INSTALL_PREFIX="C:/Program Files/testgeog" \
      .. 

Here is a very simple test code, which uses the Geodesic class:

// Small example of using the GeographicLib::Geodesic class
 
#include <iostream>
#include <GeographicLib/Geodesic.hpp>
 
using namespace std;
using namespace GeographicLib;
 
int main() {
  const Geodesic& geod = Geodesic::WGS84();
  // Distance from JFK to LHR
  double
    lat1 = 40.6, lon1 = -73.8, // JFK Airport
    lat2 = 51.6, lon2 = -0.5;  // LHR Airport
  double s12;
  geod.Inverse(lat1, lon1, lat2, lon2, s12);
  cout << s12 / 1000 << " km\n";
}

完整CMakeLists.txt

project (geodesictest)
cmake_minimum_required (VERSION 3.1.0)

find_package (GeographicLib REQUIRED)

if (NOT MSVC)
  set (CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
endif ()

add_executable (${PROJECT_NAME} example-Geodesic-small.cpp)
target_link_libraries (${PROJECT_NAME} ${GeographicLib_LIBRARIES})

if (MSVC)
  get_target_property (_LIBTYPE ${GeographicLib_LIBRARIES} TYPE)
  if (_LIBTYPE STREQUAL "SHARED_LIBRARY")
    # On Windows systems, copy the shared library to build directory
    add_custom_command (TARGET ${PROJECT_NAME} POST_BUILD
      COMMAND ${CMAKE_COMMAND} -E
      copy $<TARGET_FILE:${GeographicLib_LIBRARIES}> ${CMAKE_CFG_INTDIR}
      COMMENT "Copying shared library for GeographicLib")
  endif ()
endif () 

参考:C library for Geodesics 1.52
参考:GeographicLib 1.52
参考:

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

落花逐流水

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值