Added nearest-exact interpolation mode#64501
Added nearest-exact interpolation mode#64501vfdev-5 wants to merge 21 commits intopytorch:masterfrom
Conversation
…v-5/fix-nearest-upsampling
- updated index computation formula to match scikit-image/scipy Fixes pytorch#34808, pytorch#62237
🔗 Helpful links
💊 CI failures summary and remediationsAs of commit a612bb1 (more details on the Dr. CI page): 💚 💚 Looks good so far! There are no failures yet. 💚 💚 This comment was automatically generated by Dr. CI (expand for details).Please report bugs/suggestions to the (internal) Dr. CI Users group. |
|
FYI I just noticed that opencv already fixed the issue with a new interpolation mode: opencv/opencv#18053 |
@ppwwyyxx I have an impression that it gives other results and not always matches PIL or Scikit-Image (which not always match neither). import numpy as np
from PIL import Image
import cv2
from skimage.transform import resize
size = 10
a_in = np.arange(0, 3 * 32 * 32, dtype="uint8").reshape(32, 32, 3)
pil_in = Image.fromarray(a_in)
pil_out = pil_in.resize((size, size), resample=Image.NEAREST)
a_pil_out = np.array(pil_out)
a_cv2_out = cv2.resize(a_in, dsize=(size, size), interpolation=cv2.INTER_NEAREST_EXACT)
a_skimg_out = resize(a_in, (size, size), order=0, preserve_range=True, anti_aliasing=False).astype("uint8")
print(np.allclose(a_cv2_out, a_pil_out), np.mean(np.abs(a_cv2_out - a_pil_out)))
# > (False, 38.74)
print(np.allclose(a_cv2_out, a_skimg_out), np.mean(np.abs(a_cv2_out - a_skimg_out)))
# > (False, 25.3) |
fmassa
left a comment
There was a problem hiding this comment.
Changes LGTM, thanks!
But due to BC-breakages on the numerics of the function, I'll defer to @jbschlosser to decide how to handle this.
|
@vfdev-5 From what I can tell the difference is only due to half-rounding: when a sample fall into the middle point between two pixels, it's ambiguous which pixel is its nearest neighbor, and then different implementations make different choices. The below script verify that for all (input_size, output_size) in (1, 100), all the differences between cv2(NEAREST_EXACT), PIL and skimage are due to the above reason. In other words, these three libraries are in full agreement except for this unavoidable ambiguity of nearest neighbor resize. Please also test this against your PR if possible. |
|
Thanks @ppwwyyxx for pointing out that. Yes, you are right, I see what you mean. I think more precisely the point is about isize = 32
size = 10
scale = 1.0 * isize / size
for o in range(size):
i_f32 = (o + 0.5) * scale
i = int(i_f32)
print(o, " <- ", i, i_f32)
>
0 <- 1 1.6
1 <- 4 4.800000000000001
2 <- 8 8.0
3 <- 11 11.200000000000001
4 <- 14 14.4
5 <- 17 17.6
6 <- 20 20.8
7 <- 24 24.0
8 <- 27 27.200000000000003
9 <- 30 30.400000000000002
a_in = np.arange(0, isize, dtype="float32")[:, None]
pil_in = Image.fromarray(a_in)
pil_out = pil_in.resize((1, size), resample=Image.NEAREST)
a_pil_out = np.array(pil_out)
a_cv2_out = cv2.resize(a_in, dsize=(1, size), interpolation=cv2.INTER_NEAREST_EXACT)
a_skimg_out = resize(a_in, (size, 1), order=0, preserve_range=True, anti_aliasing=False).astype(a_in.dtype)
print("PIL", "SKI", "CV")
print(a_pil_out[:, 0])
print(a_skimg_out[:, 0])
print(a_cv2_out[:, 0])
>
PIL SKI CV
[ 1. 4. 8. 11. 14. 17. 20. 23. 27. 30.]
[ 1. 4. 8. 11. 14. 17. 20. 24. 27. 30.]
[ 1. 4. 7. 11. 14. 17. 20. 23. 27. 30.] |
jbschlosser
left a comment
There was a problem hiding this comment.
But due to BC-breakages on the numerics of the function, I'll defer to @jbschlosser to decide how to handle this.
I'm wary of making this change all at once, since it would certainly require model retraining to avoid performance metric regressions from preprocessing / trained model mismatch.
opencv already fixed the issue with a new interpolation mode: opencv/opencv#18053
I think the way to go here is to follow suit and add a new interpolation mode as well to maintain BC. It's unfortunate but I don't see a way around it while still avoiding lots of painful breakage.
|
Thanks for your comment @jbschlosser !
Seems reasonable. For example, new mode can be called "nearest-exact" or something similar. Maybe, we can keep both "nearest" and "nearest-exact" in v1.X and remove "nearest-exact", keep "nearest" and replace buggy code for v2.X (as TF did according to https://ppwwyyxx.com/blog/2021/Where-are-Pixels/#Libraries) Any better suggestions for the mode name, e.g "nearest-exact" ? |
…v-5/fix-nearest-upsampling
- upsample_nearest_exact1d
|
I'm not so sure why opencv chooses to call it "Bit-Exact". From opencv/opencv#18053 (comment) it appears it means "it produces bitwise identical output regardless of platform". If that's what the name means that doesn't sound like what we're looking for. |
CI Flow Status⚛️ CI FlowRuleset - Version:
You can add a comment to the PR and tag @pytorchbot with the following commands: # ciflow rerun, "ciflow/default" will always be added automatically
@pytorchbot ciflow rerun
# ciflow rerun with additional labels "-l <ciflow/label_name>", which is equivalent to adding these labels manually and trigger the rerun
@pytorchbot ciflow rerun -l ciflow/scheduled -l ciflow/slowFor more information, please take a look at the CI Flow Wiki. |
|
@jbschlosser I updated the PR according to your previous recommendations: a) separate private ops doing the nearest exact interpolation and b) added work around for JIT FC. Could you please review the PR. Thanks! |
jbschlosser
left a comment
There was a problem hiding this comment.
Looking pretty good, just a minor script-gating thing :)
CI Flow Status⚛️ CI FlowRuleset - Version:
You can add a comment to the PR and tag @pytorchbot with the following commands: # ciflow rerun, "ciflow/default" will always be added automatically
@pytorchbot ciflow rerun
# ciflow rerun with additional labels "-l <ciflow/label_name>", which is equivalent to adding these labels manually and trigger the rerun
@pytorchbot ciflow rerun -l ciflow/scheduled -l ciflow/slowFor more information, please take a look at the CI Flow Wiki. |
…v-5/fix-nearest-upsampling
CI Flow Status⚛️ CI FlowRuleset - Version:
You can add a comment to the PR and tag @pytorchbot with the following commands: # ciflow rerun, "ciflow/default" will always be added automatically
@pytorchbot ciflow rerun
# ciflow rerun with additional labels "-l <ciflow/label_name>", which is equivalent to adding these labels manually and trigger the rerun
@pytorchbot ciflow rerun -l ciflow/scheduled -l ciflow/slowFor more information, please take a look at the CI Flow Wiki. |
jbschlosser
left a comment
There was a problem hiding this comment.
Looks good on my end!
|
@jbschlosser has imported this pull request. If you are a Facebook employee, you can view this diff on Phabricator. |
|
@jbschlosser merged this pull request in 6adbe04. |
Description: Following pytorch#65142 (comment) adding missing nearest-exact mode and anti-alias flag - pytorch#65142 - pytorch#64501 cc @cpuhrsch
Summary: Description: Following #65142 (comment) adding missing nearest-exact mode and anti-alias flag to C++ frontend. - #65142 - #64501 - added tests in pytorch/test/cpp/api/functional.cpp Pull Request resolved: #69318 Reviewed By: davidberard98 Differential Revision: D33278995 Pulled By: jbschlosser fbshipit-source-id: fa87c0c78df6b398e4f9688cc02111eed187afa7
Summary: Description: - Removed JIT FC tweaks for interpolation options : nearest-exact and antialiasing They were added in - #64501 (Sept 04 2021) - #65142 (Sept 16 2021) cc jbschlosser Pull Request resolved: #71937 Reviewed By: mrshenli Differential Revision: D33845502 Pulled By: jbschlosser fbshipit-source-id: 8a94454fd643cd2aef21b06689f72a0f16620d30
Summary: Description: - Removed JIT FC tweaks for interpolation options : nearest-exact and antialiasing They were added in - #64501 (Sept 04 2021) - #65142 (Sept 16 2021) cc jbschlosser Pull Request resolved: #71937 Reviewed By: mrshenli Differential Revision: D33845502 Pulled By: jbschlosser fbshipit-source-id: 8a94454fd643cd2aef21b06689f72a0f16620d30 (cherry picked from commit b21173d)
Summary: Description: - Removed JIT FC tweaks for interpolation options : nearest-exact and antialiasing They were added in - pytorch/pytorch#64501 (Sept 04 2021) - pytorch/pytorch#65142 (Sept 16 2021) cc jbschlosser Pull Request resolved: pytorch/pytorch#71937 Reviewed By: mrshenli Differential Revision: D33845502 Pulled By: jbschlosser fbshipit-source-id: 8a94454fd643cd2aef21b06689f72a0f16620d30 (cherry picked from commit b21173d)
Summary: Description: - Removed JIT FC tweaks for interpolation options : nearest-exact and antialiasing They were added in - pytorch/pytorch#64501 (Sept 04 2021) - pytorch/pytorch#65142 (Sept 16 2021) cc jbschlosser Pull Request resolved: pytorch/pytorch#71937 Reviewed By: mrshenli Differential Revision: D33845502 Pulled By: jbschlosser fbshipit-source-id: 8a94454fd643cd2aef21b06689f72a0f16620d30 (cherry picked from commit b21173d)
Summary: Description: - Removed JIT FC tweaks for interpolation options : nearest-exact and antialiasing They were added in - pytorch/pytorch#64501 (Sept 04 2021) - pytorch/pytorch#65142 (Sept 16 2021) cc jbschlosser Pull Request resolved: pytorch/pytorch#71937 Reviewed By: mrshenli Differential Revision: D33845502 Pulled By: jbschlosser fbshipit-source-id: 8a94454fd643cd2aef21b06689f72a0f16620d30 (cherry picked from commit b21173d)
Summary: Description: - Removed JIT FC tweaks for interpolation options : nearest-exact and antialiasing They were added in - pytorch/pytorch#64501 (Sept 04 2021) - pytorch/pytorch#65142 (Sept 16 2021) cc jbschlosser Pull Request resolved: pytorch/pytorch#71937 Reviewed By: mrshenli Differential Revision: D33845502 Pulled By: jbschlosser fbshipit-source-id: 8a94454fd643cd2aef21b06689f72a0f16620d30 (cherry picked from commit b21173d)
Added "nearest-exact" interpolation mode to fix the issues: #34808 and #62237.
Description:
As we can not fix "nearest" mode without large impact on already trained model it was suggested to introduce new mode instead of fixing exising "nearest" mode.
"nearest":
"nearest-exact"
Comparisions with other libs: https://gist.github.com/vfdev-5/a5bd5b1477b1c82a87a0f9e25c727664
Versions:
Implementations in other libs:
Pillow:
a[2] == 0Scikit-Image :
Additionally:
cc @ezyang @gchanan @albanD @mruberry @jbschlosser @walterddr @fmassa @heitorschueroff @ppwwyyxx