using System;
using System.IO;
using OpenCvSharp;
namespace BetterGenshinImpact.Test.Simple.AllMap;
public static class ImageSplitter
{
// 写死的图片文件路径
private static readonly string ImagePath = @"E:\HuiTask\更好的原神\地图匹配\拼图结果\5.8\map_1024.jpg";
///
/// 按照1024x1024的大小对图片进行切割
///
public static void SplitImage()
{
if (!File.Exists(ImagePath))
{
Console.WriteLine($"图片文件不存在: {ImagePath}");
return;
}
try
{
// 使用OpenCV读取图片
using var originalImage = new Mat(ImagePath, ImreadModes.Color);
var originalWidth = originalImage.Width;
var originalHeight = originalImage.Height;
// 获取原始文件的扩展名
var extension = Path.GetExtension(ImagePath);
var outputDirectory = Path.Combine(Path.GetDirectoryName(ImagePath) ?? string.Empty, "tiles");
// 确保输出目录存在
if (!Directory.Exists(outputDirectory))
{
Directory.CreateDirectory(outputDirectory);
Console.WriteLine($"创建输出目录: {outputDirectory}");
}
Console.WriteLine($"原始图片尺寸: {originalWidth}x{originalHeight}");
// 计算需要切割的块数
var blocksX = (int)Math.Ceiling((double)originalWidth / 1024);
var blocksY = (int)Math.Ceiling((double)originalHeight / 1024);
Console.WriteLine($"将切割为 {blocksX}x{blocksY} 个块");
// 开始切割
for (int y = 0; y < blocksY; y++)
{
for (int x = 0; x < blocksX; x++)
{
// 计算当前块的位置和大小
var startX = x * 1024;
var startY = y * 1024;
var width = Math.Min(1024, originalWidth - startX);
var height = Math.Min(1024, originalHeight - startY);
// 使用OpenCV创建ROI(感兴趣区域)进行切割
var roi = new Rect(startX, startY, width, height);
using var croppedImage = new Mat(originalImage, roi);
// 保存切割后的图片
var outputFileName = $"{x}_{y}{extension}";
var outputPath = Path.Combine(outputDirectory, outputFileName);
// 使用OpenCV保存图片
Cv2.ImWrite(outputPath, croppedImage);
Console.WriteLine($"已保存: {outputFileName} (尺寸: {width}x{height})");
}
}
Console.WriteLine("图片切割完成!");
}
catch (Exception ex)
{
Console.WriteLine($"切割图片时发生错误: {ex.Message}");
}
}
///
/// 按照 Leaflet 标准对图片进行切割,原点在左下角
/// 切片命名格式为 x_y,其中 y 坐标从负数开始(左上角为 0_-12)
///
public static void SplitImageForLeaflet()
{
if (!File.Exists(ImagePath))
{
Console.WriteLine($"图片文件不存在: {ImagePath}");
return;
}
try
{
// 使用OpenCV读取图片
using var originalImage = new Mat(ImagePath, ImreadModes.Color);
var originalWidth = originalImage.Width;
var originalHeight = originalImage.Height;
// 获取原始文件的扩展名
var extension = Path.GetExtension(ImagePath);
var outputDirectory = Path.Combine(Path.GetDirectoryName(ImagePath) ?? string.Empty, "leaflet_tiles");
// 确保输出目录存在
if (!Directory.Exists(outputDirectory))
{
Directory.CreateDirectory(outputDirectory);
Console.WriteLine($"创建输出目录: {outputDirectory}");
}
Console.WriteLine($"原始图片尺寸: {originalWidth}x{originalHeight}");
// 计算需要切割的块数
var blocksX = (int)Math.Ceiling((double)originalWidth / 1024);
var blocksY = (int)Math.Ceiling((double)originalHeight / 1024);
Console.WriteLine($"将切割为 {blocksX}x{blocksY} 个块 (Leaflet 格式)");
// 开始切割 - Leaflet 格式,原点在左下角
for (int y = 0; y < blocksY; y++)
{
for (int x = 0; x < blocksX; x++)
{
// 计算当前块的位置和大小
var startX = x * 1024;
var startY = y * 1024;
var width = Math.Min(1024, originalWidth - startX);
var height = Math.Min(1024, originalHeight - startY);
// 使用OpenCV创建ROI(感兴趣区域)进行切割
var roi = new Rect(startX, startY, width, height);
using var croppedImage = new Mat(originalImage, roi);
// Leaflet 坐标系:原点在左下角,y 轴向上为正
// 图像坐标系:原点在左上角,y 轴向下为正
// 需要将图像坐标转换为 Leaflet 坐标
var leafletY = -(blocksY - 1 - y);
// 保存切割后的图片,使用 Leaflet 坐标命名
var outputFileName = $"{x}_{leafletY}{extension}";
var outputPath = Path.Combine(outputDirectory, outputFileName);
// 使用OpenCV保存图片
Cv2.ImWrite(outputPath, croppedImage);
Console.WriteLine($"已保存: {outputFileName} (尺寸: {width}x{height}, 图像坐标: {x}_{y})");
}
}
Console.WriteLine("Leaflet 格式图片切割完成!");
}
catch (Exception ex)
{
Console.WriteLine($"切割图片时发生错误: {ex.Message}");
}
}
}