-
-
Notifications
You must be signed in to change notification settings - Fork 56.2k
Description
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
On arm64 macOS:
#!/usr/bin/env python3
import cv2
import numpy as np
m = np.array([[ 1888, 1692, 369, 263, 199, 280, 326, 129, 143, 126, 233, 221, 130, 126, 150, 249, 575, 574, 63, 12]], dtype=np.float32)
print(cv2.__version__)
print(m.min(axis=(0, 1)), m.max(axis=(0, 1)))
mn = cv2.normalize(m, None, 0, 1, norm_type=cv2.NORM_MINMAX)
print(mn.min(axis=(0, 1)), mn.max(axis=(0, 1)))
Writes wrong result, small negative min:
% ~/python311/bin/python3 testnorm.py
4.10.0
12.0 1888.0
-2.3283064e-10 1.0
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)