Kiểm tra tốc độ chiếu hình học


8

Gần đây tôi đã sử dụng các lớp chiếu OGR đi kèm với ogr / gdal, nhưng pyproj được khuyến nghị cho tôi, vì vậy tôi nghĩ tôi nên thử. Để giúp tôi quyết định xem tôi có nên thực hiện chuyển đổi không, tôi đã làm một bài kiểm tra tốc độ. Sau đây là một ví dụ nhỏ (gần như) có thể tái tạo mà tôi đã đưa ra để kiểm tra cả hai. Tôi không chắc bài kiểm tra này có hoàn toàn công bằng hay không, vì vậy các bình luận và đề xuất đều được chào đón!

Nhập khẩu trước, để đảm bảo chúng tôi bắt đầu với một sân chơi bình đẳng:

from pandas import Series # This is what our geometries are stored in
from shapely import wkb
import functools
from shapely.geometry import shape
from osgeo import ogr
# The following two imports are the important ones
from pyproj import Proj, transform
from osgeo.osr import SpatialReference, CoordinateTransformation

Bởi vì tôi đang lưu trữ các hình học có hình dạng trong một loạt 'gấu trúc', nên các chức năng cần phải hoạt động Series.apply(). Ở đây tôi xác định hai hàm (một sử dụng 'ogr.osr' và một sử dụng 'pyproj') để thực hiện các phép biến đổi tọa độ trong một lệnh gọi tới Series.apply():

def transform_osr(geoms, origin, target):
    target_crs = SpatialReference()
    target_crs.ImportFromEPSG(origin)
    origin_crs = SpatialReference()
    origin_crs.ImportFromEPSG(origin)
    transformer = CoordinateTransformation(origin_crs, target_crs)
    def trans(geom):
        g = ogr.CreateGeometryFromWkb(geom.wkb)
        if g.Transform(transformer):
            raise Exception("Ahhhh!")
        g = wkb.loads(g.ExportToWkb())
        return g
    return geoms.apply(trans)

def transform_pyproj(geoms, origin, target):
    target = Proj(init="epsg:%s" % target)
    origin = Proj(init="epsg:%s" % origin)
    transformer = functools.partial(transform, origin, target)
    def trans(geom):
        interface = geom.__geo_interface__
        geom_type = interface['type']
        coords = interface['coordinates']
        result = apply_to_coord_pairs(transformer, coords)
        return shape({'coordinates':result, 'type':geom_type})
    def apply_to_coord_pairs(fun, geom):
        return [not all([hasattr(y, "__iter__") for y in x]) and \
                fun(*x) or apply_to_coord_pairs(fun, x) for x in geom]
    return geoms.apply(trans)

Mỗi hàm này lấy mã EPSG làm đầu vào cho hệ thống tham chiếu tọa độ gốc và đích. Cả hai thư viện đều cung cấp các cách khác nhau để xác định thông tin chiếu, nhưng mã EPSG giữ cho mã khá đơn giản.

Đây là kết quả, sử dụng %timeitchức năng ma thuật trong ipython:

In [1]: %timeit transform_pyproj(l, 29903, 4326)
1 loops, best of 3: 641 ms per loop

In [2]: %timeit transform_osr(l, 29903, 4326)
10 loops, best of 3: 27.4 ms per loop

Rõ ràng phiên bản 'ogr.osr' nhanh hơn, nhưng nó có phải là một so sánh công bằng? Phiên bản 'pyproj' được thực hiện trên các điểm riêng lẻ và hầu hết được chạy bằng Python, trong khi phiên bản 'ogr.osr' hoạt động trực tiếp trên đối tượng hình học OGR. Có cách nào tốt hơn để so sánh những điều này?

Câu trả lời:


7

Pyproj là một phần mở rộng Python C sử dụng thư viện PROJ4 và osgeo.ogr là một phần mở rộng Python C sử dụng thư viện PROJ4. Nếu bạn chỉ xem xét phép chiếu tọa độ, trong thử nghiệm công bằng nhất, chúng sẽ gần như bằng nhau.

Biến đổi của Pyproj có thể hoạt động trên các mảng của các giá trị tọa độ, vì vậy bạn chỉ cần gọi nó một lần trên mỗi dòng hoặc vòng thay vì cho mỗi cặp. Điều này sẽ tăng tốc mọi thứ lên một chút. Ví dụ: https://gist.github.com/sgillies/3642564#file-2-py-L10 .

(Cập nhật) Ngoài ra, Shapely cung cấp một chức năng biến đổi hình học trong 1.2.16:

Help on function transform in module shapely.ops:

transform(func, geom)
    Applies `func` to all coordinates of `geom` and returns a new
    geometry of the same type from the transformed coordinates.

    `func` maps x, y, and optionally z to output xp, yp, zp. The input
    parameters may iterable types like lists or arrays or single values.
    The output shall be of the same type. Scalars in, scalars out.
    Lists in, lists out.

    For example, here is an identity function applicable to both types
    of input.

      def id_func(x, y, z=None):
          return tuple(filter(None, [x, y, z]))

      g2 = transform(id_func, g1)

    A partially applied transform function from pyproj satisfies the
    requirements for `func`.

      from functools import partial
      import pyproj

      project = partial(
          pyproj.transform,
          pyproj.Proj(init='espg:4326'),
          pyproj.Proj(init='epsg:26913'))

      g2 = transform(project, g1)

    Lambda expressions such as the one in

      g2 = transform(lambda x, y, z=None: (x+1.0, y+1.0), g1)

    also satisfy the requirements for `func`.

+1. Ngoài ra Shapely Points, linearRings và LineStrings có giao diện mảng gọn gàng , vì vậy bạn có thể làm một cái gì đó nhưprojected_coords = numpy.vstack(pyproj.transform(origin, target, *numpy.array(geom).T)).T
om_henners

Điều này thật tuyệt vời @sgillies. Vì một số lý do, phiên bản tạo hình của tôi không có biến đổi? tạo hình .__ phiên bản__: '1.2.17'. Tôi sẽ thử lấy nguồn trực tiếp.
Nông dân Carson

Ối xin lỗi. Đến trong phiên bản 1.2.18 (cuối tuần này, có lẽ).
sgillies
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.