Skip to content
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 #26588

Open
3 of 4 tasks
isenberg opened this issue Dec 7, 2024 · 1 comment
Open
3 of 4 tasks

Comments

@isenberg
Copy link

isenberg commented Dec 7, 2024

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.

print(cv2.__version__)
print(img.min(axis=(0, 1)), img.max(axis=(0, 1)))
img1 = cv2.normalize(img, None, 0, 1, norm_type=cv2.NORM_MINMAX)
img2 = img / max(img.max(axis=(0, 1)))
print(img1.min(axis=(0, 1)), img1.max(axis=(0, 1)))
print(img2.min(axis=(0, 1)), img2.max(axis=(0, 1)))

4.10.0
[0.02032561 0.04122998 0.04707103] [0.6832291  0.98649204 0.9428176 ]
[-1.0251444e-10  2.1636410e-02  2.7682003e-02] [0.68611723 0.99999994 0.95479614]
[0.02060392 0.04179454 0.04771557] [0.6925845 1.        0.9557276]

If needed I guess I would be able to attach a reproducer input image and code.

Steps to reproduce

print(cv2.__version__)
print(img.min(axis=(0, 1)), img.max(axis=(0, 1)))
img1 = cv2.normalize(img, None, 0, 1, norm_type=cv2.NORM_MINMAX)
img2 = img / max(img.max(axis=(0, 1)))
print(img1.min(axis=(0, 1)), img1.max(axis=(0, 1)))
print(img2.min(axis=(0, 1)), img2.max(axis=(0, 1)))

Issue submission checklist

  • I report the issue, it's not a question
  • I checked the problem with documentation, FAQ, open issues, forum.opencv.org, Stack Overflow, etc and have not found any solution
  • I updated to the latest OpenCV version and the issue is still there
  • There is reproducer code and related data files (videos, images, onnx, etc)
@AliHaroonT
Copy link

Any update regarding this? I'm also facing same issue.
Right now I'm manually normalizing the pixel values using the solution mentioned here (https://stackoverflow.com/questions/29100722/equivalent-im2double-function-in-opencv-python)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants