在遥感影像分析中,经常需要将大尺寸的影像切分成小片段,以便于进行详细的分析和处理。这种方法特别适用于机器学习和图像处理任务,如对象检测、图像分类等。以下是如何使用Python和OpenCV库来实现这一过程,同时确保每个影像片段保留正确的地理信息。
首先,确保安装了必要的Python库,包括numpy
、opencv-python
和xml.etree.ElementTree
。这些库将用于图像处理和XML文件解析。
下面的代码逐步展示了如何从大尺寸的JPG影像中生成小片段,并为每个片段创建新的XML文件,以存储更新后的地理信息。
设置文件路径和输出目录:
file_folder
是存放原始JPG影像的目录。output_folder
是存放生成的影像片段和XML文件的目录。读取和处理每个影像:
file_folder
中的每个JPG文件,读取对应的XML文件以获取地理转换信息(GeoTransform)。影像切片:
tiles_per_dimension
)和重叠因子(overlap_factor
),计算每个影像片段的大小。保存影像片段和更新XML:
"""
This code is used to convert the image to small patch with overlap
"""
import cv2
import os
import numpy as np
import xml.etree.ElementTree as ET
file_folder = 'E:\\project\\代码\\2020_16_12800_large'
output_folder = 'E:\\project\\代码\\2020_16_12800_large_patch_0.2'
# 确保输出文件夹存在
if not os.path.exists(output_folder):
os.makedirs(output_folder)
count = 0
overlap_factor = 0.2
tiles_per_dimension = 4 # 每个维度上的切片数
for file_name in os.listdir(file_folder):
file_path = os.path.join(file_folder, file_name)
print(file_path)
# 检查是否为 JPG 文件
if file_path.endswith('.jpg'):
xml_path = file_path + '.aux.xml' # 对应的xml文件地址
image = cv2.imdecode(np.fromfile(file_path, dtype=np.uint8), cv2.IMREAD_COLOR)
if image is None:
print(f"Failed to open {file_path}")
continue
# 读取XML文件获取GeoTransform数据
tree = ET.parse(xml_path)
root = tree.getroot()
geo_transform_tag = root.find('GeoTransform')
if geo_transform_tag is None:
print(f"GeoTransform not found in XML for {file_path}")
continue
geo_transform = list(map(float, geo_transform_tag.text.split(',')))
count += 1
img_height, img_width = image.shape[:2]
tile_width = int(img_width / tiles_per_dimension * (1 + overlap_factor))
tile_height = int(img_height / tiles_per_dimension * (1 + overlap_factor))
# 分割图像并保存为jpg及对应的xml
for i in range(tiles_per_dimension):
for j in range(tiles_per_dimension):
x_offset = int(i * img_width / tiles_per_dimension)
y_offset = int(j * img_height / tiles_per_dimension)
# 确保子图不超出原始图像边界
actual_tile_width = min(tile_width, img_width - x_offset)
actual_tile_height = min(tile_height, img_height - y_offset)
# 裁剪子图像
cropped_image = image[y_offset:y_offset+actual_tile_height, x_offset:x_offset+actual_tile_width]
# 创建输出文件的路径
output_file_name = f"{file_name.replace('.jpg', '')}_{i * tiles_per_dimension + j + 1}"
output_file_path = os.path.join(output_folder, output_file_name + '.jpg')
# # 保存子图像
# cv2.imencode('.jpg', cropped_image)[1].tofile(output_file_path)
# 计算并保存子图的地理坐标到XML
top_left_x_new = geo_transform[0] + x_offset * geo_transform[1]
top_left_y_new = geo_transform[3] + y_offset * geo_transform[5]
geo_transform_new = [
top_left_x_new,
geo_transform[1],
geo_transform[2],
top_left_y_new,
geo_transform[4],
geo_transform[5]
]
geo_transform_text_new = ', '.join(map(str, geo_transform_new))
# 创建XML文件
root = ET.Element("PAMDataset")
srs_tag = ET.SubElement(root, "SRS", attrib={"dataAxisToSRSAxisMapping": "2,1"})
srs_tag.text = root.find('SRS').text
geo_transform_tag = ET.SubElement(root, "GeoTransform")
geo_transform_tag.text = geo_transform_text_new
tree = ET.ElementTree(root)
xml_output_path = os.path.join(output_folder, output_file_name + '.jpg.aux.xml')
tree.write(xml_output_path)
通过这种方法,我们可以有效地将大尺寸遥感影像切分成具有精确地理信息的小片段,这对于高精度地理空间分析和遥感数据处理至关重要。希望对大家有帮助!