Spaces:
Sleeping
Sleeping
File size: 4,473 Bytes
e40db0e | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 | #!/usr/bin/env python3
"""
Florence Forge - 数据处理工具函数
提供数据处理相关的工具函数
"""
import torch
import numpy as np
from typing import List, Tuple
from PIL import Image, ImageDraw
def generate_mask_from_polygon(
polygon: List[Tuple[float, float]],
image_size: Tuple[int, int]
) -> np.ndarray:
"""从多边形坐标生成掩码
Args:
polygon: 多边形顶点坐标列表 [(x1, y1), (x2, y2), ...]
image_size: 图像尺寸 (width, height)
Returns:
二值掩码数组,形状为 (height, width)
"""
width, height = image_size
# 创建空白图像
mask_image = Image.new('L', (width, height), 0)
draw = ImageDraw.Draw(mask_image)
# 绘制多边形
if len(polygon) >= 3:
draw.polygon(polygon, fill=255)
# 转换为numpy数组
mask = np.array(mask_image)
return mask
def normalize_bbox(
bbox: List[float],
image_size: Tuple[int, int]
) -> List[float]:
"""归一化边界框坐标
Args:
bbox: 边界框坐标 [x1, y1, x2, y2]
image_size: 图像尺寸 (width, height)
Returns:
归一化后的边界框坐标
"""
width, height = image_size
x1, y1, x2, y2 = bbox
return [
x1 / width,
y1 / height,
x2 / width,
y2 / height
]
def denormalize_bbox(
bbox: List[float],
image_size: Tuple[int, int]
) -> List[float]:
"""反归一化边界框坐标
Args:
bbox: 归一化的边界框坐标 [x1, y1, x2, y2]
image_size: 图像尺寸 (width, height)
Returns:
实际像素坐标的边界框
"""
width, height = image_size
x1, y1, x2, y2 = bbox
return [
x1 * width,
y1 * height,
x2 * width,
y2 * height
]
def resize_image_and_annotations(
image: Image.Image,
annotations: dict,
target_size: Tuple[int, int]
) -> Tuple[Image.Image, dict]:
"""调整图像大小并相应调整标注
Args:
image: PIL图像
annotations: 标注字典
target_size: 目标尺寸 (width, height)
Returns:
调整后的图像和标注
"""
original_size = image.size
resized_image = image.resize(target_size, Image.Resampling.LANCZOS)
# 计算缩放比例
scale_x = target_size[0] / original_size[0]
scale_y = target_size[1] / original_size[1]
# 调整标注
updated_annotations = annotations.copy()
# 调整边界框
if 'bboxes' in annotations:
updated_bboxes = []
for bbox in annotations['bboxes']:
x1, y1, x2, y2 = bbox
updated_bboxes.append([
x1 * scale_x,
y1 * scale_y,
x2 * scale_x,
y2 * scale_y
])
updated_annotations['bboxes'] = updated_bboxes
# 调整多边形
if 'polygons' in annotations:
updated_polygons = []
for polygon in annotations['polygons']:
updated_polygon = [
(x * scale_x, y * scale_y) for x, y in polygon
]
updated_polygons.append(updated_polygon)
updated_annotations['polygons'] = updated_polygons
return resized_image, updated_annotations
def collate_batch_data(batch_data: List[dict]) -> dict:
"""整理批次数据
Args:
batch_data: 批次数据列表
Returns:
整理后的批次数据字典
"""
if not batch_data:
return {}
# 获取所有键
keys = batch_data[0].keys()
collated = {}
for key in keys:
values = [item[key] for item in batch_data]
# 根据数据类型进行不同的处理
if isinstance(values[0], torch.Tensor):
# 对于张量,尝试堆叠
try:
collated[key] = torch.stack(values)
except RuntimeError:
# 如果无法堆叠,保持列表形式
collated[key] = values
elif isinstance(values[0], (list, tuple)):
# 对于列表或元组,保持原样
collated[key] = values
else:
# 对于其他类型,尝试转换为张量
try:
collated[key] = torch.tensor(values)
except (ValueError, TypeError):
collated[key] = values
return collated |