I’m actually not sure about any build it method.
But I use ImageMagick to do something similar. Here’s how I resize/crop them in different ways: https://arunoda.me/blog/getting-started-with-fastai
I’m actually not sure about any build it method.
But I use ImageMagick to do something similar. Here’s how I resize/crop them in different ways: https://arunoda.me/blog/getting-started-with-fastai
I’m interested in this as well.
@arunoda, thanks for the pointer. I looked at your notebook and it looks like you are using “get_transforms()” which looks to me to include crop by default. Are you doing anything special to prevent crop?
@keijik get_transforms()
does not crop AFAIK. Or at least with default params.
It does tilt and some similar transformations.
The cropping is done by the size
param. Since I’m using a square image, no cropping happens with size
param.
Hey,
I too am interested in figuring out if there is any specified method to do so. I ended up changing the code in vision/image.py
in the apply_tfms
function from default cropping when size given to the following
if size:
x.resize(size)
x.refresh()
I am not sure if that is the correct way to do so.
Looking at the code, it seems like the DataBunch constructor will pass through a do_crop
parameter to apply_tfms
which might also do the trick.
I’ll try that.
Just pushed a new version of the lib where @sgugger has added a resize_method
param, which you can pass ResizeMethod.SQUISH
to resize by squishing.
Great - thank you! Amazing how quickly fastai reponds to feedback!
I was in the middle of creating an isolated notebook to show the issue I was having when I saw this :D. I no longer get the exception using resize_method (and no transforms).
Now, with both ResizeMethod.PAD and ResizeMethod.SQUISH I get higher error rates (about 15%) in training compared to manually resize/padding the images with imagemagick (about 4%). I will report if I find what is causing this.
Thank you again!
It does crop by default if you specify a square (or int) size and your source images are not square.
@arunoda, the result of get_transforms()
is below. Based on this and the transformed images, I assumed it does Crop but thanks @jeremy for confirming
([RandTransform(tfm=TfmCrop (crop_pad), kwargs={'row_pct': (0, 1), 'col_pct': (0, 1)}, p=1.0, resolved={}, do_run=True, is_random=True),
RandTransform(tfm=TfmAffine (flip_affine), kwargs={}, p=0.5, resolved={}, do_run=True, is_random=True),
RandTransform(tfm=TfmCoord (symmetric_warp), kwargs={'magnitude': (-0.2, 0.2)}, p=0.75, resolved={}, do_run=True, is_random=True),
RandTransform(tfm=TfmAffine (rotate), kwargs={'degrees': (-10.0, 10.0)}, p=0.75, resolved={}, do_run=True, is_random=True),
RandTransform(tfm=TfmAffine (zoom), kwargs={'row_pct': (0, 1), 'col_pct': (0, 1), 'scale': (1.0, 1.1)}, p=0.75, resolved={}, do_run=True, is_random=True),
RandTransform(tfm=TfmLighting (brightness), kwargs={'change': (0.4, 0.6)}, p=0.75, resolved={}, do_run=True, is_random=True),
RandTransform(tfm=TfmLighting (contrast), kwargs={'scale': (0.8, 1.25)}, p=0.75, resolved={}, do_run=True, is_random=True)],
[RandTransform(tfm=TfmCrop (crop_pad), kwargs={}, p=1.0, resolved={}, do_run=True, is_random=True)])
Thank you for the quick addition of resize_method param. I am looking at the new documentation
For the following image I was expecting pad to place black bars above and below the image and squish to resize ignoring the original aspect ratio.
However all the images look identical to me, am I missing something?
The parameter is what Jeremy said - resize_method
. I checked the code before trying it. Ditto for the enum (ResizeMethod
, not ResizeMtd
).
Perfect, thank you.
Yes, Jeremy changed the name without updating the docs, you can address your complains to him ;);
I’m really new to python so I would appreciate it if someone could walk me though the logic behind the following taken from data.py
def _prep_tfm_kwargs(tfms, kwargs):
default_rsz = ResizeMethod.SQUISH if ('size' in kwargs and is_listy(kwargs['size'])) else ResizeMethod.CROP
resize_method = getattr(kwargs, 'resize_method', default_rsz)
if resize_method <= 2: tfms = [crop_pad()] + tfms
kwargs['resize_method'] = resize_method
return tfms, kwargs
Specifically the first two statements. Is it possible for the below to return anything but default_rsz?
getattr(kwargs, 'resize_method', default_rsz)
If not what is the reason that the size argument to _prep_tfm_kwargs have to be a list or a tuple to use the ResizeMethod.SQUISH?
Thank you.
It’s assuming that if it’s a list [u, v]
, that u != v
- i.e., if it’s square, people should not bother to make a list [u,u]
but instead just pass u
.
And that sets the default - which can be overridden by what people pass in explicitly as resize_method
.
Hope that helps!
Thank you, just to confirm, if size is not a list will the below default to ResizeMethod.CROP?
default_rsz = ResizeMethod.SQUISH if ('size' in kwargs and is_listy(kwargs['size'])) else ResizeMethod.CROP
And you are saying that
getattr(kwargs, 'resize_method', default_rsz)
can get the value for the ‘resize_method’ keyword from kwargs even though kwargs it is not an object?
I ask because in my testing this is not the case.
getattr
works fine with dictionaries, and kwargs
is one. What this does is, it tries to get kwargs['resize_method']
but it if doesn’t exists, it uses default_rsz
. A longer way to rewrite it would be
resize_method = kwargs['resize_method'] if 'resize_method' in kwargs else default_rsz
Thank you for clarifying. I think I must have something wrong with either my config or my understanding, because for me getattr does not appear to be working on dictionaries, the output from the following
testDict = {'key1':1,'key2':2}
print(type(testDict))
print(testDict.get('key1'))
print(getattr(testDict,'key1','notakey'))
is
< class 'dict'>
1
notakey
and as you have pointed out the last 2 lines should be the same.
See! You know more python than I do
I wanted to do kwargs.get('resize_method', default_rsz)
and got mixed up, sorry about that. Will fix.
I wish, I been trying to get up to speed quickly by following https://learnxinyminutes.com/docs/python3/.