Turns images into the pixel_values input of a vision model, with the preprocessor_config.json of a model repository.
featurizer = Transmuter.Featurizer.load!({:hf, "Xenova/vit-base-patch16-224"})
image = StbImage.read_file!("cat.jpg")
Transmuter.Featurizer.process(featurizer, [image], backend: EMLX.Backend)
#=> #Nx.Tensor<f32[1][3][224][224]>An image is a StbImage struct or a tensor of shape {height, width, channels}, usually of type :u8. To read image files, add {:stb_image, "~> 1.0"} to your deps.
The steps and their order are those of the image processors of Python transformers:
do_convert_rgb- the image gets 3 channels. A gray image repeats its channel, and the alpha channel is removed.do_resize- the image gets thesizeof the configuration with theresamplefilter of Pillow. Withoutresample, the filter is the default of the class ofimage_processor_typein Python transformers, such as bicubic forCLIPImageProcessorand lanczos forIdefics3ImageProcessor, else bilinear. A fast image processor resizes with bicubic in place of lanczos, because torchvision has no lanczos for tensors. Seeresize/4. For animage_processor_typethat ends inFast, the weights are those of torchvision, so a pixel can be one step away from Pillow. Asizewithheightandwidthgives that size. Asizewithshortest_edgekeeps the aspect ratio, andlongest_edgelimits the long side. Withensure_multiple_of, each side becomes the nearest multiple of it, as in the DPT image processor. Withkeep_aspect_ratio, both sides take the scale ofsizethat is nearer to 1, so the size depends on the image. The DETR, YOLOS and Grounding DINO image processors compute this size with their own rounding, and YOLOS rounds each side down to a multiple of 16. The SAM image processor gives the long sidelongest_edge, also when the image is smaller. The featurizer readsimage_processor_typeand does the same.do_center_crop- the center region ofcrop_sizestays. A configuration withcrop_pct, such as ConvNeXt, resizes the short side toshortest_edge / crop_pctand crops a square ofshortest_edge. Whenshortest_edgeis 384 or more, it resizes to a square ofshortest_edgeand does not crop.do_rescale- the values are multiplied byrescale_factor.do_normalize- the values are normalized withimage_meanandimage_std.do_padof the SAM image processor - zeros on the bottom and the right give the image thepad_size, 1024x1024 by default.
The OWLv2 image processor (Owlv2ImageProcessor) does the steps in another order, and the featurizer reads image_processor_type and does the same. It rescales the image, pads it to a square on the bottom and the right with the value 0.5 (do_pad), resizes it with the :gaussian_linear method of resize/4, and normalizes it.
The Swin2SR image processor (Swin2SRImageProcessor) only rescales and pads. With do_pad, the bottom and the right get the "symmetric" padding of numpy (the edge pixel repeats: a b c | c b a) to the next multiple of size_divisor (pad_size in older configurations). As in Python transformers, a side that is already a multiple gets size_divisor more pixels.
The result has the shape {batch, channels, height, width} and the type :f32.
Summary
Functions
Loads the featurizer of a Transmuter.Repo or of a source ({:hf, repo} or a local directory) from its preprocessor_config.json.
Builds a featurizer from the map of a preprocessor_config.json.
Turns a list of images into one tensor of shape {batch, channels, height, width} and type :f32. The images must give the same size.
Resizes an image of shape {height, width, channels} to {height, width} as Image.resize/2 of Pillow.
Converts an image of shape {height, width, channels} to 3 channels, as Image.convert("RGB") of Pillow. A gray image repeats its channel, and the alpha channel is removed.
Returns the {height, width} of the images that process/2 gives, or nil when the size depends on the image, for example with shortest_edge and no crop.
Returns {:ok, tensor} for an image, a StbImage struct or a tensor of shape {height, width, channels}. Returns {:error, message} for other values.
Functions
Returns the {height, width} of the image in the result of process/2 for an image of size {height, width}. A pad_size (as in SAM) adds padding on the bottom and the right after this size, and size/1 gives the size with the padding.
Loads the featurizer of a Transmuter.Repo or of a source ({:hf, repo} or a local directory) from its preprocessor_config.json.
Options go to Transmuter.Repo.load!/2 when the argument is a source.
Builds a featurizer from the map of a preprocessor_config.json.
An older configuration names a feature_extractor_type, such as ViTFeatureExtractor, in place of an image_processor_type. As AutoImageProcessor of Python transformers, the featurizer reads it as the image processor of the same name, such as ViTImageProcessor.
Turns a list of images into one tensor of shape {batch, channels, height, width} and type :f32. The images must give the same size.
Options
:backend- the backend that does the steps, such asEMLX.Backend. The default is the backend of each image. The resize is slow onNx.BinaryBackend.
Resizes an image of shape {height, width, channels} to {height, width} as Image.resize/2 of Pillow.
method is :nearest, :box, :bilinear, :hamming, :bicubic or :lanczos. The filters other than :nearest widen when the image gets smaller, so they also remove aliasing. The width changes first and the height second.
A :u8 image gives a :u8 image. As in Pillow, the weights are fixed-point numbers with 22 fraction bits, and each pass rounds to :u8. An image of another type is resized in :f32.
weights is :pillow, the default, or :torchvision, which the featurizer uses for the fast image processors of Python transformers (an image_processor_type that ends in Fast). On Apple silicon and on x86 with AVX2, torchvision resizes a :u8 image with the filters and the taps of Pillow, but its weights are 16-bit integers. So for :bilinear, :bicubic and :lanczos, the weights of an axis get the most fraction bits, up to 22, that keep the largest weight as an integer below 2^15. With fewer bits, a pixel can be one step away from Pillow when the image gets smaller. The other methods and the images of other types resize as with :pillow.
:gaussian_linear is the resize of the OWLv2 image processor of Python transformers, which is skimage.transform.resize with anti-aliasing. On each axis, a gaussian blur with sigma max(0, (scale - 1) / 2) comes first, where scale is the input size divided by the output size. Then a linear interpolation between the pixel centers gives the output. Both steps reflect the image at its edges, as the "mirror" mode of scipy.ndimage. The result is clipped to the minimum and the maximum of the image.
Converts an image of shape {height, width, channels} to 3 channels, as Image.convert("RGB") of Pillow. A gray image repeats its channel, and the alpha channel is removed.
Returns the {height, width} of the images that process/2 gives, or nil when the size depends on the image, for example with shortest_edge and no crop.
Returns {:ok, tensor} for an image, a StbImage struct or a tensor of shape {height, width, channels}. Returns {:error, message} for other values.