-
-
Notifications
You must be signed in to change notification settings - Fork 55.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
cv2.normalize with NORM_MINMAX produces small values below set minimum on float32 #26588
Comments
Any update regarding this? I'm also facing same issue. |
Not sure if useful, but this seems to work fine on Windows. |
Still produces the wrong results on arm64 macOS when using float 32. Reproducer:
Result is small negative which is wrong:
|
Confirmed reproducer triggers a problem on Windows as well. |
I was able to reproduce it in the C++ code
test_arithm.cpp(2228): error: Expected equality of these values: |
I've traced the problem to the following line
Changing the code to this:
Not rounding this yields |
The line scale = (float)scale indeed doesn't look like making sense as smin is a double and in the next line the result is rounded anyway. |
Added a small PR for this: |
I've created some code to find the smallest fit within the boundaries. It appears tests are failing because it expects:
expect_max evaluates to 100, If I'm not mistaking this means it allows to be outside of the interval. I hope an active contributor with more context can pitch in and decide what is most important: |
That's too much change now and could cause the performance problems again the first try years ago caused which lead to being it reverted. What about just clamping the result to the min value if it exceeds it? I.e. just adding something like this after shift = dmin - smin*scale; if (shift < dmin) |
Ah I see the problem, the actual calculation is done in convertTo and not in the function where the current changes apply. Then the performance change risk is low. |
I'm just a contributor but given the central nature of the function and that the tests suggests this is know: Avoid breaking changes by introducing a new mode? e.g. NORM_MINMAX_CLAMP or such? It isn't strictly a beautiful solution but it avoids red lamps (that expect a certain behaviour) from lighting up over the planet :) |
If you are a code contributor to opencv: Do you have a practical example where the current wrong (by the function documentation) behavior is expected or required? I couldn't think of any except for intentionally having those bugs to train people to be aware that third party code can have bugs which skipped years of usage. |
Any code that is using it. As you can see that behavior seems to be known (see the tests) and changes to such a central function are delicate. This is probably not the answer you seek but easily thousands of projects depend on it and might break or at least change behavior unexpectedly. Anyway it's a good catch and by creating this issue alone you are helping lots of people! |
I haven't checked the existing test code yet, but if the test code "knows" about the bug, that would be really interesting. I'll look into it later and if I find a hint let's add add it here. |
Btw, I found it as I process images in float32 and there the small negative number inverts the colorchannel which makes it immediately visible. |
I ment this. |
I don't see a hint that this test code expected to see numbers outside of min-max range. I only see some fuzziness expected in the results for the many different norms tested. If someone uses the norm min-max in code they expect that no results appear outside of that range because that's one of the main purposes of using this norm. Also: In the previous two bug reports about this I linked to in my initial posting, all discussions there appear to to accept that this bug needs to be fixed, just the solution back then was not optimal regarding performance. |
ic :) |
System Information
OpenCV python version: 4.10.0
Operating System / Platform: macOS 15.1.1 arm64 M2
Python version: 3.9.6 (/usr/bin/python3 provided by macOS)
Detailed description
The following code shows unexpected small negative numbers when trying to normalize an image between 0 and 1 while a comparison, which is mathematically not exactly the same, works fine. Note: The comparison img1 is keeping the offset from 0, I just used it for a quick check.
This appears to be the same as #6125 and #6170 which apparently has been fixed once in dev but then has been everted due to performance impacts.
This bug, if I don't have a misunderstanding of the OpenCV NORM_MINMAX definition, is serious as even small negative numbers can lead to critical follow up errors. For safety one can of course follow it with a img = np.clip(img, 0, 1) which is advised anyway for critical applications, but the result is mathematically slightly wrong.
If the performance impact can still be seen today with a fix, then I suggest to add at least internally a clip.
Datatype of img is np.float32. Changing to np.double like suggested in the older bug doesn't change anything.
If needed I guess I would be able to attach a reproducer input image and code.
Steps to reproduce
On arm64 macOS:
Writes wrong result, small negative min:
Issue submission checklist
The text was updated successfully, but these errors were encountered: