溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

怎么利用Python裁切tiff圖像且讀取tiff,shp文件

發(fā)布時間:2021-04-25 11:02:20 來源:億速云 閱讀:1107 作者:小新 欄目:開發(fā)技術

這篇文章主要介紹了怎么利用Python裁切tiff圖像且讀取tiff,shp文件,具有一定借鑒價值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。

Python的優(yōu)點有哪些

1、簡單易用,與C/C++、Java、C# 等傳統(tǒng)語言相比,Python對代碼格式的要求沒有那么嚴格;2、Python屬于開源的,所有人都可以看到源代碼,并且可以被移植在許多平臺上使用;3、Python面向?qū)ο?,能夠支持面向過程編程,也支持面向?qū)ο缶幊蹋?、Python是一種解釋性語言,Python寫的程序不需要編譯成二進制代碼,可以直接從源代碼運行程序;5、Python功能強大,擁有的模塊眾多,基本能夠?qū)崿F(xiàn)所有的常見功能。

具體代碼如下

from osgeo import gdal, gdalnumeric, ogr
from PIL import Image, ImageDraw
from osgeo import gdal_array
import os
import operator
from functools import reduce
gdal.UseExceptions()
 

def readTif(fileName):
  dataset = gdal.Open(fileName)
  if dataset == None:
    print(fileName+"文件無法打開")
    return
  im_width = dataset.RasterXSize #柵格矩陣的列數(shù)
  im_height = dataset.RasterYSize #柵格矩陣的行數(shù)
  im_bands = dataset.RasterCount #波段數(shù)
  band1=dataset.GetRasterBand(1)
  print(band1)
  print ('Band Type=',gdal.GetDataTypeName(band1.DataType))
  im_data = dataset.ReadAsArray(0,0,im_width,im_height)#獲取數(shù)據(jù)
  im_geotrans = dataset.GetGeoTransform()#獲取仿射矩陣信息
  im_proj = dataset.GetProjection()#獲取投影信息
  im_blueBand = im_data[0,0:im_height,0:im_width]#獲取藍波段
  im_greenBand = im_data[1,0:im_height,0:im_width]#獲取綠波段
  im_redBand =  im_data[2,0:im_height,0:im_width]#獲取紅波段
  im_nirBand = im_data[3,0:im_height,0:im_width]#獲取近紅外波段

  return(im_width,im_height,im_bands,im_data,im_geotrans
      ,im_proj,im_blueBand,im_greenBand,im_redBand,im_nirBand)

#保存tif文件函數(shù)
import gdal
import numpy as np
def writeTiff(im_data,im_width,im_height,im_bands,im_geotrans,im_proj,path):
  if 'int8' in im_data.dtype.name:
    datatype = gdal.GDT_Byte
  elif 'int16' in im_data.dtype.name:
    datatype = gdal.GDT_UInt16
  else:
    datatype = gdal.GDT_Float32

  if len(im_data.shape) == 3:
    im_bands, im_height, im_width = im_data.shape
  elif len(im_data.shape) == 2:
    im_data = np.array([im_data])
  else:
    im_bands, (im_height, im_width) = 1,im_data.shape
    #創(chuàng)建文件
  driver = gdal.GetDriverByName("GTiff")
  dataset = driver.Create(path, im_width, im_height, im_bands, datatype)
  if(dataset!= None):
    dataset.SetGeoTransform(im_geotrans) #寫入仿射變換參數(shù)
    dataset.SetProjection(im_proj) #寫入投影
  for i in range(im_bands):
    dataset.GetRasterBand(i+1).WriteArray(im_data[i])
  del dataset
 
# This function will convert the rasterized clipper shapefile
# to a mask for use within GDAL.
def imageToArray(i):
  """
  Converts a Python Imaging Library array to a
  gdalnumeric image.
  """
  a=gdalnumeric.fromstring(i.tobytes(),'b')
  a.shape=i.im.size[1], i.im.size[0]
  return a

 
def arrayToImage(a):
  """
  Converts a gdalnumeric array to a
  Python Imaging Library Image.
  """
  i=Image.frombytes('L',(a.shape[1],a.shape[0]),
      (a.astype('b')).tobytes())
  return i
 
def world2Pixel(geoMatrix, x, y):
  """
  Uses a gdal geomatrix (gdal.GetGeoTransform()) to calculate
  the pixel location of a geospatial coordinate
  """
  ulX = geoMatrix[0]
  ulY = geoMatrix[3]
  xDist = geoMatrix[1]
  pixel = int((x - ulX) / xDist)
  line = int((ulY - y) / xDist)
  return (pixel, line)
 
#
# EDIT: this is basically an overloaded
# version of the gdal_array.OpenArray passing in xoff, yoff explicitly
# so we can pass these params off to CopyDatasetInfo
#
def OpenArray( array, prototype_ds = None, xoff=0, yoff=0 ):
  ds =gdal_array.OpenArray(array)
 
  if ds is not None and prototype_ds is not None:
    if type(prototype_ds).__name__ == 'str':
      prototype_ds = gdal.Open( prototype_ds )
    if prototype_ds is not None:
      gdalnumeric.CopyDatasetInfo( prototype_ds, ds, xoff=xoff, yoff=yoff )
  return ds

def histogram(a, bins=range(0,256)):
  """
  Histogram function for multi-dimensional array.
  a = array
  bins = range of numbers to match
  """
  fa = a.flat
  n = gdalnumeric.searchsorted(gdalnumeric.sort(fa), bins)
  n = gdalnumeric.concatenate([n, [len(fa)]])
  hist = n[1:]-n[:-1]
  return hist
 
def stretch(a):
  """
  Performs a histogram stretch on a gdalnumeric array image.
  """
  hist = histogram(a)
  im = arrayToImage(a)
  lut = []
  for b in range(0, len(hist), 256):
    # step size
    step = reduce(operator.add, hist[b:b+256]) / 255
    # create equalization lookup table
    n = 0
    for i in range(256):
      lut.append(n / step)
      n = n + hist[i+b]
    im = im.point(lut)
  return imageToArray(im)
 
def main( shapefile_path, raster_path ):
  # Load the source data as a gdalnumeric array
  srcArray = gdalnumeric.LoadFile(raster_path)
 
  # Also load as a gdal image to get geotransform
  # (world file) info
  srcImage = gdal.Open(raster_path)
  geoTrans = srcImage.GetGeoTransform()
 
  # Create an OGR layer from a boundary shapefile
  shapef = ogr.Open(shapefile_path)
  lyr = shapef.GetLayer( os.path.split( os.path.splitext( shapefile_path )[0] )[1] )
  poly = lyr.GetNextFeature()
 
  # Convert the layer extent to image pixel coordinates
  minX, maxX, minY, maxY = lyr.GetExtent()
  ulX, ulY = world2Pixel(geoTrans, minX, maxY)
  lrX, lrY = world2Pixel(geoTrans, maxX, minY)
 
  # Calculate the pixel size of the new image
  pxWidth = int(lrX - ulX)
  pxHeight = int(lrY - ulY)
 
  clip = srcArray[:, ulY:lrY, ulX:lrX]
 
  #
  # EDIT: create pixel offset to pass to new image Projection info
  #
  xoffset = ulX
  yoffset = ulY
  print ("Xoffset, Yoffset = ( %f, %f )" % ( xoffset, yoffset ))
 
  # Create a new geomatrix for the image
  geoTrans = list(geoTrans)
  geoTrans[0] = minX
  geoTrans[3] = maxY
 
  # Map points to pixels for drawing the
  # boundary on a blank 8-bit,
  # black and white, mask image.
  points = []
  pixels = []
  geom = poly.GetGeometryRef()
  pts = geom.GetGeometryRef(0)
  for p in range(pts.GetPointCount()):
   points.append((pts.GetX(p), pts.GetY(p)))
  for p in points:
   pixels.append(world2Pixel(geoTrans, p[0], p[1]))
  rasterPoly = Image.new("L", (pxWidth, pxHeight), 1)
  rasterize = ImageDraw.Draw(rasterPoly)
  rasterize.polygon(pixels, 0)
  mask = imageToArray(rasterPoly)
 
  # Clip the image using the mask
  clip = gdalnumeric.choose(mask, \
    (clip, 0)).astype(gdalnumeric.uint8)
 
  # This image has 3 bands so we stretch each one to make them
  # visually brighter
  for i in range(4):
   clip[i,:,:] = stretch(clip[i,:,:])
 
  # Save new tiff
  #
  # EDIT: instead of SaveArray, let's break all the
  # SaveArray steps out more explicity so
  # we can overwrite the offset of the destination
  # raster
  #
  ### the old way using SaveArray
  #
  # gdalnumeric.SaveArray(clip, "OUTPUT.tif", format="GTiff", prototype=raster_path)
  #
  ###
  #
  gtiffDriver = gdal.GetDriverByName( 'GTiff' )
  if gtiffDriver is None:
    raise ValueError("Can't find GeoTiff Driver")
  gtiffDriver.CreateCopy( "beijing1.tif",
    OpenArray( clip, prototype_ds=raster_path, xoff=xoffset, yoff=yoffset )
  )
  print(raster_path)
   
  # Save as an 8-bit jpeg for an easy, quick preview
  clip = clip.astype(gdalnumeric.uint8)
  gdalnumeric.SaveArray(clip, "beijing1.jpg", format="JPEG")
 
  gdal.ErrorReset()

 
if __name__ == '__main__': 
  #shapefile_path, raster_path 
  shapefile_path = r'C:\Users\Administrator\Desktop\裁切shp\New_Shapefile.shp' 
  raster_path = r'C:\Users\Administrator\Desktop\2230542.tiff' 
   
  main( shapefile_path, raster_path )

補充知識:python代碼裁剪tiff影像圖和轉(zhuǎn)換成png格式+裁剪Png圖片

先來看一下需要轉(zhuǎn)換的tiff原始圖的信息,如下圖所示。

怎么利用Python裁切tiff圖像且讀取tiff,shp文件

tiff轉(zhuǎn)換成png和裁剪tiff的代碼(opencv)

import cv2 as cv
import os

"""
  轉(zhuǎn)換tiff格式為png + 橫向裁剪tiff遙感影像圖
"""
def Convert_To_Png_AndCut(dir):
  files = os.listdir(dir)
  ResultPath2 = "./RS_ToPngDir/" # 定義轉(zhuǎn)換格式后的保存路徑
  ResultPath3 = "./RS_Cut_Result/" # 定義裁剪后的保存路徑
  ResultPath4 = "./RS_Cut_Result/" # 定義裁剪后的保存路徑
  for file in files: # 這里可以去掉for循環(huán)
    a, b = os.path.splitext(file) # 拆分影像圖的文件名稱
    this_dir = os.path.join(dir + file) # 構(gòu)建保存 路徑+文件名
    
    img = cv.imread(this_dir, 1) # 讀取tif影像
    # 第二個參數(shù)是通道數(shù)和位深的參數(shù),
    # IMREAD_UNCHANGED = -1 # 不進行轉(zhuǎn)化,比如保存為了16位的圖片,讀取出來仍然為16位。
    # IMREAD_GRAYSCALE = 0 # 進行轉(zhuǎn)化為灰度圖,比如保存為了16位的圖片,讀取出來為8位,類型為CV_8UC1。
    # IMREAD_COLOR = 1  # 進行轉(zhuǎn)化為RGB三通道圖像,圖像深度轉(zhuǎn)為8位
    # IMREAD_ANYDEPTH = 2 # 保持圖像深度不變,進行轉(zhuǎn)化為灰度圖。
    # IMREAD_ANYCOLOR = 4 # 若圖像通道數(shù)小于等于3,則保持原通道數(shù)不變;若通道數(shù)大于3則只取取前三個通道。圖像深度轉(zhuǎn)為8位
    
    cv.imwrite(ResultPath2 + a + "_" + ".png", img) # 保存為png格式
    
    # 下面開始裁剪-不需要裁剪tiff格式的可以直接注釋掉
    hight = img.shape[0] #opencv寫法,獲取寬和高
    width = img.shape[1]
    #定義裁剪尺寸
    w = 480 # 寬度
    h = 360 # 高度
    _id = 1 # 裁剪結(jié)果保存文件名:0 - N 升序方式
    i = 0
    while (i + h <= hight): # 控制高度,圖像多余固定尺寸總和部分不要了
      j = 0
      while (j + w <= width):  # 控制寬度,圖像多余固定尺寸總和部分不要了
        cropped = img[i:i + h, j:j + w] # 裁剪坐標為[y0:y1, x0:x1]
        cv.imwrite(ResultPath3 + a + "_" + str(_id) + b, cropped)
        _id += 1
        j += w
      i = i + h
"""
  橫向裁剪PNG圖
"""
def toCutPng(dir):
  files = os.listdir(dir)
  ResultPath = "./RS_CutPng_Result/" # 定義裁剪后的保存路徑
  for file in files:
    a, b = os.path.splitext(file) # 拆分影像圖的文件名稱
    this_dir = os.path.join(dir + file)
    img = Image.open(this_dir) # 按順序打開某圖片
    width, hight = img.size
    w = 480 # 寬度
    h = 360 # 高度
    _id = 1 # 裁剪結(jié)果保存文件名:0 - N 升序方式
    y = 0
    while (y + h <= hight): # 控制高度,圖像多余固定尺寸總和部分不要了
      x = 0
      while (x + w <= width):  # 控制寬度,圖像多余固定尺寸總和部分不要了
        new_img = img.crop((x, y, x + w, y + h))
        new_img.save(ResultPath + a + "_" + str(_id) + b)
        _id += 1
        x += w
      y = y + h

if __name__ == '__main__':
  _path = r"./RS_TiffDir/"  # 遙感tiff影像所在路徑
  # 裁剪影像圖
  Convert_To_Png_AndCut(_path)

將轉(zhuǎn)換成png后的圖加載到軟件中(專業(yè)軟件ENVI5.3)查看結(jié)果詳細信息如下圖所示,成功的轉(zhuǎn)換成png格式了。

怎么利用Python裁切tiff圖像且讀取tiff,shp文件

下面是加載裁剪后的影像圖(Tiff格式的)

怎么利用Python裁切tiff圖像且讀取tiff,shp文件

def toCutPng(dir):函數(shù)效果圖如下圖所示。

感謝你能夠認真閱讀完這篇文章,希望小編分享的“怎么利用Python裁切tiff圖像且讀取tiff,shp文件”這篇文章對大家有幫助,同時也希望大家多多支持億速云,關注億速云行業(yè)資訊頻道,更多相關知識等著你來學習!

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI