Spaces:
Sleeping
Sleeping
| #!/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 |