gdal개요

gdal 라이브러리 1개

여기에 이미지 설명을 삽입하세요.

여기에 이미지 설명을 삽입하세요.
여기에 이미지 설명을 삽입하세요.

2 그리드 드라이버

래스터 데이터를 읽는 프로세스:
(1) 래스터 드라이버를 얻습니다(기본 드라이버가 있지만 생성할 수 없으며 생성하는 것이 가장 좋으며 명확해 보입니다.) (2)
드라이버를 등록합니다(있음) 기본값으로 설정하면 생성하지 않을 수 있습니다. 생성하면 읽기 전용 또는 읽기-쓰기를 선택할 수 있으며 이는 래스터 드라이버에 대한 권한을 설정하는 것과 같습니다.) ( 3) 데이터 세트를 통해
획득 (
4) 데이터 세트를 통해 래스터 속성을 조작합니다.

여기에 이미지 설명을 삽입하세요.

여기에 이미지 설명을 삽입하세요.

try:
    from osgeo import gdal,ogr   # gdal是处理栅格,ogr处理矢量
except:
    import gdal

driverCount = gdal.GetDriverCount()
print(driverCount)

#gdal.AllRegister()
driver = gdal.GetDriverByName('GTiff')
driver.Register()

print(driver.ShortName)
print(driver.LongName)

print(dir(driver))

3 래스터 데이터세트(다양한 래스터 속성을 포함하는 클래스)

3.1 좌표(6개 매개변수)

여기에 이미지 설명을 삽입하세요.
여기에 이미지 설명을 삽입하세요.
여기에 이미지 설명을 삽입하세요.

# 读取地理坐标
from osgeo import gdal

filePath = '1.tif'  # tif文件路径
dataset = gdal.Open(filePath)  # 打开tif

adfGeoTransform = dataset.GetGeoTransform()  # 读取地理信息

# 左上角地理坐标
print(adfGeoTransform[0])
print(adfGeoTransform[3])

nXSize = dataset.RasterXSize  # 列数
nYSize = dataset.RasterYSize  # 行数

print(nXSize, nYSize)

arrSlope = []  # 用于存储每个像素的(X,Y)坐标
for i in range(nYSize):
    row = []
    for j in range(nXSize):
        px = adfGeoTransform[0] + i * adfGeoTransform[1] + j * adfGeoTransform[2]
        py = adfGeoTransform[3] + i * adfGeoTransform[4] + j * adfGeoTransform[5]
        col = [px, py]  # 每个像素的经纬度
        row.append(col)
        print(col)
    arrSlope.append(row)


위의 코드는 실제로 tif에서 경도와 위도를 얻기 위해 구현된 코드입니다. 자세히 연구해 보면 실제로 gdal의 GetGeoTransform 메소드를 사용하여 좌표를 읽는다는 것을 알 수 있습니다. 이 메소드를 간단히 소개하겠습니다. 이 메소드는 6개의 매개변수를 따릅니다.

GT(0) 왼쪽 위 픽셀의 왼쪽 위 모서리의 x 좌표입니다.
GT(1) we픽셀 해상도/픽셀 너비.
GT(2) 행 회전(일반적으로 0).
GT(3) 왼쪽 위 픽셀의 왼쪽 위 모서리의 y 좌표입니다.
GT(4) 열 회전(일반적으로 0).
GT(5) ns 픽셀 해상도/픽셀 높이(북향 이미지의 경우 음수 값)

3.1.2 tif 파일의 지리적 좌표(2가지 경우)

첫 번째는 tif 파일만 있고 이 tif 파일에 지리 좌표가 저장되어 있다는 것이고, 두 번째
는 첨부된 tfw 파일이 있는데 이 파일에 지리 좌표의 매개변수 6개가 저장되어 있다는 것입니다.
tif 파일에서 먼저 tif 파일에 지리가 있는지 확인하고 좌표가 있으면 직접 사용하고 그렇지 않으면 tfw 파일을 찾습니다.

3.2 밴드 번호, 크기, 투영 및 기타 정보

try:
    from osgeo import gdal,ogr
except:
    import gdal

gdal.AllRegister()
dataset = gdal.Open('C:\\Users\\Administrator\\Desktop\\gdal\\样例数据\\GF1\\GF1.tif')

print(dir(dataset))

#波段信息
bandCount = dataset.RasterCount
print(bandCount)

#大小
weight,height = dataset.RasterXSize,dataset.RasterYSize
print(weight,height)

#空间信息
transform = dataset.GetGeoTransform()
print(transform)

#投影信息
proj = dataset.GetProjection()

#描述信息
descrip = dataset.GetDescription()
print(descrip)

3.3 래스터 픽셀 읽기

래스터 데이터를 읽는 프로세스:
(1) 래스터 드라이버 얻기(기본값이 있으므로 생성할 필요가 없음), (
2) 드라이버 등록(기본값이 있으므로 생성할 필요 없음) 생성해야 하며 생성하는 경우 읽기 전용을 선택하거나 래스터 드라이버에 대한 권한을 설정하는 것과 동일한 읽기 및 쓰기를 선택할 수 있습니다. (3)
드라이버를 통해 데이터 세트를 얻습니다.
(4) 조작 데이터 세트를 통한 래스터 속성;
여기에 이미지 설명을 삽입하세요.

try:
    from osgeo import gdal,ogr
except:
    import gdal

gdal.AllRegister()      # 只读,这里前面没有指定驱动,它自动会用tif
dataset = gdal.Open('C:\\Users\\Administrator\\Desktop\\gdal\\样例数据\\GF1\\GF1.tif')

width = dataset.RasterXSize       # 数据集中的各种属性信息
height = dataset.RasterYSize
bandCont = dataset.RasterCount

for i in range(bandCont):
    band = dataset.GetRasterBand(i+1)      # 获取波段,波段从1开始,不是从0开始
    bandinform = band.ReadRaster(0,0,3,3)  # 获取栅格数值0-3
    print(bandinform)
    #获得波段的数值类型
    dataType = band.DataType
    print(dataType)

    #获得影像的nodata
    nodata = band.GetNoDataValue()
    print(nodata)

    #获得最大值最小值,这个波段中的最大最小值
    maxmin = band.ComputeRasterMinMax()
    print(maxmin)

    imageArray = band.ReadAsArray(0,0,3,3,10,10)   # 读取栅格像元并输出为numpy的array形式
    print(imageArray)


3.4 래스터 이미지 생성

래스터 이미지 생성 프로세스:
(1) 드라이버 생성,
(2) 데이터 세트 이름, 데이터 세트 이미지의 너비 및 높이 정의, (3)
데이터 세트 생성, (4) 래스터 픽셀 값 추가,
(4) 래스터 픽셀 값 추가
여기에 이미지 설명을 삽입하세요.
여기에 이미지 설명을 삽입하세요.
위의 두 가지 읽기 및 쓰기 방법은 실제로 다음 예에서 사용됩니다:
(1) WriteRaster: 래스터를 무작위로 자르려면 3.4.4를 참조하세요.
(2) WriteArray: NDVI 밴드를 계산하려면 3.4.5를 참조하세요.

3.4.1 배열에서 직접 데이터 세트 생성

픽셀 값 저장 유형 서로 다른 수치 유형으로 얻은 픽셀 값의 범위가 다릅니다.
여기에 이미지 설명을 삽입하세요.

from osgeo import gdal
import numpy as np

srcFile = 'C:\\Users\\Administrator\\Desktop\\gdal\\样例数据\\GF1\\GF1.tif'
dstFile = 'C:\\Users\\Administrator\\Desktop\\gdal\\样例数据\\GF1\\GF1Create.tif'
dataSet = gdal.Open(srcFile)

width = dataSet.RasterXSize
height = dataSet.RasterYSize
bandCount = dataSet.RasterCount

driver = gdal.GetDriverByName('GTiff')
print(dir(driver))
metadata = driver.GetMetadata()
if gdal.DCAP_CREATE in metadata and metadata['DCAP_CREATE'] == 'YES':
    print('支持create方法')
else:
    print('不支持create方法')
if gdal.DCAP_CREATECOPY in metadata and metadata['DCAP_CREATECOPY'] == 'YES':
    print('支持createCopy方法')
else:
    print('不支持createCopy方法')
dataSetOut = driver.Create(dstFile,width,height,bandCount,gdal.GDT_Byte)   # 8位无符号整数

#空间参考
srcProj = dataSet.GetProjection()
srcTranform = dataSet.GetGeoTransform()

dataSetOut.SetProjection(srcProj)
dataSetOut.SetGeoTransform(srcTranform)
datas= []
for i in range(bandCount):
    band = dataSet.GetRasterBand(i+1)
    dataArray = band.ReadAsArray(0,0,width,height)
    #图像处理
    datas.append(dataArray)


    #bandOut = dataSetOut.GetRasterBand(i+1)     # 1这种是分波段写入
    #bandOut.WriteArray(dataArray)
datas = np.concatenate(datas)
dataSetOut.WriteRaster(0,0,width,height,datas.tobytes())   # 2这种是直接写入数据集
gdal.SetConfigOption('USE_RRD','YES')
dataSetOut.BuildOverviews(overviewlist = [2,4,8,16,32,64,128])   # 生成金字塔,不同分辨率的显示

3.4.2 CreateCopy를 사용하여 기존 데이터 세트 직접 복사

from osgeo import gdal
import numpy as np

srcFile = 'C:\\Users\\Administrator\\Desktop\\gdal\\样例数据\\GF1\\GF1.tif'
dataSet = gdal.Open(srcFile)
dstFile = 'C:\\Users\\Administrator\\Desktop\\gdal\\样例数据\\GF1\\GF1Copy.tif'
driver = gdal.GetDriverByName('GTiff')
proc = gdal.TermProgress_nocb    # 这个是显示进度条,可以不加这句话
datasetCopy = driver.CreateCopy(dstFile,dataSet,0,callback = proc)

print()

여기에 이미지 설명을 삽입하세요.

3.4.3 읽기 차단(대용량 파일 읽기 속도가 느린 문제 해결)

# 分块读取
from osgeo import gdal
import numpy as np
gdal.AllRegister()
src = 'C:\\Users\\Administrator\\Desktop\\gdal\\样例数据\\GF1\\GF1.tif'
dataset = gdal.Open(src)

width = dataset.RasterXSize
heigth = dataset.RasterYSize
bandCount = dataset.RasterCount
block = 64
# 每次读取1块儿内容
for i in range(0,width,block):
    if i+block < width:
        numCols = block
    else:
        numCols = width-i
    for j in range(0,heigth,block):
        if j+block < heigth:
            numRows = block
        else:
            numRows = heigth - j
        for m in range(bandCount):
            band = dataset.GetRasterBand(m+1)
            imageBlock = band.ReadAsArray(i,j,numCols,numRows)
            #之后进行波段数据的处理

3.4.4 무작위로 래스터 자르기(딥러닝 샘플 데이터 생성)

from osgeo import gdal
import numpy as np

def ReadImage(src):
    dataset = gdal.Open(src)
    if dataset is None:
        print('数据集无法打开!!')
    width = dataset.RasterXSize               # 宽
    heigth = dataset.RasterYSize              # 高
    bandCount = dataset.RasterCount           # 波段数
    proj = dataset.GetProjection()            # 投影信息
    transform = dataset.GetGeoTransform()     # 空间参考6个参数

    return dataset,width,heigth,bandCount,proj,transform

def WriteImage(clipImageData,outName,imageSize,bandCount,proj,transform):
    driver = gdal.GetDriverByName('GTiff')
    dataset = driver.Create(outName,imageSize,imageSize,bandCount,gdal.GDT_Byte)
    dataset.SetProjection(proj)                         # 设置投影
    dataset.SetGeoTransform(transform)                  # 设置空间参考6要素
    dataset.WriteRaster(0,0,imageSize,imageSize,clipImageData.tobyte())     # 写入栅格值
    dataset.FlushCache()     # 刷新到硬盘
    dataset = None

if __name__ == '__main__':
    src_image = 'C:\\Users\\Administrator\\Desktop\\gdal\\样例数据\\GF1\\GF1.tif'
    outPath = ''
    src_label = ''

    dataset,width,heigth,bandCount,proj, transform = ReadImage(src_image)
    datasetLabel, width, heigth, bandCount, proj, transform = ReadImage(src_label)

    #裁剪的大小和数量
    sampleCount = 50
    imageSize = 512
    count = 0

    while count < sampleCount:
        #生成随机的角点
        randomWidth = np.random.randint(0,width-imageSize-1)
        randomHeight = np.random.randint(0, heigth - imageSize - 1)

        #裁剪
        clipImageData = dataset.ReadAsArray(randomWidth,randomHeight,imageSize,imageSize)
        clipLabelData = datasetLabel.ReadAsArray(randomWidth,randomHeight,imageSize,imageSize)
        count+=1

        #保存影像
        outName = outPath+'\\'+'%s.tif'%(count)
        WriteImage(clipImageData,outName,imageSize,bandCount,proj,transform)
        WriteImage(clipLabelData, outName, imageSize, bandCount, proj, transform)

3.4.5 NDVI 대역 계산

from osgeo import gdal
import numpy as np

dataset = gdal.Open('C:\\Users\\Administrator\\Desktop\\gdal\\样例数据\\GF1\\GF1-NIR.tif')
width = dataset.RasterXSize
heigth = dataset.RasterYSize
bandCount = dataset.RasterCount
if bandCount < 4:
    print('请确认是否存在近红外波段')

#获得相应的波段
bandNir = dataset.GetRasterBand(1)
bandNirArray = bandNir.ReadAsArray(0,0,width,heigth).astype(np.float16)

bandRed = dataset.GetRasterBand(3)
bandRedArray = bandRed.ReadAsArray(0,0,width,heigth).astype(np.float16)

#计算NDVI
NDVI=(bandNirArray - bandRedArray)/(bandNirArray+bandRedArray)

#排除分母为0情况
mask = np.greater(bandNirArray + bandRedArray,0)
NDVI = np.choose(mask,(-99,NDVI))

#ndvi写出去
outName = 'C:\\Users\\Administrator\\Desktop\\gdal\\样例数据\\GF1\\NDVI_FF.tif'
driver = gdal.GetDriverByName('GTiff')
datasetOut =driver.Create(outName,width,heigth,1,gdal.GDT_Float32)
datasetOut.GetRasterBand(1).WriteArray(NDVI)

datasetOut.FlushCache()

datasetOut = None

4 벡터 데이터 처리(OGR 라이브러리)

여기에 이미지 설명을 삽입하세요.
여기에 이미지 설명을 삽입하세요.여기에 이미지 설명을 삽입하세요.
여기에 이미지 설명을 삽입하세요.
여기에 이미지 설명을 삽입하세요.

4.1 벡터 파일 읽기

from osgeo import gdal
from osgeo import ogr
import os
##打开矢量数据集
os.chdir('C:\\Users\\Administrator\\Desktop\\gdal\\样例数据\\shp')
driver = ogr.GetDriverByName('ESRI Shapefile')
dataset = driver.Open('prov_capital.shp',0)    # 0代表只读
if dataset is None:
    print('矢量数据打开出错!!!')

#打开图层
layer = dataset.GetLayer(0)          # 获取第1个图层,当然shp格式只有1个图层
#获取图层的属性信息
#图层里有共多少要素、图层的空间范围、属性表的结构信息
featureCount = layer.GetFeatureCount()
print(featureCount)
#西东南北及空间参考信息
extent = layer.GetExtent()
print(extent)
proj = layer.GetSpatialRef()   # 获取空间投影
print(proj)
#获得属性表的信息,属性的字段,就是每列的列名等信息
layerDef = layer.GetLayerDefn()           # 获取属性表
layerDefCount = layerDef.GetFieldCount()  # 获取字段数量
for i in range(layerDefCount):
    defn = layerDef.GetFieldDefn(i)       # 获取这个字段
    # 输出字段名字,字段类型,精度等
    print(defn.GetName(),defn.GetWidth(),defn.GetType(),defn.GetPrecision())

#获取要素及要素信息
for i in range(featureCount):
    feature = layer.GetNextFeature()   # 获取要素
    geo = feature.GetGeometryRef()     # 获取几何对象
    #获取指定字段的内容
    name = feature.GetField('name')
    #获得点的坐标
    X = geo.GetX()
    Y = geo.GetY()
dataset.Destroy() #释放内存

4.2 포인트 피쳐 생성

다음 6단계로 나누어집니다:
(1) 드라이버 획득,
(2) 데이터 세트 생성,
(3) 레이어 생성,
(4) 속성 테이블 생성,
(5) 피처 생성 및 레이어에 추가(포함) 수집 정보 및 속성 정보),
(6) 디스크에 저장합니다.

from osgeo import gdal,osr,ogr
import os

out_shp = 'C:\\Users\\Administrator\\Desktop\\gdal\\样例数据\\4.2\\test.shp'
driver = ogr.GetDriverByName('ESRI Shapefile')
#创建数据集
ds = driver.CreateDataSource(out_shp)
#判断文件夹下是否已经存在同名文件
if os.path.exists(out_shp):
    driver.DeletDataSource(out_shp)
#创建图层
# 方法的3个参数,图层名,空间参考,图层类型
layer = ds.CreateLayer('point',None ,geom_type = ogr.wkbPoint)
#定义属性结构,字段一共有3个
fieldID = ogr.FieldDefn('id',ogr.OFTString)
fieldID.SetWidth(4)
layer.CreateField(fieldID)

fieldName = ogr.FieldDefn('x',ogr.OFTString)
fieldName.SetWidth(10)#设置宽度
layer.CreateField(fieldName)
fieldName = ogr.FieldDefn('y',ogr.OFTString)
fieldName.SetWidth(10)#设置宽度
layer.CreateField(fieldName)


#设置地理位置
pointList = [(100,100),(200,200),(300,300),(400,400)]
#point = ogr.Geometry(ogr.wkbPoint)
# 创建点要素
# 从layer中获得要素的结构
featureDefn = layer.GetLayerDefn()
feature = ogr.Feature(featureDefn)

for points in pointList:
    ss = str(pointList.index(points))
    # 设置要素的属性信息和几何信息
    feature.SetField('id', ss)
    feature.SetField('x', points[0])
    feature.SetField('y', points[1])
    #point.AddPoint(points[0],points[1])
    #feature.SetGeometry(point)
    #使用wkt创建要素
    # wkt = 'Point(%f %f)'%(points[0],points[1])
    # geo = ogr.CreateGeometryFromWkt(wkt)
    # feature.SetGeometry(geo)
    # 创建,将要素添加到图层中
    layer.CreateFeature(feature)   

#释放内存,刷新到磁盘中
ds.Destroy()

4.3 라인 피처 생성(포인트 피처와 동일한 단계)

from osgeo import ogr
import os

out_shp = 'C:\\Users\\Administrator\\Desktop\\gdal\\样例数据\\4.2\\line.shp'
driver = ogr.GetDriverByName('ESRI Shapefile')

ds = driver.CreateDataSource(out_shp)
#判断文件夹下是否已经存在同名文件
if os.path.exists(out_shp):
    driver.DeletDataSource(out_shp)
layer = ds.CreateLayer('line',None,ogr.wkbLineString)

#定义属性表结构
fieldID = ogr.FieldDefn('id',ogr.OFTString)
fieldID.SetWidth(4)
layer.CreateField(fieldID)

#创建要素
featureDefn = layer.GetLayerDefn()
feature = ogr.Feature(featureDefn)

pointList = [(100,100),(100,500)]#每两个点连成一个线
#属性信息
feature.SetField('id',0)
#几何信息
line = ogr.Geometry(ogr.wkbLineString)
#wkt = ''    # 用wkt字符串也可以创建几何,是第2种创建几何的方式
for idx,point in  enumerate(pointList):
    line.AddPoint(point[0],point[1])
    # if idx == len(pointList)-1:
    #     wkt = wkt + '%f %f' % (point[0], point[1])
    # else:
    #     wkt = wkt + '%f %f,'%(point[0],point[1])

# wkt = 'Linestring(%s)'% wkt
# geo = ogr.CreateGeometryFromWkt(wkt)
# feature.SetGeometry(geo)
# 下面这个代码的作用是使得线闭合,不加这个代码,得到的是不闭合的线,首尾不相连
line.CloseRings()       
feature.SetGeometry(line)
layer.CreateFeature(feature)

ds.Destroy()

4.4 영역 피처 생성(포인트 피처와 동일한 단계)

from osgeo import ogr

out_shp = 'C:\\Users\\Administrator\\Desktop\\gdal\\样例数据\\4.2\\polygon.shp'
driver = ogr.GetDriverByName('ESRI Shapefile')
ds = driver.CreateDataSource(out_shp)

layer = ds.CreateLayer('polygon',None,ogr.wkbPolygon)

#属性结构
fieldID = ogr.FieldDefn('id',ogr.OFTString)
fieldID.SetWidth(4)
layer.CreateField(fieldID)

#创建要素
featureDefn =  layer.GetLayerDefn()
feature = ogr.Feature(featureDefn)#创建一个对象

#设置feature对象的属性
feature.SetField('id','1')
#设置几何属性
#1、封闭的线
pointList = [(100,100),(100,500),(500,500),(500,100),(100,100)]
#wkt = 'Polygon((100 100,100 500,500 500,500 100,100 100))'   # wkt字符串创建几何的方式
lineClosing = ogr.Geometry(ogr.wkbLinearRing)
for point in pointList:
    lineClosing.AddPoint(point[0],point[1])
lineClosing.CloseRings()

polygon = ogr.Geometry(ogr.wkbPolygon)
polygon.AddGeometry(lineClosing)
#polygon = ogr.CreateGeometryFromWkt(wkt)
feature.SetGeometry(polygon)
layer.CreateFeature(feature)

ds.Destroy()

4.5 요소 선택

4.5.1 속성정보에 따른 요소 선택

from osgeo import ogr
import os

inShp = 'C:\\Users\\Administrator\\Desktop\\gdal\\样例数据\\shp\\county_popu.shp'
ds = ogr.Open(inShp)
layer = ds.GetLayer()
featureCout = layer.GetFeatureCount()
print(featureCout)

#按照属性条件选择
layer.SetAttributeFilter('Area<200')

layerSlectCount = layer.GetFeatureCount()
print(layerSlectCount)

#把选中的要素输出
outShp = 'C:\\Users\\Administrator\\Desktop\\gdal\\样例数据\\select\\select.shp'
driver = ogr.GetDriverByName('ESRI Shapefile')
if os.access(outShp,os.F_OK):
    driver.DeleteDataSource(outShp)
dsOut = driver.CreateDataSource(outShp)
layerOut = dsOut.CreateLayer('test',None,ogr.wkbPolygon)

#获得要素
feature = layer.GetNextFeature()  # GetNextFeature每次只获取1个要素
while feature is not None:
    layerOut.CreateFeature(feature)#只能拷贝几何位置,属性信息还没有复制了
    feature = layer.GetNextFeature()

#选择会对后续操作产生影响
layerSlectCount = layer.GetFeatureCount()
print(layerSlectCount)    # 上面已经选择了要素,这里只显示选择了的要素
ds = ogr.Open(inShp)      # 如果要获取全部要素,不被前面的选择影响,从新再打开1次shp文件,或者可以直接清空上面的选择就行
# layer.SetSpatialFilter(None)  #清空上边的选择也可以
layer2 = ds.GetLayer()
featureCout2 = layer2.GetFeatureCount()
print(featureCout2)

dsOut.Destroy()

4.5.2 공간 위치 또는 SQL 문으로 요소 선택

여기에 이미지 설명을 삽입하세요.
여기에 이미지 설명을 삽입하세요.

import os
from osgeo import ogr
#打开已有矢量数据
inshp = 'C:\\Users\\Administrator\\Desktop\\gdal\\样例数据\\select\\GSHHS_c.shp'
covershp = 'C:\\Users\\Administrator\\Desktop\\gdal\\样例数据\\select\\cover.shp'

ds_in = ogr.Open(inshp)
layer_in = ds_in.GetLayer()
fcount= layer_in.GetFeatureCount()
print(fcount)
ds_cover = ogr.Open(covershp)
layer_cover = ds_cover.GetLayer()
feature_cover = layer_cover.GetNextFeature()

cover = feature_cover.GetGeometryRef()
#cover = feature_cover.geometry()

#根据空间位置选择
layer_in.SetSpatialFilter(cover)

fcount = layer_in.GetFeatureCount()
print(fcount)

#清空上边的选择
layer_in.SetSpatialFilter(None)

#按照矩形坐标*(minx,miny,maxx,maxy)
layer_in.SetSpatialFilterRect()
fcount = layer_in.GetFeatureCount()
print(fcount)

#SQL查询
layer_in.SetSpatialFilterRect(None)   # 清除上面矩形选择
fcount = layer_in.GetFeatureCount()
print(fcount)
layername = layer_in.GetName()
result = ds_in.ExecteSQL('select * from {layer_in} where area < 800000'
                   .format(layer_in=layername))
fcount = result.GetFeatureCount()
print(fcount)
ds_in.ReleaseResultSet(result)

4.6 래스터 벡터화 및 선분의 평활화

from osgeo import gdal,ogr,osr
import os,cv2
import numpy as np
from skimage import measure
imagePath = 'C:\\Users\\DELL\\Desktop\\Code\\data\\raster2shp.tif'
outShp = 'C:\\Users\\DELL\\Desktop\\Code\\data\\raster2shp1.shp'

image = gdal.Open(imagePath)
if image is None:
    print('数据不能正常打开!!!')
bandCount = image.RasterCount
if bandCount != 1:
    print('输入数据必须是单波段数据!!!')
#获得影像的投影信息
imgproj = image.GetProjection()

#定义矢量数据
driver = ogr.GetDriverByName('ESRI Shapefile')
shp = driver.CreateDataSource(outShp)
proj = osr.SpatialReference()
proj.ImportFromWkt(imgproj)
layer = shp.CreateLayer('shp',proj,ogr.wkbPolygon)
field = ogr.FieldDefn('id',ogr.OFTString)
shpField = layer.CreateField(field)
#栅格矢量化
prog_func = gdal.TermProgress_nocb
band = image.GetRasterBand(1)
result = gdal.Polygonize(band,None,layer,shpField,[],prog_func)
featCount = layer.GetFeatureCount()
print(featCount)

#创建一个新的shp
outShp2 = 'C:\\Users\\DELL\\Desktop\\Code\\data\\raster2shp2.shp'
shp2 = driver.CreateDataSource(outShp2)
layer2 = shp2.CreateLayer('name',None,ogr.wkbPolygon)

featDefn2 = layer2.GetLayerDefn()
feature2 = ogr.Feature(featDefn2)

# 下面使用3种方法将矢量化后的线段圆滑化

# 第一种方法直接简化
# feature = layer.GetNextFeature()
# while feature is not None:
#     geo = feature.GetGeometryRef()
#     geom = geo.SimplifyPreserveTopology(12)
#     feature2.SetGeometry(geom)
#     layer2.CreateFeature(feature2)
#     feature = layer.GetNextFeature()
# shp.Destroy() # 写到磁盘里
#第二种方法借助skimage
# width = image.RasterXSize
# height = image.RasterYSize
# gdalImage = image.ReadAsArray(0,0,width,height)
# imageGeoTransform = image.GetGeoTransform()
# contours, hierarchy = cv2.findContours(
#         gdalImage, cv2.RETR_TREE, cv2.CHAIN_APPROX_TC89_KCOS)
#
# polygons = ogr.Geometry(ogr.wkbMultiPolygon)
# for i in range(len(contours)):
#     data = np.squeeze(contours[i])
#     print(len(data.shape))
#     if len(data.shape) == 1:
#         continue
#     contours2 = measure.subdivide_polygon(data)
#     lineRing = ogr.Geometry(ogr.wkbLinearRing)
#     for contour in contours2:
#         x_col = float(contour[1])
#         y_row = float(contour[0])
#         # 把图像行列坐标转化成地理坐标
#         # x_geo = 左上角x + xpixel*x分辨率 + ypixel *旋转角
#         row_geo = imageGeoTransform[0] + imageGeoTransform[1] * y_row + x_col * imageGeoTransform[2]
#         col_geo = imageGeoTransform[3] + imageGeoTransform[4] * y_row + x_col * imageGeoTransform[5]
#         lineRing.AddPoint(row_geo, col_geo)
#
#     lineRing.CloseRings()
#     polygon = ogr.Geometry(ogr.wkbPolygon)
#     polygon.AddGeometry(lineRing)
#     polygons.AddGeometry(polygon)
# feature2.SetGeometry(polygons)
# layer2.CreateFeature(feature2)
# shp2.Destroy()
#第三种方法,借助OPencv
#用Opencv中的方法寻找角点并进行简化,然后把角点用gdal构建矢量面
width = image.RasterXSize
height = image.RasterYSize
gdalImage = image.ReadAsArray(0,0,width,height)
imageGeoTransform = image.GetGeoTransform()
contours, hierarchy = cv2.findContours(
        gdalImage, cv2.RETR_TREE, cv2.CHAIN_APPROX_TC89_KCOS)
polygons = ogr.Geometry(ogr.wkbMultiPolygon)
for contour in contours:
        lineRing = ogr.Geometry(ogr.wkbLinearRing)
        for point in contour:
            x_col = float(point[0, 1])
            y_row = float(point[0, 0])
            # 把图像行列坐标转化成地理坐标
            # x_geo = 左上角x + xpixel*x分辨率 + ypixel *旋转角
            row_geo = imageGeoTransform[0] + imageGeoTransform[1] * y_row + x_col * imageGeoTransform[2]
            col_geo = imageGeoTransform[3] + imageGeoTransform[4] * y_row + x_col * imageGeoTransform[5]
            lineRing.AddPoint(row_geo, col_geo)
        lineRing.CloseRings()
        polygon = ogr.Geometry(ogr.wkbPolygon)
        polygon.AddGeometry(lineRing)
        polygons.AddGeometry(polygon)
feature2.SetGeometry(polygons)
layer2.CreateFeature(feature2)
shp2.Destroy()

5 일부 처리 도구

GDAL은 주로 두 가지 범주를 포함하여 일반적으로 사용되는 많은 도구를 캡슐화했습니다:
(1) .exe 실행 프로그램, Python 코드로 직접 호출할 수 있음;
(2) .python 파일, 여기에는 많은 라이브러리와 함수가 있으므로 직접 사용하고 우리 코드에 직접 넣어보세요.
이러한 도구는 공식 Gdal 문서에 자세히 설명되어 있습니다.
여기에 이미지 설명을 삽입하세요.

.exe 파일은 설치 패키지 아래 디렉터리에 있습니다.
여기에 이미지 설명을 삽입하세요.

.py 파일은 설치 패키지 아래 디렉터리에 있습니다.
여기에 이미지 설명을 삽입하세요.

6 요약(간단, 반나절만에 학습)

Gdal은 3개 부분, 조직 벡터 처리, gdal 래스터 처리 및 일반적으로 사용되는 일부 도구 세트를 포함하여 매우 간단합니다.
우리가 래스터 클래스나 정량적 데이터 세트 클래스와 같은 일부 클래스를 다루고 있다는 점을 기억하세요. 우리는 주로 이러한 클래스의 속성을 조작하기 위해 해당 클래스의 메소드를 사용합니다.

이는 총 세 부분으로 나뉩니다.
첫 번째 부분은 gdal을 사용하여 래스터 이미지를 처리하는 것입니다.

  1. 래스터를 읽으려면 섹션 3.3을 참조하세요.
  2. 그리드를 작성하려면 섹션 3.4를 참조하세요.
  3. 래스터를 계산하려면 numpy의 연산인 3.4.4를 참조하세요.

두 번째 부분은 벡터 데이터를 ORG 처리하는 부분입니다.
1. shp 파일을 읽고, 읽을 드라이버를 직접 생성하고, 데이터 세트, 레이어, 피처의 속성 정보를 읽을 수 있습니다. 2.
포인트, 라인, 서피스 파일을 생성합니다. , 위를 참조하십시오. 섹션 4.2, 4.3 및 4.4의 코드에는 파일을 만드는 두 가지 방법이 있습니다. 1은 기하학적 요소를 직접 생성하는 것이고, 2는 wkt 문자열을 사용하여 기하학적 요소를 생성하는 것입니다.
3. 요소에 대한 작업, 요소 선택, 래스터 벡터화, 벡터 선분 평활화 등

세 번째 부분은 일부 도구 세트입니다.
주로 .exe 및 .py 도구 세트입니다.

참고자료

[1] Python 및 GDAL - 공간 데이터 처리 입문 튜토리얼_Python 동영상 -
Python 및 GDAL - 51CTO 아카데미의 공간 데이터 처리 입문 튜토리얼 51cto 공식 웹사이트, 강좌 코드 및 자료, 개인 저장소
https://github.com/GisXiaoMa/gdal_51cto

[2] Gdal 공식 문서: https://gdal.org/
[3] 유타 주립대학교 튜토리얼:
https://www.osgeo.cn/python gdal utah tutorial/index.html
[4] OSGEO 중국 공식 웹사이트: https ://www.osgeo.cn/
[5] Bu Kun의 Python 및 오픈 소스 GIS
[6] Li Minlu의 GDAL 소스 코드 분석 책

Supongo que te gusta

Origin blog.csdn.net/xiaotiig/article/details/128297792
Recomendado
Clasificación