পাইথনের রাস্টারটিতে পয়েন্ট ডেটার বিলিয়ার সংযোগ?


12

আমার সাথে একজন রাস্টার রয়েছে যার সাথে আমি কিছু পয়েন্ট ইন্টারপোলেশনগুলি করতে চাই। আমি এখানে যেখানে আছি:

from osgeo import gdal
from numpy import array

# Read raster
source = gdal.Open('my_raster.tif')
nx, ny = source.RasterXSize, source.RasterYSize
gt = source.GetGeoTransform()
band_array = source.GetRasterBand(1).ReadAsArray()
# Close raster
source = None

# Compute mid-point grid spacings
ax = array([gt[0] + ix*gt[1] + gt[1]/2.0 for ix in range(nx)])
ay = array([gt[3] + iy*gt[5] + gt[5]/2.0 for iy in range(ny)])

এখন অবধি , আমি সায়পাইয়ের ইন্টারপ 2 ডি ফাংশনটি চেষ্টা করেছি :

from scipy import interpolate
bilinterp = interpolate.interp2d(ax, ay, band_array, kind='linear')

তবে আমি আমার 32-বিট উইন্ডোজ সিস্টেমে 317 × 301 রাস্টার সহ একটি স্মৃতি ত্রুটি পেয়েছি:

Traceback (most recent call last):
  File "<interactive input>", line 1, in <module>
  File "C:\Python25\Lib\site-packages\scipy\interpolate\interpolate.py", line 125, in __init__
    self.tck = fitpack.bisplrep(self.x, self.y, self.z, kx=kx, ky=ky, s=0.)
  File "C:\Python25\Lib\site-packages\scipy\interpolate\fitpack.py", line 873, in bisplrep
tx,ty,nxest,nyest,wrk,lwrk1,lwrk2)
MemoryError

আমি স্বীকার করব, আমার এই সায়পাই ফাংশনে সীমিত আত্মবিশ্বাস আছে কারণ নথিবদ্ধ bounds_errorবা fill_valueপ্যারামিটারগুলি কাজ করে না। আমি দেখতে পাচ্ছি না কেন আমার মেমরির ত্রুটি হওয়া উচিত, যেহেতু আমার রাস্টারটি 317। 301, এবং বিলিনিয়ার অ্যালগরিদমটি অসুবিধা হওয়া উচিত নয়।

সাধারণত কি পাইথনে, সম্ভবত নুমপি-র সাথে উপযুক্তভাবে তৈরি করা কোনও ভাল বিলাইনার ইন্টারপোলেশন অ্যালগরিদম জুড়ে এসেছেন? কোন ইঙ্গিত বা পরামর্শ?


(দ্রষ্টব্য: নিকটতম প্রতিবেশী ইন্টারপোলেশন অ্যালগরিদম হ'ল সহজ পিঠা:

from numpy import argmin, NAN

def nearest_neighbor(px, py, no_data=NAN):
    '''Nearest Neighbor point at (px, py) on band_array
    example: nearest_neighbor(2790501.920, 6338905.159)'''
    ix = int(round((px - (gt[0] + gt[1]/2.0))/gt[1]))
    iy = int(round((py - (gt[3] + gt[5]/2.0))/gt[5]))
    if (ix < 0) or (iy < 0) or (ix > nx - 1) or (iy > ny - 1):
        return no_data
    else:
        return band_array[iy, ix]

... তবে আমি বিলিনিয়ার ইন্টারপোলেশন পদ্ধতিতে বেশি পছন্দ করি)


1
MemoryErrorNumPy আপনার এর বাইরে অ্যাক্সেস করার চেষ্টা করার কারণে আপনি পেতে পারেন band_array? আপনার চেক করা উচিত axএবং ay
Olt

1
গ্রিডটি মোটেই আবর্তিত হলে কুড়াল, আইয়ের সমস্যা হতে পারে। আপনার ইন্টারপোলিট-টু পয়েন্টগুলিকে পিক্সেল বা ডেটা স্থানাঙ্কে রূপান্তর করা ভাল। এছাড়াও, যদি তাদের সাথে অফ-ওয়ান সমস্যা হয় তবে আপনি সম্ভবত ব্যান্ডের আকারের বাইরে চলে যাচ্ছেন।
ডেভ এক্স

সঠিক, ঘোরানো গ্রিডগুলির গ্রিড-স্পেসে আবার স্থানাঙ্ক-স্পেসে রূপান্তর প্রয়োজন to এর জন্য অ্যাফাইন ট্রান্সফর্ম সহগের বিপরীত দরকার gt
মাইক টি

উত্তর:


7

আমি নীচের সূত্রটি অনুবাদ করেছি ( উইকিপিডিয়া থেকে ) পাইথন-স্পোকে নিম্নলিখিত অ্যালগরিদম তৈরি করতে, যা কাজ করে বলে মনে হচ্ছে।

from numpy import floor, NAN

def bilinear(px, py, no_data=NAN):
    '''Bilinear interpolated point at (px, py) on band_array
    example: bilinear(2790501.920, 6338905.159)'''
    ny, nx = band_array.shape
    # Half raster cell widths
    hx = gt[1]/2.0
    hy = gt[5]/2.0
    # Calculate raster lower bound indices from point
    fx = (px - (gt[0] + hx))/gt[1]
    fy = (py - (gt[3] + hy))/gt[5]
    ix1 = int(floor(fx))
    iy1 = int(floor(fy))
    # Special case where point is on upper bounds
    if fx == float(nx - 1):
        ix1 -= 1
    if fy == float(ny - 1):
        iy1 -= 1
    # Upper bound indices on raster
    ix2 = ix1 + 1
    iy2 = iy1 + 1
    # Test array bounds to ensure point is within raster midpoints
    if (ix1 < 0) or (iy1 < 0) or (ix2 > nx - 1) or (iy2 > ny - 1):
        return no_data
    # Calculate differences from point to bounding raster midpoints
    dx1 = px - (gt[0] + ix1*gt[1] + hx)
    dy1 = py - (gt[3] + iy1*gt[5] + hy)
    dx2 = (gt[0] + ix2*gt[1] + hx) - px
    dy2 = (gt[3] + iy2*gt[5] + hy) - py
    # Use the differences to weigh the four raster values
    div = gt[1]*gt[5]
    return (band_array[iy1,ix1]*dx2*dy2/div +
            band_array[iy1,ix2]*dx1*dy2/div +
            band_array[iy2,ix1]*dx2*dy1/div +
            band_array[iy2,ix2]*dx1*dy1/div)

মনে রাখবেন যে ফলাফলটি নুমপির dtype('float64')ডেটা টাইপের সাথে সংযুক্ত হওয়ায় উত্সের ডেটার চেয়ে আপাত উচ্চতর নির্ভুলতার সাথে ফিরে আসবে । .astype(band_array.dtype)আউটপুট ডেটা টাইপটিকে ইনপুট অ্যারের মতো করে তুলতে আপনি তার সাথে রিটার্ন মানটি ব্যবহার করতে পারেন ।

বিলাইনার ইন্টারপোলেশন সূত্র


3

আমি স্থানীয়ভাবে অনুরূপ ফলাফলের জন্য চেষ্টা করেছিলাম, তবে আমি একটি 64৪-বিট প্ল্যাটফর্মে আছি তাই এটি মেমরির সীমাতে না এসে আঘাত করে। সম্ভবত পরিবর্তে একবারে অ্যারের ছোট ছোট টুকরাগুলি বিভক্ত করার চেষ্টা করুন, উদাহরণস্বরূপ

আপনি জিডিএল-এর মাধ্যমে কমান্ড লাইনটি থেকে এটি করতে পারেন:

gdalwarp -ts $XSIZE*2 0 -r bilinear input.tif interp.tif

পাইথন সমতুল্য অপারেশন করতে, পুনঃপ্রয়োগ আইটেম () ব্যবহার করুন :

mem_drv = gdal.GetDriverByName('MEM')
dest = mem_drv.Create('', nx, ny, 1)

resample_by = 2
dt = (gt[0], gt[1] * resample_by, gt[2], gt[3], gt[4], gt[5] * resample_by)
dest.setGeoTransform(dt)

resampling_method = gdal.GRA_Bilinear    
res = gdal.ReprojectImage(source, dest, None, None, resampling_method)

# then, write the result to a file of your choice...    

আমার পয়েন্ট ডেটা যা আমি ইন্টারপোল্ট করতে চাই তা নিয়মিতভাবে ব্যবধানে থাকে না, তাই আমি জিডিএল এর অন্তর্নির্মিত ReprojectImageকৌশলটি ব্যবহার করতে পারি না ।
মাইক টি

1

আমার অতীতে হুবুহু সমস্যা ছিল এবং আমি ইন্টারপোলেট.আইন্টারপি 2 ডি ব্যবহার করে এর সমাধান করিনি। আমি scipy.ndimage.map_coordinates ব্যবহার করে সাফল্য পেয়েছি । নিম্নলিখিত চেষ্টা করুন:

scipy.ndimage.map_coordinates (ব্যান্ড_আরে, [কুড়াল, আই]], অর্ডার = 1)

এটি বিলিনিয়ার হিসাবে একই আউটপুট দেয় বলে মনে হচ্ছে।


আমি এটির দ্বারা কিছুটা ছুঁড়ে ফেলেছি, কারণ উত্স রাস্টার স্থানাঙ্কগুলি কীভাবে ব্যবহৃত হবে (পিক্সেল স্থানাঙ্কগুলি ব্যবহার না করে) কীভাবে ব্যবহার করা যায় তা আমি নিশ্চিত ure আমি দেখতে পাই এটি অনেক পয়েন্ট সমাধানের জন্য "ভেক্টরাইজড" "
মাইক টি

রাজি হয়েছি, আমি আসলেই স্কিপি বুঝতে পারি না। আপনার অদ্ভুত সমাধান আরও ভাল।
ম্যাথু স্নেপ

0

scipy.interpolate.interp2d () আরও আধুনিক স্কিপির সাথে দুর্দান্ত কাজ করে। আমি মনে করি পুরানো সংস্করণগুলি অনিয়মিত গ্রিডগুলি ধরে নিয়েছে এবং নিয়মিত গ্রিডগুলির সুবিধা নেবে না। আপনি স্কিপি দিয়ে যেমন করেন তেমনি ত্রুটিও পেয়েছি। সংস্করণ = 0.11.0, কিন্তু স্কিপি উপর। সংস্করণ = 0.14.0, এটি আনন্দের সাথে কিছু 1600x1600 মডেলের আউটপুটটিতে কাজ করে।

আপনার প্রশ্নের ইঙ্গিতগুলির জন্য আপনাকে ধন্যবাদ।

#!/usr/bin/env python

from osgeo import gdal
from numpy import array
import argparse

parser = argparse.ArgumentParser()
parser.add_argument("filename",help='raster file from which to interpolate a (1/3,1/3) point from from')
args = parser.parse_args()

# Read raster
source = gdal.Open(args.filename)
nx, ny = source.RasterXSize, source.RasterYSize
gt = source.GetGeoTransform()
band_array = source.GetRasterBand(1).ReadAsArray()
# Close raster
source = None

# Compute mid-point grid spacings
ax = array([gt[0] + ix*gt[1] + gt[1]/2.0 for ix in range(nx)])
ay = array([gt[3] + iy*gt[5] + gt[5]/2.0 for iy in range(ny)])

from scipy import interpolate
bilinterp = interpolate.interp2d(ax, ay, band_array, kind='linear')

x1 = gt[0] + gt[1]*nx/3
y1 = gt[3] + gt[5]*ny/3.

print(nx, ny, x1,y1,bilinterp(x1,y1))

####################################

$ time ./interp2dTesting.py test.tif 
(1600, 1600, -76.322, 30.70889, array([-8609.27777778]))

real    0m4.086s
user    0m0.590s
sys 0m0.252s
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.