利用Python裁切tiff圖像且讀取tiff,shp文件的實(shí)例
我就廢話不多說了,還是直接看代碼吧!
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]#獲取藍(lán)波段
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 )
補(bǔ)充知識(shí):python代碼裁剪tiff影像圖和轉(zhuǎn)換成png格式+裁剪Png圖片
先來看一下需要轉(zhuǎn)換的tiff原始圖的信息,如下圖所示。

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)
ResultPath1 = "./RS_ToPngDir/" # 定義轉(zhuǎn)換格式后的保存路徑
ResultPath2 = "./RS_Cut_Result/" # 定義裁剪后的保存路徑
ResultPath3 = "./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影像
# 第二個(gè)參數(shù)是通道數(shù)和位深的參數(shù),
# IMREAD_UNCHANGED = -1 # 不進(jìn)行轉(zhuǎn)化,比如保存為了16位的圖片,讀取出來仍然為16位。
# IMREAD_GRAYSCALE = 0 # 進(jìn)行轉(zhuǎn)化為灰度圖,比如保存為了16位的圖片,讀取出來為8位,類型為CV_8UC1。
# IMREAD_COLOR = 1 # 進(jìn)行轉(zhuǎn)化為RGB三通道圖像,圖像深度轉(zhuǎn)為8位
# IMREAD_ANYDEPTH = 2 # 保持圖像深度不變,進(jìn)行轉(zhuǎn)化為灰度圖。
# IMREAD_ANYCOLOR = 4 # 若圖像通道數(shù)小于等于3,則保持原通道數(shù)不變;若通道數(shù)大于3則只取取前三個(gè)通道。圖像深度轉(zhuǎn)為8位
cv.imwrite(ResultPath1 + 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] # 裁剪坐標(biāo)為[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 # 裁剪結(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é)果詳細(xì)信息如下圖所示,成功的轉(zhuǎn)換成png格式了。

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

def toCutPng(dir):函數(shù)效果圖如下圖所示。
以上這篇利用Python裁切tiff圖像且讀取tiff,shp文件的實(shí)例就是小編分享給大家的全部?jī)?nèi)容了,希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Anaconda+Pycharm+Pytorch虛擬環(huán)境創(chuàng)建(各種包安裝保姆級(jí)教學(xué))
相信很多時(shí)候大家都會(huì)用到虛擬環(huán)境,他具有可以讓你快速切換不同的python版本,本文主要介紹了Anaconda+Pycharm+Pytorch虛擬環(huán)境創(chuàng)建,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-10-10
Python3 venv搭建輕量級(jí)虛擬環(huán)境的步驟(圖文)
這篇文章主要介紹了Python3 venv搭建輕量級(jí)虛擬環(huán)境的步驟(圖文),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-08-08
打包Python代碼的常用方法實(shí)現(xiàn)程序exe應(yīng)用
Python是一門強(qiáng)大的編程語言,但在將Python代碼分享給其他人時(shí),讓他們安裝Python解釋器并運(yùn)行腳本可能有點(diǎn)繁瑣,這時(shí),將Python代碼打包成可執(zhí)行的應(yīng)用程序(.exe)可以大大簡(jiǎn)化這個(gè)過程,本文將介紹幾種常用的方法,輕松地將Python代碼變成獨(dú)立的可執(zhí)行文件2023-12-12
Python實(shí)現(xiàn)RGB與HSI顏色空間的互換方式
今天小編就為大家分享一篇Python實(shí)現(xiàn)RGB與HSI顏色空間的互換方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2019-11-11
使用Python將圖片轉(zhuǎn)正方形的兩種方法實(shí)例代碼詳解
這篇文章主要介紹了使用Python將圖片轉(zhuǎn)正方形的兩種方法,本文通過實(shí)例代碼給大家給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-04-04
對(duì)Python進(jìn)行數(shù)據(jù)分析_關(guān)于Package的安裝問題
下面小編就為大家?guī)硪黄獙?duì)Python進(jìn)行數(shù)據(jù)分析_關(guān)于Package的安裝問題。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-05-05
用Python實(shí)現(xiàn)一個(gè)打字速度測(cè)試工具來測(cè)試你的手速
有很多小伙伴們都苦惱自己手速不夠,今天特地整理了這篇文章,教你用Python實(shí)現(xiàn)一個(gè)打字測(cè)試工具來測(cè)試你的打字速度,文中有非常詳細(xì)的代碼示例,對(duì)想練手速的小伙伴們很有用哦,需要的朋友可以參考下2021-05-05

