Skip to content

cv2.normalize with NORM_MINMAX produces small values below set minimum on float32 #26588

@isenberg

Description

@isenberg

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)

Metadata

Metadata

Labels

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions

    pFad - Phonifier reborn

    Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

    Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


    Alternative Proxies:

    Alternative Proxy

    pFad Proxy

    pFad v3 Proxy

    pFad v4 Proxy