当前位置:   article > 正文

Python 使用矢量数据对栅格进行裁剪_python用某一个矢量裁剪栅格数据

python用某一个矢量裁剪栅格数据

参考:GeospatialPython.com: Clip a Raster using a Shapefile

1. 主要步骤

  • 将矢量的shapefile转化为mask数组;
  • 加载栅格影像数据;
  • 舍弃shapefile边界范围外的所有像元;
  • 将shapefile范围外的所有像元值设置为NODATA;
  • 可选步骤:对影像采用直方图拉伸,便于可视化
  • 将裁剪后的影像保存为新的栅格数据

2. 工具

  • GDAL:处理栅格数据
  • Numpy:大型的多维数组运算
  • PIL:便于影像与数组的相互转换

3. 代码

  1. import operator
  2. from cv2 import reduce
  3. from osgeo import gdal, gdalnumeric, ogr, osr
  4. import Image, ImageDraw
  5. # 将栅格影像数据转化为数组
  6. def imageToArray(img_file):
  7. arr = gdalnumeric.fromstring(img_file.tostring(), 'b')
  8. arr.shape = img_file.im.size[1], img_file.im.size[0]
  9. return arr
  10. # 将数组转化为栅格影像
  11. def arrayToImage(arr):
  12. img = Image.fromstring('L', (arr.shape[1], arr.shape[0]),
  13. (arr.astype('b')).tostring())
  14. return img
  15. # 计算像元的地理坐标信息
  16. def world2Pixel(geoMatrix, x, y):
  17. ulX = geoMatrix[0]
  18. ulY = geoMatrix[3]
  19. xDist = geoMatrix[1]
  20. yDist = geoMatrix[5]
  21. rtnX = geoMatrix[2]
  22. rtnY = geoMatrix[4]
  23. pixel = int((x - ulX) / xDist)
  24. line = int((ulY - y) / yDist)
  25. return pixel, line
  26. # 多维数组的直方图变换函数
  27. def histogram(arr, bins=range(0, 256)):
  28. """
  29. :parameter arr: 输入的数组
  30. :parameter bins:直方图变换的输出范围
  31. """
  32. fa = arr.flat
  33. n = gdalnumeric.searchsorted(gdalnumeric.sort(fa), bins)
  34. n = gdalnumeric.concatenate([n, [len(fa)]])
  35. hist = n[1:] - n[:-1]
  36. return hist
  37. # 直方图拉伸
  38. def stretch(arr):
  39. hist = histogram(arr)
  40. im = arrayToImage(arr)
  41. lut = []
  42. for b in range(0, len(hist), 256):
  43. # step size
  44. step = reduce(operator.add, hist[b:b + 256]) / 255
  45. # create equalization lookup table
  46. n = 0
  47. for i in range(256):
  48. lut.append(n / step)
  49. n = n + hist[i + b]
  50. im = im.point(lut)
  51. return imageToArray(im)
  52. if __name__ == "__main__":
  53. raster_file = "ras_test.tif" # 待裁剪的栅格影像
  54. shp_file = "county" # 用于裁剪的矢量数据
  55. output_file = "ras_clip" # 裁剪输出后的数据
  56. srcArray = gdalnumeric.LoadFile(raster_file) # 加载数据
  57. srcImage = gdal.Open(raster_file) # 获取投影等地理信息
  58. geoTrans = srcImage.GetGeoTransform()
  59. shape_file = ogr.Open("%s.shp" % shp_file)
  60. lyr = shape_file.GetLayer(shp_file)
  61. poly = lyr.GetNextFeature()
  62. # 将layer的坐标信息转换为与栅格数据一致,并计算新影像的像元大小
  63. minX, maxX, minY, maxY = lyr.GetExtent()
  64. ulX, ulY = world2Pixel(geoTrans, minX, maxY)
  65. lrX, lrY = world2Pixel(geoTrans, maxX, minY)
  66. pxWidth = int(lrX - ulX)
  67. pxHeight = int(lrY - ulY)
  68. clip = srcArray[:, ulY:lrY, ulX:lrX]
  69. geoTrans = list(geoTrans)
  70. geoTrans[0] = minX
  71. geoTrans[3] = maxY
  72. # 制作mask数据
  73. points = []
  74. pixels = []
  75. geom = poly.GetGeometryRef()
  76. pts = geom.GetGeometryRef(0)
  77. for p in range(pts.GetPointCount()):
  78. points.append((pts.GetX(p), pts.GetY(p)))
  79. for p in points:
  80. pixels.append(world2Pixel(geoTrans, p[0], p[1]))
  81. rasterPoly = Image.new("L", (pxWidth, pxHeight), 1)
  82. rasterize = ImageDraw.Draw(rasterPoly)
  83. rasterize.polygon(pixels, 0)
  84. mask = imageToArray(rasterPoly)
  85. # 使用mask裁剪影像
  86. clip = gdalnumeric.choose(mask, (clip, 0)).astype(gdalnumeric.uint8)
  87. # 对3波段的数据进行拉伸
  88. for i in range(3):
  89. clip[i, :, :] = stretch(clip[i, :, :])
  90. # 将裁剪后的数据存为tif格式
  91. gdalnumeric.SaveArray(clip, "%s.tif" % output_file, format="GTiff", prototype=raster_file)
  92. # 将裁剪后的数据存为8bit的jpeg格式
  93. clip = clip.astype(gdalnumeric.uint8)
  94. gdalnumeric.SaveArray(clip, "%s.jpg" % output_file, format="JPEG")

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/笔触狂放9/article/detail/208245
推荐阅读
相关标签
  

闽ICP备14008679号