
深入解析 Transformers 图像处理器工具集image_transforms 与 ImageProcessingMixin 源码级指南【免费下载链接】transformers Transformers: the model-definition framework for state-of-the-art machine learning models in text, vision, audio, and multimodal models, for both inference and training.项目地址: https://gitcode.com/GitHub_Trending/tra/transformers本篇指南聚焦当前仓库中 图像处理器工具文档 所对应的两大核心主题image_transforms模块中的函数式图像变换工具以及ImageProcessingMixin提供的图像处理器序列化与加载机制。它们构成了库中所有视觉模型如 CLIP、ViT、DETR 等图像预处理流程的地基。读完本文你将掌握每个变换函数的输入输出约定、通道格式与类型处理细节并能利用ImageProcessingMixin独立实现可保存、可加载的自定义图像处理器。一、总览图像处理器工具集在库中的定位该文档属于仓库的 Internal内部 API文档区与 英文版 内容一一对应。文档明确指出这些函数大多只在研究库中图像处理器代码时才有用即它们面向的是视觉模型的内部实现者与二次开发者而非终端用户。工具集由两部分组成函数式变换定义在 image_transforms.py是纯函数风格的无状态图像操作resize、normalize、pad 等以numpy.ndarray为主要输入输出基类 Mixin定义在 image_processing_base.py 的ImageProcessingMixin该模块从image_processing_utils.py再导出负责所有图像处理器共有的「保存 / 加载 / 序列化 / 注册自动类」能力。在代码组织上文档中提及的image_processing_utils.ImageProcessingMixin实际是经由image_processing_utils.py从image_processing_base.py导入再导出的见 image_processing_utils.py其实现位于image_processing_base.py。同时 image_processing_utils.py 中还定义了继承ImageProcessingMixin的BaseImageProcessor作为基于继承后端架构的图像处理器基类。二、贯穿所有变换的基础约定在逐个讲解变换函数之前需要先理解image_transforms.py依赖的四个核心约定它们来自 image_utils.py2.1 通道维度格式ChannelDimensionChannelDimension 是一个显式枚举只有两个取值枚举值字符串值含义ChannelDimension.FIRSTchannels_first(num_channels, height, width)即 CHW 布局ChannelDimension.LASTchannels_last(height, width, num_channels)即 HWC 布局几乎每个变换函数都接受data_format输出格式与input_data_format输入格式两个参数当input_data_format未指定时会用infer_channel_dimension_format从输入数组推断通道轴当data_format未指定时默认与输入保持一致。这一设计保证了所有变换函数都能自动兼容 CHW 与 HWC 两种布局。2.2 通道格式转换原语 to_channel_dimension_format源码位置image_transforms.pydef to_channel_dimension_format( image: np.ndarray, channel_dim: ChannelDimension | str, input_channel_dim: ChannelDimension | str | None None, ) - np.ndarray:该函数将图像转换到指定的通道格式其实现要点包括输入必须是numpy.ndarray否则抛出TypeError支持任意数量的前导维度例如带 batch 维的 4D 数组只有最后三个维度参与转置若input_channel_dim未指定则自动推断若推断结果与目标一致则直接返回原数组零拷贝目标格式只能为FIRST或LAST其余取值抛出ValueError。从源码结构可以推断它是其余所有变换函数内部统一调用的搬运工rescale、normalize、center_crop、pad等函数在需要保持或改变通道布局时都会复用该原语。2.3 图像尺寸读取 get_image_size源码位置image_utils.pyget_image_size(image, channel_dimNone)返回(height, width)二元组同时接受np.ndarray与PIL.Image.Image两种输入是resize、center_crop、divide_to_patches等函数计算目标尺寸的基础。2.4 PIL 重采样枚举 PILImageResamplingresize的resample参数默认值为PILImageResampling.BILINEAR直接映射到 Pillow 的重采样滤镜。库内多模型默认采用双线性插值这也是与旧版 feature extractor 保持兼容的行为。三、函数式图像变换逐个详解以下 10 个函数正是文档[[autodoc]] image_transforms.*所指向的内容均实现在 image_transforms.py 中。3.1 rescale —— 像素值缩放源码位置image_transforms.pydef rescale( image: np.ndarray, scale: float, data_format: ChannelDimension | None None, dtype: np.dtype np.float32, input_data_format: str | ChannelDimension | None None, ) - np.ndarray:功能按scale缩放图像像素值对应公式rescaled image * scale。实现细节值得注意输入必须是np.ndarray否则抛TypeError先上转型内部先image.astype(np.float64) * scale再在最后下转型到目标dtype。源码注释解释了原因——NumPy 类型提升规则已改变直接运算可能溢出或丢失精度dtype默认np.float32这一默认值是为了与旧版 feature extractor 的行为保持向后兼容典型用途将[0, 255]的 uint8 像素缩放到[0, 1]浮点区间scale1/255这正是多数视觉模型输入标准化流程的第一步。3.2 normalize —— 均值方差归一化源码位置image_transforms.pydef normalize( image: np.ndarray, mean: float | Collection[float], std: float | Collection[float], data_format: ChannelDimension | None None, input_data_format: str | ChannelDimension | None None, ) - np.ndarray:功能执行image (image - mean) / std。实现要点mean/std可以是标量也可以是按通道的集合若为集合其长度必须等于通道数否则抛ValueError若为标量会按通道数自动扩展为数组避免 uint8 减法溢出当输入不是浮点类型时先转为float32若已是浮点类型则保留原 dtype避免把 float16 无谓升级通道轴由input_data_format决定使用(image.T - mean) / std).T的技巧在 CHW 布局下正确广播典型用法配合rescale(1/255)使用 ImageNet 的mean[0.485, 0.456, 0.406]、std[0.229, 0.224, 0.225]。3.3 resize —— 图像尺寸调整源码位置image_transforms.pydef resize( image: np.ndarray, size: tuple[int, int], resample: Optional[PILImageResampling] None, reducing_gap: int | None None, data_format: ChannelDimension | None None, return_numpy: bool True, input_data_format: str | ChannelDimension | None None, ) - np.ndarray:功能使用 PIL 库将图像缩放到size(height, width)指定的尺寸。关键实现细节底层依赖 PIL非 PIL 输入会先经to_pil_image转换必要时自动先缩放到[0, 255]再调用PIL.Image.resize最后转回 numpy——这正是源码注释所说的为了与旧版 image feature extractor 的缩放行为保持向后兼容resample默认PILImageResampling.BILINEARreducing_gap是 Pillow 的分步缩放优化参数值越大结果越接近公平重采样return_numpyFalse时直接返回PIL.Image.Image对象单通道陷阱输入若只有 1 个通道转 PIL 时该维度会被丢弃返回 numpy 前会通过np.expand_dims重新补回转 PIL 后图像恒为 channels-last因此回填时会用to_channel_dimension_format还原到data_format若在转 PIL 前做过[0, 1] → [0, 255]的预缩放返回前会以1/255反向还原。与resize配套的两个尺寸计算辅助函数同样值得了解源码位置 image_transforms.pyget_size_with_aspect_ratio(image_size, size, max_sizeNone)给定输入尺寸与目标size计算保持纵横比的输出尺寸max_size用于约束长边上限先按比例缩放若超限则回退重算get_resize_output_image_size(input_image, size, default_to_squareTrue, max_sizeNone, ...)当size是(h, w)二元组时直接使用是单个 int 且default_to_squareTrue时输出正方形(size, size)default_to_squareFalse时则复刻torchvision.transforms.Resize的行为——只对齐短边并可选max_size限制长边源码注释明确标注该逻辑改编自 torchvision。3.4 center_crop —— 中心裁剪源码位置image_transforms.pydef center_crop( image: np.ndarray, size: tuple[int, int], data_format: str | ChannelDimension | None None, input_data_format: str | ChannelDimension | None None, ) - np.ndarray:功能对图像做中心裁剪到size(height, width)。实现要点内部统一先转为FIRST格式执行裁剪再转回输出格式裁剪区域为top (orig_h - crop_h) // 2、left (orig_w - crop_w) // 2奇数差时向下取整以保证尺寸奇偶正确裁剪越界自动补零当原图小于目标尺寸时会先构造一个零填充的更大画布np.zeros_like配合ceil计算填充量把原图居中放置后再裁剪因此返回值恒等于目标size这是与 torchvisionCenterCrop一致的保证性行为输入非np.ndarray抛TypeErrorsize必须是长度为 2 的可迭代对象。3.5 pad —— 边缘填充源码位置image_transforms.pydef pad( image: np.ndarray, padding: int | tuple[int, int] | Iterable[tuple[int, int]], mode: PaddingMode PaddingMode.CONSTANT, constant_values: float | Iterable[float] 0.0, data_format: str | ChannelDimension | None None, input_data_format: str | ChannelDimension | None None, ) - np.ndarray:功能按指定 padding 与 mode 填充图像底层委托给np.pad。padding参数支持三种书写格式格式含义(pad,)或 int高、宽四个方向均填充pad((before, after),)高、宽方向使用相同的前后填充量((before_h, after_h), (before_w, after_w))每个轴独立的前后填充量mode由 PaddingMode 枚举约束共四种映射关系如下PaddingMode语义np.pad 底层模式CONSTANT常量填充默认constant值由constant_values指定默认 0REFLECT以向量首尾值为镜面做反射填充reflectREPLICATE复制边缘值填充edgeSYMMETRIC沿数组边缘对称反射填充symmetric实现细节内部_expand_for_data_format会把padding与constant_values按输入通道格式自动补上通道维(0, 0)以及 batch 维输入为 4D 时从而对 CHW/HWC、有无 batch 维的输入都透明生效。3.6 to_pil_image —— 转 PIL 图像源码位置image_transforms.pydef to_pil_image( image: Union[np.ndarray, PIL.Image.Image, torch.Tensor], do_rescale: bool | None None, image_mode: str | None None, input_data_format: str | ChannelDimension | None None, ) - PIL.Image.Image:功能将图像转换为PIL.Image.Image可选地先做缩放并把通道维还原到最后一维。实现要点已是 PIL 图像则原样返回torch.Tensor先经.numpy()转 numpy其余非 numpy 类型抛ValueError内部调用to_channel_dimension_format(image, ChannelDimension.LAST, ...)强制 channels-last若最后一维为 1单通道np.squeeze去掉该维因为 PIL 无法处理之自动缩放判定do_rescaleNone时由辅助函数_rescale_for_pil_conversionimage_transforms.py决定——uint8 不缩放整数值且在[0, 255]内不缩放浮点值在[0, 1]内则缩放 255 倍任何超出允许范围的情况都会抛出带实际取值范围的ValueErrorPIL 只能存储 uint8image_mode用于指定 PIL 模式如RGB不传则使用默认。3.7 边界框格式转换center_to_corners_format 与 corners_to_center_formatcenter_to_corners_format将中心格式(center_x, center_y, width, height)的边界框转换为角点格式(top_left_x, top_left_y, bottom_right_x, bottom_right_y)corners_to_center_format反向转换(center_x, center_y, width, height)由角点坐标算术平均与差值得出。两者是互逆操作且都同时支持torch.Tensor与np.ndarray内部各自实现 torch/numpy 版本_center_to_corners_format_torch/numpy与_corners_to_corners_format_torch/numpy。源码注释明确说明这两个函数会被模型前向传播直接调用因此如果不相关就尽量在 torch 域内完成、避免转 numpy。其实现灵感来自 DETR 的util/box_ops.py源码注释中标注了出处主要用于目标检测/实例分割类图像处理器如 DETR 系列。3.8 语义分割 ID 转换rgb_to_id 与 id_to_rgbrgb_to_id将 RGB 颜色编码为唯一 ID公式为r 256*g 256*256*b支持单像素三元组或 3D(H, W, 3)数组uint8 会先升为 int32 避免溢出id_to_rgb逆操作把唯一 ID 逐位拆回 RGB 三通道。二者实现在源码注释中标注为从panopticapi移植github.com/cocodataset/panopticapi 的panopticapi/utils.py是全景/语义分割数据标注在 RGB 编码与类别 ID 之间互转的标准工具。3.9 文档之外的相关工具源码佐证文档正文虽只 autodoc 了上述 10 个函数与ImageProcessingMixin但 image_transforms.py 中还包含若干同源工具理解它们有助于把握模块全貌to_channel_dimension_format上文 2.2 已述模块内部的核心转换原语convert_to_rgbimage_transforms.py仅当输入是 PIL 图像且非 RGB 模式时执行.convert(RGB)否则原样返回flip_channel_orderimage_transforms.py翻转通道顺序RGB ↔ BGR兼容 CHW/HWC 两种布局divide_to_patchesimage_transforms.py按patch_sizeint 或(patch_h, patch_w)将图像切分为补丁列表split_to_tilesimage_transforms.py把批量张量切分为num_tiles_height × num_tiles_width的瓦片网格group_images_by_shape/reorder_imagesimage_transforms.py按 shape 对可嵌套的图像列表分组批处理后再按原顺序还原disable_grouping未指定时遵循经验规则——CPU 上默认禁用分组、GPU 上默认启用源码注释引用了 huggingface/transformers PR #38157 的实验结论safe_squeeze仅在目标轴长度为 1 时执行 squeeze否则原样返回。四、ImageProcessingMixin图像处理器的统一序列化基类文档第二部分 autodoc 的是ImageProcessingMixin。它在image_processing_utils.py中被导入再导出image_processing_utils.py实际实现位于 image_processing_base.py。其类注释将其定位为为序列化与图像特征提取器提供保存/加载功能的 mixin并继承自PushToHubMixin因而天然具备推送 Hub 的能力。4.1 构造行为kwargs 即属性源码位置image_processing_base.pydef __init__(self, **kwargs): kwargs.pop(feature_extractor_type, None) kwargs.pop(processor_class, None) for key, value in kwargs.items(): setattr(self, key, value)构造逻辑非常朴素把传入的kwargs全部setattr为实例属性。两个被特殊剔除的键是历史遗留——feature_extractor_type来自旧的XXXFeatureExtractor命名时代现已是误导性字段processor_class不再随图像处理器配置保存。4.2 核心 API 一览ImageProcessingMixin提供的公开能力可归纳为下表方法作用源码位置from_pretrained类方法从 Hub 模型 ID、本地目录或单个 JSON 文件加载图像处理器image_processing_base.pysave_pretrained将处理器保存为 JSON 到指定目录可选推送 Hubimage_processing_base.pyget_image_processor_dict从路径解析出参数 dict供from_dict使用image_processing_base.pyfrom_dict从参数字典实例化处理器image_processing_base.pyto_dict序列化为字典自动附加image_processor_type字段image_processing_base.pyfrom_json_file从 JSON 文件路径实例化image_processing_base.pyto_json_string/to_json_file序列化为 JSON 字符串 / 写入 JSON 文件image_processing_base.pyregister_for_auto_class将自定义处理器注册到AutoImageProcessorimage_processing_base.pyfetch_images将单个 / 列表 / 嵌套列表的 URL 批量转换为 PIL 图像image_processing_base.py4.3 加载流程 from_pretrained 的完整链路从源码可以还原出from_pretrained的解析顺序image_processing_base.py支持三种输入形态Hub 上的模型 ID 字符串、包含处理器文件的本地目录、指向单个 JSON 文件的路径关键参数包括cache_dir自定义缓存目录、force_download强制重下、local_files_only仅用本地、token认证令牌、revision分支/标签/commit可用refs/pr/pr_number测试 PR、subfolder仓库子目录、return_unused_kwargs是否返回未被消费的 kwargs内部经由get_image_processor_dict解析出参数字典离线模式is_offline_mode()会强制local_files_onlyTrue优先读取processor_config.json中嵌套的image_processor字段新版嵌套结构找不到再回退到独立的preprocessor_config.json旧式平铺结构——源码注释明确指出这种优先级设计是为了同时兼容新旧两种保存格式最终调用from_dict(image_processor_dict, **kwargs)完成实例化。from_dict的实现image_processing_base.py只把 kwargs 中声明于cls.valid_kwargs.__annotations__的键合并进配置其余键若与已有属性同名则会以向后兼容方式被附加到实例并给出告警提示应把新键加入valid_kwargs一个自定义 TypedDict以避免该告警。文档中给出的标准示例源自 docstringimage_processing_base.py# 从 Hub 下载并缓存 image_processor CLIPImageProcessor.from_pretrained(openai/clip-vit-base-patch32) # 从本地目录加载此前用 save_pretrained 保存 image_processor CLIPImageProcessor.from_pretrained(./test/saved_model/) # 直接指向单个 JSON 配置文件 image_processor CLIPImageProcessor.from_pretrained(./test/saved_model/preprocessor_config.json) # 用 kwargs 覆盖已保存的属性 image_processor CLIPImageProcessor.from_pretrained( openai/clip-vit-base-patch32, do_normalizeFalse, fooFalse ) assert image_processor.do_normalize is False # 回收未消费的 kwargs image_processor, unused_kwargs CLIPImageProcessor.from_pretrained( openai/clip-vit-base-patch32, do_normalizeFalse, fooFalse, return_unused_kwargsTrue ) assert unused_kwargs {foo: False}4.4 保存流程 save_pretrained 的要点源码位置image_processing_base.pysave_directory若已是文件路径会抛AssertionError目录不存在则自动创建文件默认以IMAGE_PROCESSOR_NAME即preprocessor_config.json命名保存以便后续from_pretrained直接按标准名字加载若设置了_auto_class例如通过register_for_auto_class注册过AutoImageProcessor会额外调用custom_object_save把自定义类定义文件一并复制到保存目录从而支持从 Hub 加载自定义处理器push_to_hubTrue时先创建仓库create_repo(..., exist_okTrue)、记录文件时间戳保存完成后经_upload_modified_files上传返回值为保存的文件路径列表。4.5 与 AutoImageProcessor 的衔接register_for_auto_class(auto_classAutoImageProcessor)image_processing_base.py用于把自定义图像处理器注册进自动类体系库内置的处理器已在models/auto的映射中登记无需手动注册。注册后_auto_class被赋值配合save_pretrained的自定义对象保存逻辑即可实现自定义处理器 → 保存 → Auto 加载的完整闭环。五、实战从零定义一个可保存/加载的最小图像处理器综合本章内容可构建一个演示用处理器骨架仅供学习参考展示 Mixin 与变换函数的组合方式import numpy as np from transformers import ImageProcessingMixin from transformers.image_transforms import center_crop, normalize, rescale, resize from transformers.image_utils import ChannelDimension, infer_channel_dimension_format class MyImageProcessor(ImageProcessingMixin): def __init__(self, size224, meanNone, stdNone, **kwargs): super().__init__(**kwargs) self.size size self.mean mean if mean is not None else [0.485, 0.456, 0.406] self.std std if std is not None else [0.229, 0.224, 0.225] def __call__(self, image: np.ndarray): data_format infer_channel_dimension_format(image) # 先统一到 (H, W, C)便于 PIL 链路处理 image image image resize(image, (self.size, self.size), input_data_formatdata_format) image center_crop(image, (self.size, self.size), input_data_formatdata_format) image rescale(image, 1 / 255, input_data_formatdata_format) image normalize( image, self.mean, self.std, data_formatChannelDimension.FIRST, input_data_formatdata_format, ) return {pixel_values: image} # 保存 / 加载闭环 proc MyImageProcessor(size224) proc.save_pretrained(./my_image_processor) loaded MyImageProcessor.from_pretrained(./my_image_processor) assert loaded.size 224要点回顾__init__中先调super().__init__(**kwargs)以让 Mixin 的kwargs 即属性机制接管未知字段变换函数全部以输入格式推断 → 变换 → 输出格式还原/指定的方式串联调用链可对照 image_transforms.py 中各函数签名逐一验证保存后目录内会生成preprocessor_config.jsonfrom_pretrained会自动读取并恢复全部属性。六、与处理器测试体系的呼应仓库测试侧tests/test_image_processing_common.py 中的公共测试类覆盖了所有继承自ImageProcessingMixin的处理器的序列化往返to_dict/from_dict、save_pretrained/from_pretrained等保证了每个新增视觉模型处理器都遵循同一套契约而各模型目录下的具体处理器例如 tests/models/clip 下的测试则负责验证特定变换参数组合如 CLIP 的do_resize/do_center_crop/do_rescale/do_normalize开关在真实数据上的行为。这两层测试共同约束了变换函数 Mixin这一组合的正确性与向后兼容性。七、小结image_transforms与ImageProcessingMixin构成了 Transformers 视觉模型图像预处理的地基变换层image_transforms.py以 numpy 为中心、以ChannelDimension为统一约定的纯函数集合覆盖缩放、归一化、缩放尺寸、中心裁剪、填充、PIL 转换、边界框格式互转与分割 ID 互转全部兼容 CHW/HWC 与任意前导维度基类层image_processing_base.py 中的ImageProcessingMixin提供from_pretrained/save_pretrained/to_dict/from_dict/to_json_file等完整的序列化与加载链路支持新旧两种配置文件格式的兼容读取并能通过register_for_auto_class接入AutoImageProcessor。对想要研究库内各视觉模型处理器实现或需要为自有模型编写自定义图像处理器的开发者而言这两个文件是最值得精读的入口。【免费下载链接】transformers Transformers: the model-definition framework for state-of-the-art machine learning models in text, vision, audio, and multimodal models, for both inference and training.项目地址: https://gitcode.com/GitHub_Trending/tra/transformers创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考