การประมวลผลภาพโดยใช้ Python, GDAL และ Scikit-Image


11

ฉันกำลังดิ้นรนกับการประมวลผลและหวังว่าฉันจะสามารถแก้ไขได้ที่นี่

ฉันทำงานกับ Remote Sensing ที่ใช้กับการป่าไม้โดยเฉพาะการทำงานกับข้อมูล LiDAR แนวคิดคือการใช้ Scikit-image สำหรับการตรวจจับต้นไม้ด้านบน เนื่องจากฉันใหม่ใน Python ฉันถือว่าชัยชนะส่วนตัวที่ยอดเยี่ยมในการทำสิ่งต่อไปนี้:

  1. นำเข้า CHM (พร้อม matplotlib);
  2. เรียกใช้ตัวกรอง Gaussian (พร้อมแพ็คเกจ scikit-image);
  3. เรียกใช้ตัวกรอง maxima (พร้อมแพ็คเกจ scikit-image);
  4. รัน peak_local_max (พร้อมแพ็กเกจ scikit-image);
  5. แสดง CHM ​​ด้วย maxima ท้องถิ่น (พร้อม matplotlib);

ตอนนี้ปัญหาของฉัน เมื่อฉันนำเข้าด้วย matplot รูปภาพจะสูญเสียพิกัดทางภูมิศาสตร์ ดังนั้นพิกัดที่ฉันมีจึงเป็นเพียงพิกัดรูปภาพพื้นฐาน (เช่น 250,312) สิ่งที่ฉันต้องการคือการรับค่าของพิกเซลภายใต้จุดสูงสุดในภาพ (จุดสีแดงในภาพ) ที่นี่ในฟอรัมฉันเห็นชายคนหนึ่งถามสิ่งเดียวกัน ( รับค่าพิกเซลของแรสเตอร์ GDAL ภายใต้จุด OGR โดยไม่มี NumPy? ) แต่เขามีคะแนนในรูปร่างไฟล์อยู่แล้ว ในกรณีของฉันคะแนนถูกคำนวณด้วยรูปภาพ scikit (เป็นอาร์เรย์ที่มีพิกัดของต้นไม้แต่ละต้น) ดังนั้นฉันไม่มี shapefile

โดยสรุปสิ่งที่ฉันต้องการในท้ายที่สุดคือไฟล์ txt พร้อมพิกัดของแต่ละ maxima ท้องถิ่นในพิกัดทางภูมิศาสตร์ตัวอย่างเช่น

525412 62980123 1150 ...

Local maxima (จุดสีแดง) ใน CHM

คำตอบ:


11

ประการแรกยินดีต้อนรับสู่เว็บไซต์!

อาร์เรย์ Numpy ไม่มีแนวคิดของระบบพิกัดที่รวมอยู่ในอาร์เรย์ สำหรับแรสเตอร์ 2D จะมีการทำดัชนีโดยคอลัมน์และแถว

หมายเหตุ:ฉันทำสมมติฐานที่ว่าคุณกำลังอ่านรูปแบบแรสเตอร์ที่GDAL สนับสนุน

ใน Python วิธีที่ดีที่สุดในการนำเข้าข้อมูล raster เชิงพื้นที่อยู่ในrasterioแพ็คเกจ ข้อมูลดิบที่นำเข้าโดย rasterio ยังคงเป็น numpy array โดยไม่ต้องเข้าถึงระบบพิกัด แต่ rasterio ยังให้คุณเข้าถึงวิธีเลียนแบบบนอาร์เรย์ต้นทางซึ่งคุณสามารถใช้เพื่อแปลงคอลัมน์และแถวแรสเตอร์เป็นพิกัดที่ฉายไว้ ตัวอย่างเช่น:

import rasterio

# The best way to open a raster with rasterio is through the context manager
# so that it closes automatically

with rasterio.open(path_to_raster) as source:

    data = source.read(1) # Read raster band 1 as a numpy array
    affine = source.affine

# ... do some work with scikit-image and get an array of local maxima locations
# e.g.
# maxima = numpy.array([[0, 0], [1, 1], [2, 2]])
# Also note that convention in a numy array for a 2d array is rows (y), columns (x)

for point in maxima: #Loop over each pair of coordinates
    column = point[1]
    row = point[0]
    x, y = affine * (column, row)
    print x, y

# Or you can do it all at once:

columns = maxima[:, 1]
rows = maxima[:, 0]

xs, ys = affine * (columns, rows)

และจากตรงนั้นคุณสามารถเขียนผลลัพธ์ของเราลงในไฟล์ข้อความได้ตามต้องการ (ฉันขอแนะนำให้ดูที่โมดูลinbuiltcsvเป็นต้น)


ขอบคุณมาก. ดูเหมือนว่านี่อาจจะใช้ได้ ตั้งแต่ฉันใหม่ที่นี้ฉันยังคงต้องทำความคุ้นเคยกับสิ่งต่าง ๆ มากมาย ขอบคุณสำหรับความอดทน
João Paulo Pereira

1
ใน Rasterio 1.x คุณสามารถใช้ source.xy (แถว, คอลัมน์) เพื่อรับพิกัดทางภูมิศาสตร์
bugmenot123

0

จากการดูอย่างรวดเร็วที่ matplotlib ผมว่าคุณต้องเปลี่ยนสเกลของแกนหลังจากการนำเข้า


ฉันคิดว่าปัญหาอยู่ในภาพ scikit เมื่อฉันรันมัน scikit จะเปลี่ยนเป็นพิกัดภาพโดยอัตโนมัติ
João Paulo Pereira

0

โปรดลองด้วยรหัสต่อไปนี้ นี้สามารถใช้ในการอ่านข้อมูลภาพจากแรสเตอร์และเขียนข้อมูลการประมวลผลไปยังแรสเตอร์ (ไฟล์. regotiff)

from PIL import Image,ImageOps
import numpy as np
from osgeo import gdal
#from osgeo import gdal_array
#from osgeo import osr
#from osgeo.gdalconst import *
#import matplotlib.pylab as plt

#from PIL import Image, ImageOps
#import gdal
#from PIL import Image
gdal.AllRegister()

################## Read Raster #################
inRaster='C:\python\Results\Database\Risat1CRS\CRS_LEVEL2_GEOTIFF\scene_HH\imagery_HH.tif'

inDS=gdal.Open(inRaster,1)
geoTransform = inDS.GetGeoTransform()
band=inDS.GetRasterBand(1)
datatype=band.DataType
proj = inDS.GetProjection()
rows = inDS.RasterYSize
cols=inDS.RasterXSize
data=band.ReadAsArray(0,0,cols,rows)#extraction of data to be processed#
############write raster##########
driver=inDS.GetDriver()
outRaster='C:\\python\\Results\\Database\\Temporary data base\\clipped_26July2017\\demo11.tif'
outDS = driver.Create(outRaster, cols,rows, 1,datatype)
geoTransform = inDS.GetGeoTransform()
outDS.SetGeoTransform(geoTransform)
proj = inDS.GetProjection()
outDS.SetProjection(proj)
outBand = outDS.GetRasterBand(1)
outBand.WriteArray(data1,0,0)
#data is the output array to written in tiff file
outDS=None 
im2=Image.open('C:\\python\\Results\\Database\\Temporary data base\\clipped_26July2017\\demo11.tif');
im2.show()
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.