Torchvision crop#6353
Conversation
Signed-off-by: Marek Dabek <mdabek@nvidia.com>
Signed-off-by: Marek Dabek <mdabek@nvidia.com>
Signed-off-by: Marek Dabek <mdabek@nvidia.com>
Signed-off-by: Marek Dabek <mdabek@nvidia.com>
Signed-off-by: Marek Dabek <mdabek@nvidia.com>
|
@greptileai please review |
|
| Filename | Overview |
|---|---|
| dali/python/nvidia/dali/experimental/torchvision/v2/randomcrop.py | New RandomCrop operator with random offset computation, padding support, and fill validation — contains a misleading error message that lists dict as a valid fill type after dict support was commented out, plus TODO/commented-out code in a docstring. |
| dali/python/nvidia/dali/experimental/torchvision/v2/functional/crop.py | New functional crop API using ndd.slice with layout-aware axis detection; reuses RandomCrop.verify_args for size/coordinate validation. Logic is sound. |
| dali/test/python/torchvision/test_tv_randomcrop.py | Comprehensive test suite covering identity, padding, asymmetric padding, shape, and error-rejection cases; two # TODO comments for skipped dict-fill tests violate doc-no-todo-on-merge. |
| dali/test/python/torchvision/test_tv_crop.py | Tests for functional crop covering tensors, PIL images, batches, dtype preservation, and error cases across CPU/GPU; correctness validated against torchvision reference. |
| dali/python/nvidia/dali/experimental/torchvision/init.py | Exports RandomCrop and crop in the public API; trivial change, no issues. |
| dali/python/nvidia/dali/experimental/torchvision/v2/functional/init.py | Adds crop to the functional module's public __all__; trivial, no issues. |
Sequence Diagram
sequenceDiagram
participant User
participant RandomCrop
participant _ValidateFill
participant fn_slice as fn.slice
User->>RandomCrop: __init__(size, padding, fill, ...)
RandomCrop->>_ValidateFill: "verify(fill=fill)"
Note over _ValidateFill: _verify_fill_value(fill)<br/>rejects dicts but error<br/>message says dict is valid
RandomCrop->>RandomCrop: adjust_fill(fill)
RandomCrop->>RandomCrop: adjust_padding(padding)
User->>RandomCrop: __call__(image)
RandomCrop->>RandomCrop: _kernel(in_h, in_w, c, tensor)
Note over RandomCrop: compute padded_h/w,<br/>pad_if_needed adjustment
RandomCrop->>RandomCrop: _randint(max_top) → top
RandomCrop->>RandomCrop: _randint(max_left) → left
RandomCrop->>fn_slice: "fn.slice(tensor, anchor, shape, axis_names=WH)"
fn_slice-->>User: cropped tensor
User->>crop: crop(inpt, top, left, height, width)
crop->>crop: _verify_crop_coordinate(top/left)
crop->>RandomCrop: "verify_args(size=(height,width), ...)"
crop->>ndd_slice: "ndd.slice(inpt, axes=_get_crop_axes(inpt))"
ndd_slice-->>User: cropped output
Reviews (5): Last reviewed commit: "Review comments" | Re-trigger Greptile
Signed-off-by: Marek Dabek <mdabek@nvidia.com>
|
@greptileai re-review please |
Signed-off-by: Marek Dabek <mdabek@nvidia.com>
3414c38 to
fdb1565
Compare
Signed-off-by: Marek Dabek <mdabek@nvidia.com>
fdb1565 to
12dddd3
Compare
| self.pad_if_needed = pad_if_needed | ||
| self.fill = RandomCrop.adjust_fill(fill) | ||
| self.padding_mode = padding_mode | ||
| self.needs_padding = pad_if_needed or any(self.padding) |
There was a problem hiding this comment.
[Question] needs_padding = pad_if_needed or any(self.padding) — when pad_if_needed=True but the input is already large enough, pad_h = pad_w = 0 and the fn.slice block (lines 229-240) becomes an effective no-op that still runs in the graph (start=0, size=in_w/in_h). Worth a comment confirming that's intentional / cheap enough, or short-circuiting at graph construction time when both any(self.padding) == False and we don't actually need extra padding? Not blocking — just want to flag the extra graph node for large-input/pad_if_needed=True callers.
There was a problem hiding this comment.
Added checking if padding is needed
Signed-off-by: Marek Dabek <mdabek@nvidia.com>
|
@greptileai, re-review |
| raise TypeError(f"fill must be a number, sequence of numbers, None or a dict, got {fill!r}") | ||
|
|
||
| @classmethod | ||
| def verify(cls, *, fill, **_) -> None: | ||
| """ | ||
| TODO: Fill using dictionary pattern is currently not supported | ||
| if isinstance(fill, dict): | ||
| for key, value in fill.items(): | ||
| if not isinstance(key, (type, str)): | ||
| raise TypeError(f"fill dictionary keys must be types or strings, got {key!r}") | ||
| cls._verify_fill_value(value) | ||
| else: | ||
| cls._verify_fill_value(fill) | ||
| """ | ||
| cls._verify_fill_value(fill) |
There was a problem hiding this comment.
[Bug]
_verify_fill_value error message falsely lists dict as a valid fill type
The error message on line 86 says "fill must be a number, sequence of numbers, None or a dict", but dict is not handled by _verify_fill_value and falls through to this same raise — so a user who passes fill={torch.Tensor: 9} (which matches the __init__ type annotation) gets TypeError: fill must be a number, sequence of numbers, None or a dict and then tries a dict again, stuck in a loop. The "or a dict" fragment is a leftover from when dict support was enabled; now that it's commented out, the message should be corrected to remove it.
Category:
New feature
Description:
Torchvision API operators RandomCrop and functional crop.
Unit tests checking conformance with Torchvision.
Known limitations: tensor and PIL.Image based paddings are not supported
Additional information:
Affected modules and functionalities:
Key points relevant for the review:
Tests:
Checklist
Documentation
DALI team only
Requirements
REQ IDs: N/A
JIRA TASK: N/A