Skip to content

Commit c22ebb3

Browse files
authored
Expose crop op into Python API. (#11546)
1 parent a29cb4b commit c22ebb3

File tree

2 files changed

+108
-0
lines changed

2 files changed

+108
-0
lines changed

python/paddle/fluid/layers/nn.py

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@
9393
'mean_iou',
9494
'relu',
9595
'log',
96+
'crop',
9697
]
9798

9899

@@ -5003,3 +5004,101 @@ def mean_iou(input, label, num_classes):
50035004
},
50045005
attrs={"num_classes": num_classes})
50055006
return out_mean_iou, out_wrong, out_correct
5007+
5008+
5009+
def crop(x, shape=None, offsets=None, name=None):
5010+
"""
5011+
Crop input into output, as specified by offsets and shape.
5012+
5013+
.. code-block:: text
5014+
5015+
* Case 1:
5016+
Given
5017+
X = [[0, 1, 2, 0, 0]
5018+
[0, 3, 4, 0, 0]
5019+
[0, 0, 0, 0, 0]],
5020+
and
5021+
shape = [2, 2],
5022+
offsets = [0, 1],
5023+
output is:
5024+
Out = [[1, 2],
5025+
[3, 4]].
5026+
* Case 2:
5027+
Given
5028+
X = [[0, 1, 2, 5, 0]
5029+
[0, 3, 4, 6, 0]
5030+
[0, 0, 0, 0, 0]],
5031+
and shape is tensor
5032+
shape = [[0, 0, 0]
5033+
[0, 0, 0]]
5034+
and
5035+
offsets = [0, 1],
5036+
5037+
output is:
5038+
Out = [[1, 2, 5],
5039+
[3, 4, 6]].
5040+
5041+
Args:
5042+
x (Variable): The input tensor variable.
5043+
shape (Variable|list/tuple of integer): The output shape is specified
5044+
by `shape`, which can a Variable or a list/tupe of integer.
5045+
If a tensor Variable, it's rank must be the same as `x`. This way
5046+
is suitable for the case that the output shape may be changed each
5047+
iteration. If a list/tupe of integer, it's length must be the same
5048+
as the rank of `x`
5049+
offsets (Variable|list/tuple of integer|None): Specifies the copping
5050+
offsets at each dimension. It can be a Variable or or a list/tupe
5051+
of integer. If a tensor Variable, it's rank must be the same as `x`.
5052+
This way is suitable for the case that the offsets may be changed
5053+
each iteration. If a list/tupe of integer, it's length must be the
5054+
same as the rank of `x`. If None, the offsets are 0 at each
5055+
dimension.
5056+
name(str|None): A name for this layer(optional). If set None, the layer
5057+
will be named automatically.
5058+
5059+
Returns:
5060+
Variable: The cropped tensor variable.
5061+
5062+
Raises:
5063+
ValueError: If shape is not a list, tuple or Variable.
5064+
5065+
Examples:
5066+
5067+
.. code-block:: python
5068+
5069+
x = fluid.layers.data(name="x", shape=[3, 5], dtype="float32")
5070+
y = fluid.layers.data(name="y", shape=[2, 3], dtype="float32")
5071+
crop = fluid.layers.crop(x, shape=y)
5072+
5073+
# or
5074+
z = fluid.layers.data(name="z", shape=[3, 5], dtype="float32")
5075+
crop = fluid.layers.crop(z, shape=[2, 3])
5076+
5077+
"""
5078+
helper = LayerHelper('crop', **locals())
5079+
5080+
if not (isinstance(shape, list) or isinstance(shape, tuple) or \
5081+
isinstance(shape, Variable)):
5082+
raise ValueError("The shape should be a list, tuple or Variable.")
5083+
5084+
if offsets is None:
5085+
offsets = [0] * len(x.shape)
5086+
5087+
out = helper.create_tmp_variable(x.dtype)
5088+
ipts = {'X': x}
5089+
attrs = {}
5090+
if isinstance(shape, Variable):
5091+
ipts['Y'] = shape
5092+
else:
5093+
attrs['shape'] = shape
5094+
if isinstance(offsets, Variable):
5095+
ipts['Offsets'] = offsets
5096+
else:
5097+
attrs['offsets'] = offsets
5098+
5099+
helper.append_op(
5100+
type='crop',
5101+
inputs=ipts,
5102+
outputs={'Out': out},
5103+
attrs=None if len(attrs) == 0 else attrs)
5104+
return out

python/paddle/fluid/tests/unittests/test_layers.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -401,6 +401,15 @@ def test_maxout(self):
401401
self.assertIsNotNone(output)
402402
print(str(program))
403403

404+
def test_maxout(self):
405+
program = Program()
406+
with program_guard(program):
407+
x = layers.data(name='x', shape=[3, 5], dtype="float32")
408+
y = layers.data(name='y', shape=[2, 3], dtype="float32")
409+
output = layers.crop(x, shape=y)
410+
self.assertIsNotNone(output)
411+
print(str(program))
412+
404413

405414
if __name__ == '__main__':
406415
unittest.main()

0 commit comments

Comments
 (0)