利用Python裁切tiff图像且读取tiff,shp文件的实例


Posted in Python onMarch 10, 2020

我就废话不多说了,还是直接看代码吧!

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 #栅格矩阵的列数
  im_height = dataset.RasterYSize #栅格矩阵的行数
  im_bands = dataset.RasterCount #波段数
  band1=dataset.GetRasterBand(1)
  print(band1)
  print ('Band Type=',gdal.GetDataTypeName(band1.DataType))
  im_data = dataset.ReadAsArray(0,0,im_width,im_height)#获取数据
  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文件函数
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
    #创建文件
  driver = gdal.GetDriverByName("GTiff")
  dataset = driver.Create(path, im_width, im_height, im_bands, datatype)
  if(dataset!= None):
    dataset.SetGeoTransform(im_geotrans) #写入仿射变换参数
    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影像图和转换成png格式+裁剪Png图片

先来看一下需要转换的tiff原始图的信息,如下图所示。

利用Python裁切tiff图像且读取tiff,shp文件的实例

tiff转换成png和裁剪tiff的代码(opencv)

import cv2 as cv
import os

"""
  转换tiff格式为png + 横向裁剪tiff遥感影像图
"""
def Convert_To_Png_AndCut(dir):
  files = os.listdir(dir)
  ResultPath1 = "./RS_ToPngDir/" # 定义转换格式后的保存路径
  ResultPath2 = "./RS_Cut_Result/" # 定义裁剪后的保存路径
  ResultPath3 = "./RS_Cut_Result/" # 定义裁剪后的保存路径
  for file in files: # 这里可以去掉for循环
    a, b = os.path.splitext(file) # 拆分影像图的文件名称
    this_dir = os.path.join(dir + file) # 构建保存 路径+文件名
    
    img = cv.imread(this_dir, 1) # 读取tif影像
    # 第二个参数是通道数和位深的参数,
    # IMREAD_UNCHANGED = -1 # 不进行转化,比如保存为了16位的图片,读取出来仍然为16位。
    # IMREAD_GRAYSCALE = 0 # 进行转化为灰度图,比如保存为了16位的图片,读取出来为8位,类型为CV_8UC1。
    # IMREAD_COLOR = 1  # 进行转化为RGB三通道图像,图像深度转为8位
    # IMREAD_ANYDEPTH = 2 # 保持图像深度不变,进行转化为灰度图。
    # IMREAD_ANYCOLOR = 4 # 若图像通道数小于等于3,则保持原通道数不变;若通道数大于3则只取取前三个通道。图像深度转为8位
    
    cv.imwrite(ResultPath1 + a + "_" + ".png", img) # 保存为png格式
    
    # 下面开始裁剪-不需要裁剪tiff格式的可以直接注释掉
    hight = img.shape[0] #opencv写法,获取宽和高
    width = img.shape[1]
    #定义裁剪尺寸
    w = 480 # 宽度
    h = 360 # 高度
    _id = 1 # 裁剪结果保存文件名: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(ResultPath2 + 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 # 裁剪结果保存文件名: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)

将转换成png后的图加载到软件中(专业软件ENVI5.3)查看结果详细信息如下图所示,成功的转换成png格式了。

利用Python裁切tiff图像且读取tiff,shp文件的实例

下面是加载裁剪后的影像图(Tiff格式的)

利用Python裁切tiff图像且读取tiff,shp文件的实例

def toCutPng(dir):函数效果图如下图所示。

以上这篇利用Python裁切tiff图像且读取tiff,shp文件的实例就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Python 相关文章推荐
深入理解python try异常处理机制
Jun 01 Python
Python 爬虫学习笔记之单线程爬虫
Sep 21 Python
python中hashlib模块用法示例
Oct 30 Python
对python模块中多个类的用法详解
Jan 10 Python
浅谈Python小波分析库Pywavelets的一点使用心得
Jul 09 Python
python自动循环定时开关机(非重启)测试
Aug 26 Python
python制作英语翻译小工具代码实例
Sep 09 Python
python GUI库图形界面开发之PyQt5不规则窗口实现与显示GIF动画的详细方法与实例
Mar 09 Python
Python 随机按键模拟2小时
Dec 30 Python
Django+Django-Celery+Celery的整合实战
Jan 20 Python
Python爬虫之爬取某文库文档数据
Apr 21 Python
Python操作CSV格式文件的方法大全
Jul 15 Python
GDAL 矢量属性数据修改方式(python)
Mar 10 #Python
使用Python开发个京东上抢口罩的小实例(仅作技术研究学习使用)
Mar 10 #Python
python 获取当前目录下的文件目录和文件名实例代码详解
Mar 10 #Python
python爬虫开发之使用Python爬虫库requests多线程抓取猫眼电影TOP100实例
Mar 10 #Python
Django 404、500页面全局配置知识点详解
Mar 10 #Python
python使用gdal对shp读取,新建和更新的实例
Mar 10 #Python
Python实现获取当前目录下文件名代码详解
Mar 10 #Python
You might like
教你如何用php实现LOL数据远程获取
2014/06/10 PHP
ThinkPHP视图查询详解
2014/06/30 PHP
PHP输出两个数字中间有多少个回文数的方法
2015/03/23 PHP
PHP引用的调用方法分析
2016/04/25 PHP
php文件上传后端处理小技巧
2016/05/22 PHP
php 截取utf-8格式的字符串实例代码
2016/10/30 PHP
Extjs学习过程中新手容易碰到的低级错误积累
2010/02/11 Javascript
限制textbox或textarea输入字符长度的JS代码
2013/10/16 Javascript
js在数组中删除重复的元素自保留一个(两种实现思路)
2014/08/22 Javascript
JS中自定义定时器让它在某一时刻执行
2014/09/02 Javascript
jquery获取文档高度和窗口高度汇总
2016/01/25 Javascript
jquery获取所有选中的checkbox实现代码
2016/05/26 Javascript
js H5 canvas投篮小游戏
2016/08/18 Javascript
js实现常见的工具条效果
2017/03/02 Javascript
详解Puppeteer 入门教程
2018/05/09 Javascript
Mint UI实现A-Z字母排序的城市选择列表
2018/12/28 Javascript
Vue页面刷新记住页面状态的实现
2019/12/27 Javascript
js实现验证码功能
2020/07/24 Javascript
基于vue项目设置resolves.alias: '@'路径并适配webstorm
2020/12/02 Vue.js
[45:52]完美世界DOTA2联赛PWL S3 Forest vs INK ICE 第二场 12.09
2020/12/12 DOTA
Python fileinput模块使用实例
2015/05/28 Python
解决Python中字符串和数字拼接报错的方法
2016/10/23 Python
Python入门_浅谈数据结构的4种基本类型
2017/05/16 Python
python如何拆分含有多种分隔符的字符串
2018/03/20 Python
Python RabbitMQ消息队列实现rpc
2018/05/30 Python
python进程间通信Queue工作过程详解
2019/11/01 Python
浅谈pandas.cut与pandas.qcut的使用方法及区别
2020/03/03 Python
如何理解Python中的变量
2020/06/01 Python
CSS超出文本指定宽度用省略号代替和文本不换行
2016/05/05 HTML / CSS
Timex手表官网:美国运动休闲手表品牌
2017/01/28 全球购物
卡拉威高尔夫官方网站:Callaway Golf
2020/09/16 全球购物
公司经理任命书
2014/06/05 职场文书
医院标语大全
2014/06/23 职场文书
争当四好少年演讲稿
2014/09/13 职场文书
教师自查自纠工作情况报告
2014/10/29 职场文书
golang switch语句的灵活写法介绍
2021/05/06 Golang