isLinXu
Pack FlorenceForge source for embedded HF Spaces deployment
e40db0e
Raw
History Blame Contribute Delete
4.47 kB
#!/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