遥感影像的切片处理

在遥感影像分析中,经常需要将大尺寸的影像切分成小片段,以便于进行详细的分析和处理。这种方法特别适用于机器学习和图像处理任务,如对象检测、图像分类等。以下是如何使用Python和OpenCV库来实现这一过程,同时确保每个影像片段保留正确的地理信息。

准备环境

首先,确保安装了必要的Python库,包括numpyopencv-pythonxml.etree.ElementTree。这些库将用于图像处理和XML文件解析。

代码解析

下面的代码逐步展示了如何从大尺寸的JPG影像中生成小片段,并为每个片段创建新的XML文件,以存储更新后的地理信息。

  1. 设置文件路径和输出目录

    • file_folder是存放原始JPG影像的目录。
    • output_folder是存放生成的影像片段和XML文件的目录。
  2. 读取和处理每个影像

    • 对于file_folder中的每个JPG文件,读取对应的XML文件以获取地理转换信息(GeoTransform)。
    • 如果影像读取失败或XML中缺少必要的信息,将跳过该影像。
  3. 影像切片

    • 根据指定的维度(tiles_per_dimension)和重叠因子(overlap_factor),计算每个影像片段的大小。
    • 通过嵌套循环,按照计算出的片段大小对影像进行裁剪。
  4. 保存影像片段和更新XML

    • 为每个影像片段生成新的文件名,并保存为JPG格式。
    • 根据原始影像的地理转换信息计算新片段的地理坐标,更新XML文件中的GeoTransform标签,并保存新的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)

通过这种方法,我们可以有效地将大尺寸遥感影像切分成具有精确地理信息的小片段,这对于高精度地理空间分析和遥感数据处理至关重要。希望对大家有帮助!

你可能感兴趣的:(计算机视觉,python,图像处理)