Python assigns image coordinate system in batches and merges images according to coordinates
- reference article
1. Python assigns image coordinate system in batches
1.1 Environmental conditions preparation
- The relevant coordinates are: the
qgis
generated gridshpfile
file, the obtained relevant coordinates- Each grid has associated coordinate information
- Each grid has associated coordinate information
- The given picture,
gird_256_4490.shp
the picture cut using the grid file 赋予图片坐标系原因
- After using
qgis
the file with cutting coordinates, save.png
the format, there is no coordinate information, and assign the coordinate information of the cutting picture
- After using
1.2. Find the projected coordinate system
- Official website link: https://spatialreference.org/ref/
- Enter the name of the coordinate system you want to turn
- Mine is
China Geodetic Coordinate System 2000
- click on the first link
- Mine is
- click
OGC WKT
- Copy Text **【Copy All】**
- assign text to variable
img_pos_proj
- assign text to variable
1.3. Related code
-
Picture plus coordinate system function
def def_geoCoordSys(read_path, save_name, img_transf, img_proj): """ :param read_path: 不带坐标的图像 :param save_name: 保存带有坐标的图像 :param img_transf: 投影相关坐标 :param img_proj: 投影类型 :return: """ array_dataset = gdal.Open(read_path) img_array = array_dataset.ReadAsArray(0, 0, array_dataset.RasterXSize, array_dataset.RasterYSize) if 'int8' in img_array.dtype.name: datatype = gdal.GDT_Byte elif 'int16' in img_array.dtype.name: datatype = gdal.GDT_UInt16 else: datatype = gdal.GDT_Float32 if len(img_array.shape) == 3: img_bands, im_height, im_width = img_array.shape else: img_bands, (im_height, im_width) = 1, img_array.shape driver = gdal.GetDriverByName("GTiff") # 创建文件驱动 dataset = driver.Create( save_name, im_width, im_height, img_bands, datatype) dataset.SetGeoTransform(img_transf) # 写入仿射变换参数 dataset.SetProjection(img_proj) # 写入投影 # 写入影像数据 if img_bands == 1: dataset.GetRasterBand(1).WriteArray(img_array) else: for i in range(img_bands): dataset.GetRasterBand(i + 1).WriteArray(img_array[i]) print(read_path, 'geoCoordSys get!')
-
Get
shpfile
file relative coordinates
shpdata = gpd.read_file('data/grid.shp',encoding='utf-8') for j in range(0, len(shpdata)): # 遍历网格数据 geo = shpdata.geometry[j] # 获取坐标属性 # ((120.78513142722576 29.253768371972182, 120.78516670362751 29.258387207528127, 120.79043393150636 29.258356166298398, 120.79039841851554 29.25373733658219, 120.78513142722576 29.253768371972182)) # 坐标位置为:0:左上,1:左下,2:右下,3:右上,4:左上 minX,minY=geo.__geo_interface__['coordinates'][0][1] maxX,maxY=geo.__geo_interface__['coordinates'][0][3] numX,numY=256,256 # 图片x轴像素,y轴像素 img_pos_transf=(minX,(maxX-minX)/256 , 0.0, minY, 0.0,-(minY-maxY)/256) img_pos_proj = 'GEOGCS["China Geodetic Coordinate System 2000 ",DATUM["China 2000",SPHEROID["CGCS2000",6378137,298.257222101,AUTHORITY["EPSG","1024"]],AUTHORITY["EPSG","6610"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.01745329251994328,AUTHORITY["EPSG","9122"]],AUTHORITY["EPSG","4490"]]' def_geoCoordSys(read_path,save_name, img_pos_transf, img_pos_proj)
-
full code
import os from osgeo import gdal import geopandas as gpd def def_geoCoordSys(read_path, save_name, img_transf, img_proj): """ :param read_path: 不带坐标的图像 :param save_name: 保存带有坐标的图像 :param img_transf: 投影相关坐标 :param img_proj: 投影类型 :return: """ array_dataset = gdal.Open(read_path) img_array = array_dataset.ReadAsArray(0, 0, array_dataset.RasterXSize, array_dataset.RasterYSize) if 'int8' in img_array.dtype.name: datatype = gdal.GDT_Byte elif 'int16' in img_array.dtype.name: datatype = gdal.GDT_UInt16 else: datatype = gdal.GDT_Float32 if len(img_array.shape) == 3: img_bands, im_height, im_width = img_array.shape else: img_bands, (im_height, im_width) = 1, img_array.shape driver = gdal.GetDriverByName("GTiff") # 创建文件驱动 dataset = driver.Create( save_name, im_width, im_height, img_bands, datatype) dataset.SetGeoTransform(img_transf) # 写入仿射变换参数 dataset.SetProjection(img_proj) # 写入投影 # 写入影像数据 if img_bands == 1: dataset.GetRasterBand(1).WriteArray(img_array) else: for i in range(img_bands): dataset.GetRasterBand(i + 1).WriteArray(img_array[i]) print(read_path, 'geoCoordSys get!') label_path='' # 无坐标图片路径 label_tif_path='' # 保存有坐标图片路径 if not os.path.exists(label_tif_path): os.makedirs(label_tif_path) data = os.walk(label_path) file_list=[file_list for path, folder_list, file_list in data][0] shpdata = gpd.read_file('grid.shp',encoding='utf-8') for j in range(0, len(shpdata)): geo = shpdata.geometry[j] id_name=j+1 minX,minY=geo.__geo_interface__['coordinates'][0][1] maxX,maxY=geo.__geo_interface__['coordinates'][0][3] numX,numY=256,256 # 图片x轴像素,y轴像素 img_pos_transf=(minX,(maxX-minX)/256 , 0.0, minY, 0.0,-(minY-maxY)/256) read_path=os.path.join(label_path,f'{ id_name}.png') # 无坐标图片路径· save_name=os.path.join(label_tif_path,f'{ id_name}.tif') # 保存有坐标图片路径 save_name=save_name.replace('png','tif') img_pos_proj = 'GEOGCS["China Geodetic Coordinate System 2000 ",DATUM["China 2000",SPHEROID["CGCS2000",6378137,298.257222101,AUTHORITY["EPSG","1024"]],AUTHORITY["EPSG","6610"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.01745329251994328,AUTHORITY["EPSG","9122"]],AUTHORITY["EPSG","4490"]]' def_geoCoordSys(read_path,save_name, img_pos_transf, img_pos_proj)
2.Python merges pictures in batches according to the coordinates and reassigns the coordinates
- read filename
dirpath = " " # 图片文件绝对路径 save_path= os.path.join(dirpath, 'merge_tif') # 合并图片文件保存路径 if not os.path.exists(save_path): os.makedirs(save_path) out_path = os.path.join(save_path, "merge.tif") coordinate_path=os.path.join(save_path, "coordinate_merge.tif") # 赋予合并坐标 tif_file = glob.glob(os.path.join(dirpath, "*.tif")) # 读取所有文件名
- add files to list
src_files_to_mosaic = [] for tif_f in tif_file: src = rasterio.open(tif_f) src_files_to_mosaic.append(src)
- Merge and save files
tif
The file is a grayscale image, so I needmosaic.reshape(mosaic.shape[1],mosaic.shape[2])
mosaic, out_trans = merge(src_files_to_mosaic) Image.fromarray(mosaic.reshape(mosaic.shape[1],mosaic.shape[2]),'L').save(out_path)
- Reassign image coordinates
def def_geoCoordSys(read_path, save_name,img_transf, img_proj): array_dataset = gdal.Open(read_path) img_array = array_dataset.ReadAsArray(0, 0, array_dataset.RasterXSize, array_dataset.RasterYSize) if 'int8' in img_array.dtype.name: datatype = gdal.GDT_Byte elif 'int16' in img_array.dtype.name: datatype = gdal.GDT_UInt16 else: datatype = gdal.GDT_Float32 if len(img_array.shape) == 3: img_bands, im_height, im_width = img_array.shape else: img_bands, (im_height, im_width) = 1, img_array.shape driver = gdal.GetDriverByName("GTiff") # 创建文件驱动 dataset = driver.Create(save_name, im_width, im_height, img_bands, datatype) dataset.SetGeoTransform(img_transf) # 写入仿射变换参数 dataset.SetProjection(img_proj) # 写入投影 if img_bands == 1: dataset.GetRasterBand(1).WriteArray(img_array) else: for i in range(img_bands): dataset.GetRasterBand(i + 1).WriteArray(img_array[i]) print(read_path, 'geoCoordSys get!') img_pos_transf=((out_trans[2],out_trans[0],0.0,out_trans[5],0.0,out_trans[4])) img_pos_proj = 'GEOGCS["China Geodetic Coordinate System 2000 ",DATUM["China 2000",SPHEROID["CGCS2000",6378137,298.257222101,AUTHORITY["EPSG","1024"]],AUTHORITY["EPSG","6610"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.01745329251994328,AUTHORITY["EPSG","9122"]],AUTHORITY["EPSG","4490"]]' def_geoCoordSys(out_path,coordinate_path, img_pos_transf, img_pos_proj)
- full code
import os import glob import rasterio from osgeo import gdal import PIL.Image as Image from rasterio.merge import merge def def_geoCoordSys(read_path, save_name,img_transf, img_proj): array_dataset = gdal.Open(read_path) img_array = array_dataset.ReadAsArray(0, 0, array_dataset.RasterXSize, array_dataset.RasterYSize) if 'int8' in img_array.dtype.name: datatype = gdal.GDT_Byte elif 'int16' in img_array.dtype.name: datatype = gdal.GDT_UInt16 else: datatype = gdal.GDT_Float32 if len(img_array.shape) == 3: img_bands, im_height, im_width = img_array.shape else: img_bands, (im_height, im_width) = 1, img_array.shape driver = gdal.GetDriverByName("GTiff") # 创建文件驱动 dataset = driver.Create(save_name, im_width, im_height, img_bands, datatype) dataset.SetGeoTransform(img_transf) # 写入仿射变换参数 dataset.SetProjection(img_proj) # 写入投影 if img_bands == 1: dataset.GetRasterBand(1).WriteArray(img_array) else: for i in range(img_bands): dataset.GetRasterBand(i + 1).WriteArray(img_array[i]) print(read_path, 'geoCoordSys get!') dirpath = "" save_path= os.path.join(dirpath, 'merge_tif') if not os.path.exists(save_path): os.makedirs(save_path) out_path = os.path.join(save_path, "merge.tif") coordinate_path=os.path.join(save_path, "coordinate_merge.tif") tif_file = glob.glob(os.path.join(dirpath, "*.tif")) mosaic, out_trans = merge(src_files_to_mosaic) Image.fromarray(mosaic.reshape(mosaic.shape[1],mosaic.shape[2]),'L').save(out_path) img_pos_transf=((out_trans[2],out_trans[0],0.0,out_trans[5],0.0,out_trans[4])) img_pos_proj = 'GEOGCS["China Geodetic Coordinate System 2000 ",DATUM["China 2000",SPHEROID["CGCS2000",6378137,298.257222101,AUTHORITY["EPSG","1024"]],AUTHORITY["EPSG","6610"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.01745329251994328,AUTHORITY["EPSG","9122"]],AUTHORITY["EPSG","4490"]]' def_geoCoordSys(out_path,coordinate_path, img_pos_transf, img_pos_proj)